diff --git a/acceptance/handle_config_file_test.go b/acceptance/handle_config_file_test.go index 21cad67b..4216190a 100644 --- a/acceptance/handle_config_file_test.go +++ b/acceptance/handle_config_file_test.go @@ -102,7 +102,7 @@ username123: username Expect(err).ToNot(HaveOccurred()) Eventually(session, "5s").Should(gexec.Exit(1)) - Expect(session.Err.Contents()).To(ContainSubstring("unknown flag `username123'")) + Expect(session.Err.Contents()).To(ContainSubstring("unknown flag(s) [\"--username123\"]")) }) }) diff --git a/acceptance/upload_product_test.go b/acceptance/upload_product_test.go index 27d86786..63c87ec3 100644 --- a/acceptance/upload_product_test.go +++ b/acceptance/upload_product_test.go @@ -2,6 +2,7 @@ package acceptance import ( "archive/zip" + "fmt" "io" "net/http" "os" @@ -13,6 +14,8 @@ import ( "github.com/onsi/gomega/gbytes" "github.com/onsi/gomega/gexec" "github.com/onsi/gomega/ghttp" + "github.com/pivotal-cf/om/extractor" + "github.com/pivotal-cf/om/validator" ) var _ = Describe("upload-product command", func() { @@ -176,4 +179,212 @@ name: some-product`) }) }) + When("validating command flags", func() { + var actualShasum string + var actualVersion string + var configFile *os.File + var varsFile1 *os.File + var varsFile2 *os.File + + BeforeEach(func() { + // Calculate the actual shasum of the test file + shaValidator := validator.NewSHA256Calculator() + var err error + actualShasum, err = shaValidator.Checksum(productFile.Name()) + Expect(err).ToNot(HaveOccurred()) + + // Get the actual version from the test file + metadataExtractor := extractor.NewMetadataExtractor() + metadata, err := metadataExtractor.ExtractFromFile(productFile.Name()) + Expect(err).ToNot(HaveOccurred()) + actualVersion = metadata.Version + + // Create temporary config file + configFile, err = os.CreateTemp("", "config.yml") + Expect(err).ToNot(HaveOccurred()) + _, err = configFile.WriteString("product: ((product_path))\npolling-interval: ((interval))") + Expect(err).ToNot(HaveOccurred()) + Expect(configFile.Close()).To(Succeed()) + + // Create temporary vars files + varsFile1, err = os.CreateTemp("", "vars1.yml") + Expect(err).ToNot(HaveOccurred()) + _, err = varsFile1.WriteString(fmt.Sprintf("product_path: %s\ninterval: \"5\"", productFile.Name())) + Expect(err).ToNot(HaveOccurred()) + Expect(varsFile1.Close()).To(Succeed()) + + varsFile2, err = os.CreateTemp("", "vars2.yml") + Expect(err).ToNot(HaveOccurred()) + _, err = varsFile2.WriteString("additional_var: value") + Expect(err).ToNot(HaveOccurred()) + Expect(varsFile2.Close()).To(Succeed()) + + // Add handler for product upload + server.AppendHandlers( + ghttp.CombineHandlers( + ghttp.VerifyRequest("POST", "/api/v0/available_products"), + http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + err := req.ParseMultipartForm(100) + Expect(err).ToNot(HaveOccurred()) + + requestFileName := req.MultipartForm.File["product[file]"][0].Filename + Expect(requestFileName).To(Equal(filepath.Base(productFile.Name()))) + + w.WriteHeader(http.StatusOK) + _, err = w.Write([]byte(`{}`)) + Expect(err).ToNot(HaveOccurred()) + }), + ), + ) + }) + + AfterEach(func() { + os.Remove(configFile.Name()) + os.Remove(varsFile1.Name()) + os.Remove(varsFile2.Name()) + }) + + It("accepts valid flags", func() { + command := exec.Command(pathToMain, + "--target", server.URL(), + "--username", "some-username", + "--password", "some-password", + "--skip-ssl-validation", + "upload-product", + "--product", productFile.Name(), + "--polling-interval", "5", + "--shasum", actualShasum, + "--product-version", actualVersion, + ) + + session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) + Expect(err).ToNot(HaveOccurred()) + Eventually(session, 5).Should(gexec.Exit(0)) + }) + + It("accepts valid short flags", func() { + command := exec.Command(pathToMain, + "--target", server.URL(), + "--username", "some-username", + "--password", "some-password", + "--skip-ssl-validation", + "upload-product", + "-p", productFile.Name(), + "-i", "5", + ) + + session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) + Expect(err).ToNot(HaveOccurred()) + Eventually(session, 5).Should(gexec.Exit(0)) + }) + + It("accepts all config interpolation flags", func() { + command := exec.Command(pathToMain, + "--target", server.URL(), + "--username", "some-username", + "--password", "some-password", + "--skip-ssl-validation", + "upload-product", + "-c", configFile.Name(), + "--vars-env", "MY", + "-l", varsFile1.Name(), + "-l", varsFile2.Name(), + "-v", "FOO=bar", + "-v", "BAZ=qux", + "-p", productFile.Name(), + ) + + session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) + Expect(err).ToNot(HaveOccurred()) + Eventually(session, 5).Should(gexec.Exit(0)) + }) + + It("accepts mix of config and main flags", func() { + command := exec.Command(pathToMain, + "--target", server.URL(), + "--username", "some-username", + "--password", "some-password", + "--skip-ssl-validation", + "upload-product", + "-p", productFile.Name(), + "-c", configFile.Name(), + "--vars-env", "MY", + "--shasum", actualShasum, + "-l", varsFile1.Name(), + "-v", "FOO=bar", + ) + + session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) + Expect(err).ToNot(HaveOccurred()) + Eventually(session, 5).Should(gexec.Exit(0)) + }) + + It("rejects unknown flags", func() { + command := exec.Command(pathToMain, + "--target", server.URL(), + "--username", "some-username", + "--password", "some-password", + "--skip-ssl-validation", + "upload-product", + "-p", productFile.Name(), + "--notaflag", + ) + + session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) + Expect(err).ToNot(HaveOccurred()) + Eventually(session, 5).Should(gexec.Exit(1)) + Eventually(session.Err).Should(gbytes.Say("Error: unknown flag\\(s\\) \\[\"--notaflag\"\\] for command 'upload-product'")) + }) + + It("rejects multiple unknown flags", func() { + command := exec.Command(pathToMain, + "--target", server.URL(), + "--username", "some-username", + "--password", "some-password", + "--skip-ssl-validation", + "upload-product", + "--foo", + "--bar", + ) + + session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) + Expect(err).ToNot(HaveOccurred()) + Eventually(session, 5).Should(gexec.Exit(1)) + Eventually(session.Err).Should(gbytes.Say("Error: unknown flag\\(s\\) \\[\"--foo\" \"--bar\"\\] for command 'upload-product'")) + }) + + It("rejects unknown short flags", func() { + command := exec.Command(pathToMain, + "--target", server.URL(), + "--username", "some-username", + "--password", "some-password", + "--skip-ssl-validation", + "upload-product", + "-p", productFile.Name(), + "-x", "18000", + ) + + session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) + Expect(err).ToNot(HaveOccurred()) + Eventually(session, 5).Should(gexec.Exit(1)) + Eventually(session.Err).Should(gbytes.Say("Error: unknown flag\\(s\\) \\[\"-x\"\\] for command 'upload-product'")) + }) + + It("rejects another unknown short flag", func() { + command := exec.Command(pathToMain, + "--target", server.URL(), + "--username", "some-username", + "--password", "some-password", + "--skip-ssl-validation", + "upload-product", + "-p", productFile.Name(), + "-z", "18000", + ) + + session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) + Expect(err).ToNot(HaveOccurred()) + Eventually(session, 5).Should(gexec.Exit(1)) + Eventually(session.Err).Should(gbytes.Say("Error: unknown flag\\(s\\) \\[\"-z\"\\] for command 'upload-product'")) + }) + }) }) diff --git a/cmd/loadConfigFile_test.go b/cmd/loadConfigFile_test.go index 142fb561..667fb5aa 100644 --- a/cmd/loadConfigFile_test.go +++ b/cmd/loadConfigFile_test.go @@ -1,8 +1,6 @@ package cmd import ( - "testing" - . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) @@ -22,8 +20,3 @@ var _ = Describe("parseOptions", func() { }) }) - -func TestCmds(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Cmds") -} diff --git a/cmd/main.go b/cmd/main.go index 3e643e34..d66f7720 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -659,11 +659,14 @@ func Main(sout io.Writer, serr io.Writer, version string, applySleepDurationStri return err } - parser.Options |= flags.HelpFlag - - _, err = parser.ParseArgs(args) - + // Strict flag validation block + err = validateCommandFlags(parser, args) if err != nil { + return err + } + + parser.Options |= flags.HelpFlag + if _, err = parser.ParseArgs(args); err != nil { if e, ok := err.(*flags.Error); ok { switch e.Type { case flags.ErrHelp, flags.ErrCommandRequired: @@ -787,3 +790,157 @@ func checkForVars(opts *options) error { return nil } + +// Helper to recursively collect all options from a group and its subgroups +func collectAllOptions(group *flags.Group) []*flags.Option { + var allOptions []*flags.Option + allOptions = append(allOptions, group.Options()...) + for _, subgroup := range group.Groups() { + allOptions = append(allOptions, collectAllOptions(subgroup)...) + } + return allOptions +} + +// validateCommandFlags checks if the provided command flags are valid for the given command. +func validateCommandFlags(parser *flags.Parser, args []string) error { + if len(args) == 0 { + return nil + } + + var selectedCmd *flags.Command + cmds := parser.Commands() + // currentArgPosition tracks our position in the args array as we traverse the command hierarchy + currentArgPosition := 0 + + // Find the top-level command + for _, cmd := range cmds { + if cmd.Name == args[currentArgPosition] || contains(cmd.Aliases, args[currentArgPosition]) { + selectedCmd = cmd + break + } + } + if selectedCmd == nil { + return nil // unknown command, let parser handle it + } + currentArgPosition++ + + // Walk down subcommands as long as the next arg matches a subcommand + // For example: "om vm-lifecycle export-opsman-config" would traverse: + // 1. "vm-lifecycle" (top-level command) + // 2. "export-opsman-config" (subcommand) + for currentArgPosition < len(args) { + found := false + for _, sub := range selectedCmd.Commands() { + if sub.Name == args[currentArgPosition] || contains(sub.Aliases, args[currentArgPosition]) { + selectedCmd = sub + currentArgPosition++ + found = true + break + } + } + if !found { + break + } + } + + // Now selectedCmd is the deepest subcommand + // Check remaining args for unknown flags + invalidFlags := findUnknownFlags(selectedCmd, args[currentArgPosition:]) + + if len(invalidFlags) > 0 { + return fmt.Errorf( + "Error: unknown flag(s) %q for command '%s'\nSee 'om %s --help' for available options", + invalidFlags, + selectedCmd.Name, + selectedCmd.Name, + ) + } + return nil +} + +// findUnknownFlags checks for unknown flags in the provided args for the given command. +func findUnknownFlags(selectedCmd *flags.Command, args []string) []string { + validFlags := make(map[string]bool) + addFlag := func(name string, takesValue bool) { + validFlags[name] = takesValue + } + cmd := selectedCmd + for cmd.Active != nil { + cmd = cmd.Active + } + for _, opt := range collectAllOptions(cmd.Group) { + val := opt.Value() + _, isBool := val.(*bool) + _, isBoolSlice := val.(*[]bool) + takesValue := !(isBool || isBoolSlice) + if ln := opt.LongNameWithNamespace(); ln != "" { + addFlag("--"+ln, takesValue) + } + if opt.ShortName != 0 { + addFlag("-"+string(opt.ShortName), takesValue) + } + } + addFlag("--help", false) + addFlag("-h", false) + + var invalidFlags []string + i := 0 + for i < len(args) { + arg := args[i] + if !strings.HasPrefix(arg, "-") { + // Not a flag, and not a value for a previous flag (since we only check flags) + // Stop processing further, as all remaining args are positional + break + } + + // Split flag and value if --flag=value + flagName, hasEquals := arg, false + if eqIdx := strings.Index(arg, "="); eqIdx != -1 { + flagName = arg[:eqIdx] + hasEquals = true + // Example: arg = "--product=foo.pivotal" -> flagName = "--product", value = "foo.pivotal" + } + + takesValue, isValid := validFlags[flagName] + if !isValid { + // Unknown flag + // Example: arg = "--notaflag" (not defined in command options) + invalidFlags = append(invalidFlags, flagName) + i++ + continue + } + + if takesValue { + if hasEquals { + // --flag=value, value is in this arg + // Example: arg = "--product=foo.pivotal" + i++ + } else if i+1 < len(args) { + // --flag value, value is next arg (even if it looks like a flag) + // Example: args = ["--product", "--notaflag"] + // "--notaflag" is treated as the value for --product, not as a flag + i += 2 + } else { + // --flag with missing value. + // No need to handle this here as this will handled appropriately by the parser. + // Example: args = ["--product"] (no value provided) + i++ + } + } else { + // Boolean flag, no value expected + // Example: arg = "--help" + i++ + } + } + return invalidFlags +} + +// contains checks if a string is present in a list of strings. +func contains(list []string, s string) bool { + for _, v := range list { + if v == s { + return true + } + } + return false +} diff --git a/cmd/suite_test.go b/cmd/suite_test.go new file mode 100644 index 00000000..4bd8e403 --- /dev/null +++ b/cmd/suite_test.go @@ -0,0 +1,13 @@ +package cmd + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestCmd(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Cmd Suite") +} diff --git a/formcontent/formcontent_test.go b/formcontent/formcontent_test.go index d51df0c8..05dfbdfc 100644 --- a/formcontent/formcontent_test.go +++ b/formcontent/formcontent_test.go @@ -192,7 +192,7 @@ var _ = Describe("Formcontent", func() { content, err := io.ReadAll(submission.Content) Expect(err).ToNot(HaveOccurred()) - Expect(submission.ContentLength).To(Or(Equal(int64(373)), Equal(int64(374)))) + Expect(submission.ContentLength).To(Or(Equal(int64(372)), Equal(int64(373)), Equal(int64(374)))) Expect(string(content)).To(MatchRegexp(`^--\w+\r\nContent-Disposition: form-data; name=\"file1\"; filename=\"\w+\"\r\n` + `Content-Type: application/octet-stream\r\n\r\n` + `some content` + diff --git a/go.mod b/go.mod index cb081a84..4021c4df 100644 --- a/go.mod +++ b/go.mod @@ -97,8 +97,8 @@ require ( github.com/golang-jwt/jwt/v4 v4.5.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/snappy v0.0.4 // indirect - github.com/google/go-cmp v0.6.0 // indirect - github.com/google/pprof v0.0.0-20241101162523-b92577c0c142 // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect github.com/google/s2a-go v0.1.8 // indirect github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect @@ -143,21 +143,21 @@ require ( go.opentelemetry.io/otel/sdk v1.32.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.32.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect - golang.org/x/crypto v0.29.0 // indirect - golang.org/x/mod v0.22.0 // indirect - golang.org/x/net v0.31.0 // indirect - golang.org/x/sync v0.9.0 // indirect - golang.org/x/sys v0.27.0 // indirect - golang.org/x/term v0.26.0 // indirect - golang.org/x/text v0.20.0 // indirect + golang.org/x/crypto v0.36.0 // indirect + golang.org/x/mod v0.24.0 // indirect + golang.org/x/net v0.37.0 // indirect + golang.org/x/sync v0.12.0 // indirect + golang.org/x/sys v0.32.0 // indirect + golang.org/x/term v0.30.0 // indirect + golang.org/x/text v0.23.0 // indirect golang.org/x/time v0.8.0 // indirect - golang.org/x/tools v0.27.0 // indirect + golang.org/x/tools v0.31.0 // indirect google.golang.org/genproto v0.0.0-20241104194629-dd2ea8efbc28 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect google.golang.org/grpc v1.68.0 // indirect google.golang.org/grpc/stats/opentelemetry v0.0.0-20241028142157-ada6787961b3 // indirect - google.golang.org/protobuf v1.35.1 // indirect + google.golang.org/protobuf v1.36.5 // indirect gopkg.in/cheggaaa/pb.v1 v1.0.28 // indirect gopkg.in/go-playground/assert.v1 v1.2.1 // indirect ) diff --git a/go.sum b/go.sum index a743f956..08936373 100644 --- a/go.sum +++ b/go.sum @@ -236,15 +236,15 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20241101162523-b92577c0c142 h1:sAGdeJj0bnMgUNVeUpp6AYlVdCt3/GdI3pGRqsNSQLs= -github.com/google/pprof v0.0.0-20241101162523-b92577c0c142/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/readahead v0.0.0-20161222183148-eaceba169032/go.mod h1:qYysrqQXuV4tzsizt4oOQ6mrBZQ0xnQXP3ylXX8Jk5Y= github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM= github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= @@ -463,8 +463,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= -golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -473,8 +473,8 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= -golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= +golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20180712202826-d0887baf81f4/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -497,8 +497,8 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= -golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= +golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= +golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -513,8 +513,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= -golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= +golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180709060233-1b2967e3c290/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -547,15 +547,15 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= -golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= -golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= -golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= +golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= +golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -566,8 +566,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= -golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= @@ -582,8 +582,8 @@ golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDq golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o= -golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q= +golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU= +golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -625,8 +625,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= -google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= +google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/vmlifecycle/acceptance/delete_vm_test.go b/vmlifecycle/acceptance/delete_vm_test.go index 13a06d22..1e21c386 100644 --- a/vmlifecycle/acceptance/delete_vm_test.go +++ b/vmlifecycle/acceptance/delete_vm_test.go @@ -55,7 +55,7 @@ opsman-configuration: Expect(err).ToNot(HaveOccurred()) Eventually(session, 5).Should(gexec.Exit(1)) - Eventually(session.Err).Should(gbytes.Say("unknown flag `random'")) + Expect(session.Err).To(gbytes.Say("unknown flag\\(s\\) \\[\"--random\"\\] for command 'delete-vm'")) }) }) })