diff --git a/.gitignore b/.gitignore index f78d60ba..bfc5c400 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ coverage.out metalctl result tmp +.DS_Store diff --git a/cmd/size.go b/cmd/size.go index 288a8246..c1768a20 100644 --- a/cmd/size.go +++ b/cmd/size.go @@ -3,13 +3,17 @@ package cmd import ( "errors" "fmt" + "time" "github.com/dustin/go-humanize" + "github.com/go-openapi/strfmt" + "github.com/google/uuid" "github.com/metal-stack/metal-go/api/client/size" "github.com/metal-stack/metal-go/api/models" "github.com/metal-stack/metal-lib/pkg/genericcli" "github.com/metal-stack/metal-lib/pkg/genericcli/printers" "github.com/metal-stack/metal-lib/pkg/pointer" + "github.com/metal-stack/metal-lib/pkg/tag" "github.com/metal-stack/metalctl/cmd/sorters" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -92,7 +96,22 @@ func newSizeCmd(c *config) *cobra.Command { reservationsCmd.AddCommand(listReservationsCmd) - return genericcli.NewCmds(cmdsConfig, newSizeImageConstraintCmd(c), tryCmd, reservationsCmd) + suggestCmd := &cobra.Command{ + Use: "suggest ", + Short: "suggest size from a given machine id", + RunE: func(cmd *cobra.Command, args []string) error { + return w.suggest(args) + }, + } + + suggestCmd.Flags().String("machine-id", "", "Machine id used to create the size suggestion. [required]") + suggestCmd.Flags().String("name", "suggested-size", "The name of the suggested size") + suggestCmd.Flags().String("description", "a suggested size", "The description of the suggested size") + suggestCmd.Flags().StringSlice("labels", []string{}, "labels to add to the size") + + must(suggestCmd.RegisterFlagCompletionFunc("machine-id", c.comp.MachineListCompletion)) + + return genericcli.NewCmds(cmdsConfig, newSizeImageConstraintCmd(c), tryCmd, reservationsCmd, suggestCmd) } func (c sizeCmd) Get(id string) (*models.V1SizeResponse, error) { @@ -239,3 +258,40 @@ func (c sizeCmd) listReverations() error { return c.listPrinter.Print(resp.Payload) } + +func (c *sizeCmd) suggest(args []string) error { + sizeid, _ := genericcli.GetExactlyOneArg(args) + + var ( + machineid = viper.GetString("machine-id") + name = viper.GetString("name") + description = viper.GetString("description") + labels = tag.NewTagMap(viper.GetStringSlice("labels")) + now = time.Now() + ) + + if sizeid == "" { + sizeid = uuid.NewString() + } + + if machineid == "" { + return fmt.Errorf("machine-id flag is required") + } + + resp, err := c.client.Size().Suggest(size.NewSuggestParams().WithBody(&models.V1SizeSuggestRequest{ + MachineID: &machineid, + }), nil) + if err != nil { + return err + } + + return c.describePrinter.Print(&models.V1SizeResponse{ + ID: &sizeid, + Name: name, + Description: description, + Constraints: resp.Payload, + Labels: labels, + Changed: strfmt.DateTime(now), + Created: strfmt.DateTime(now), + }) +} diff --git a/cmd/size_test.go b/cmd/size_test.go index 4912ec87..5def9220 100644 --- a/cmd/size_test.go +++ b/cmd/size_test.go @@ -4,6 +4,7 @@ import ( "strconv" "testing" + "github.com/go-openapi/strfmt" "github.com/metal-stack/metal-go/api/client/size" "github.com/metal-stack/metal-go/api/models" "github.com/metal-stack/metal-go/test/client" @@ -290,6 +291,68 @@ ID NAME DESCRIPTION RESERVATIONS CPU RANGE MEMORY RANGE STORAGE RA }, want: size1, }, + { + name: "suggest", + cmd: func(want *models.V1SizeResponse) []string { + + args := []string{"size", "suggest", "c1-large-x86", "--machine-id=1", "--name=mysize", "--description=foo", "--labels=1=b"} + + assertExhaustiveArgs(t, args, commonExcludedFileArgs()...) + return args + }, + mocks: &client.MetalMockFns{ + Size: func(mock *mock.Mock) { + mock.On("Suggest", testcommon.MatchIgnoreContext(t, size.NewSuggestParams().WithBody(&models.V1SizeSuggestRequest{ + MachineID: pointer.Pointer("1"), + })), nil).Return(&size.SuggestOK{ + Payload: []*models.V1SizeConstraint{ + { + Max: pointer.Pointer(int64(2)), + Min: pointer.Pointer(int64(1)), + Type: pointer.Pointer("storage"), + }, + { + Max: pointer.Pointer(int64(4)), + Min: pointer.Pointer(int64(3)), + Type: pointer.Pointer("memory"), + }, + { + Max: pointer.Pointer(int64(6)), + Min: pointer.Pointer(int64(5)), + Type: pointer.Pointer("cores"), + }, + }, + }, nil) + }, + }, + want: &models.V1SizeResponse{ + Constraints: []*models.V1SizeConstraint{ + { + Max: pointer.Pointer(int64(2)), + Min: pointer.Pointer(int64(1)), + Type: pointer.Pointer("storage"), + }, + { + Max: pointer.Pointer(int64(4)), + Min: pointer.Pointer(int64(3)), + Type: pointer.Pointer("memory"), + }, + { + Max: pointer.Pointer(int64(6)), + Min: pointer.Pointer(int64(5)), + Type: pointer.Pointer("cores"), + }, + }, + Description: "foo", + ID: pointer.Pointer("c1-large-x86"), + Name: "mysize", + Labels: map[string]string{ + "1": "b", + }, + Changed: strfmt.DateTime(testTime), + Created: strfmt.DateTime(testTime), + }, + }, } for _, tt := range tests { tt.testCmd(t) diff --git a/docs/metalctl_size.md b/docs/metalctl_size.md index 965b4f86..82be6d15 100644 --- a/docs/metalctl_size.md +++ b/docs/metalctl_size.md @@ -51,6 +51,7 @@ a size matches a machine in terms of cpu cores, ram and storage. * [metalctl size imageconstraint](metalctl_size_imageconstraint.md) - manage imageconstraint entities * [metalctl size list](metalctl_size_list.md) - list all sizes * [metalctl size reservations](metalctl_size_reservations.md) - manage size reservations +* [metalctl size suggest](metalctl_size_suggest.md) - suggest size from a given machine id * [metalctl size try](metalctl_size_try.md) - try a specific hardware spec and give the chosen size back * [metalctl size update](metalctl_size_update.md) - updates the size diff --git a/docs/metalctl_size_suggest.md b/docs/metalctl_size_suggest.md new file mode 100644 index 00000000..d50081a0 --- /dev/null +++ b/docs/metalctl_size_suggest.md @@ -0,0 +1,50 @@ +## metalctl size suggest + +suggest size from a given machine id + +``` +metalctl size suggest [flags] +``` + +### Options + +``` + --description string The description of the suggested size (default "a suggested size") + -h, --help help for suggest + --labels strings labels to add to the size + --machine-id string Machine id used to create the size suggestion. [required] + --name string The name of the suggested size (default "suggested-size") +``` + +### Options inherited from parent commands + +``` + --api-token string api token to authenticate. Can be specified with METALCTL_API_TOKEN environment variable. + --api-url string api server address. Can be specified with METALCTL_API_URL environment variable. + -c, --config string alternative config file path, (default is ~/.metalctl/config.yaml). + Example config.yaml: + + --- + apitoken: "alongtoken" + ... + + + --debug debug output + --force-color force colored output even without tty + --kubeconfig string Path to the kube-config to use for authentication and authorization. Is updated by login. Uses default path if not specified. + --no-headers do not print headers of table output format (default print headers) + -o, --output-format string output format (table|wide|markdown|json|yaml|template), wide is a table with more columns. (default "table") + --template string output template for template output-format, go template format. + For property names inspect the output of -o json or -o yaml for reference. + Example for machines: + + metalctl machine list -o template --template "{{ .id }}:{{ .size.id }}" + + + --yes-i-really-mean-it skips security prompts (which can be dangerous to set blindly because actions can lead to data loss or additional costs) +``` + +### SEE ALSO + +* [metalctl size](metalctl_size.md) - manage size entities + diff --git a/docs/metalctl_update.md b/docs/metalctl_update.md index e739992f..3fce1e2b 100644 --- a/docs/metalctl_update.md +++ b/docs/metalctl_update.md @@ -5,8 +5,7 @@ update the program ### Options ``` - -h, --help help for update - -v, --version string the version to update to, by default updates to the supported version, use "latest" to update to latest version + -h, --help help for update ``` ### Options inherited from parent commands diff --git a/docs/metalctl_update_do.md b/docs/metalctl_update_do.md index 2ede1a82..d2269d5e 100644 --- a/docs/metalctl_update_do.md +++ b/docs/metalctl_update_do.md @@ -9,7 +9,8 @@ metalctl update do [flags] ### Options ``` - -h, --help help for do + -h, --help help for do + -v, --version string the version to update to, by default updates to the supported version, use "latest" to update to latest version ``` ### Options inherited from parent commands diff --git a/go.mod b/go.mod index e6057a8c..35825dda 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/go-openapi/runtime v0.28.0 github.com/go-openapi/strfmt v0.23.0 github.com/google/go-cmp v0.6.0 + github.com/google/uuid v1.6.0 github.com/metal-stack/metal-go v0.28.3 github.com/metal-stack/metal-lib v0.16.1 github.com/metal-stack/updater v1.2.1 @@ -82,7 +83,6 @@ require ( github.com/google/go-github/v56 v56.0.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/nftables v0.2.0 // indirect - github.com/google/uuid v1.6.0 // indirect github.com/gorilla/csrf v1.7.2 // indirect github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/securecookie v1.1.2 // indirect