From 642820b98ec936e84a9a4b89848ec90d463c1971 Mon Sep 17 00:00:00 2001 From: Marques Johansson Date: Sat, 29 Aug 2020 17:03:34 -0400 Subject: [PATCH] add global includes and excludes options Adds `--include` and `--exclude` which can accept comma-separated values or can be given multiple times to specify more includes/excludes. Naturally, dotted syntax (as supported by the API) can be used to include/exclude deep values. Default includes will not be used when their results are not rendered. Signed-off-by: Marques Johansson --- cmd/retrieve_device.go | 2 +- cmd/retrieve_event.go | 11 ++++++++++- cmd/retrieve_facilities.go | 2 +- cmd/retrieve_hardware_reservations.go | 15 ++++++++++++--- cmd/retrieve_organization.go | 7 +++++-- cmd/retrieve_plans.go | 2 +- cmd/retrieve_project.go | 21 +++++++++++++++------ cmd/retrieve_virtual_network.go | 2 +- cmd/retrieve_volume.go | 2 +- cmd/root.go | 18 ++++++++++++++++++ 10 files changed, 65 insertions(+), 17 deletions(-) diff --git a/cmd/retrieve_device.go b/cmd/retrieve_device.go index ce9370c8..d447199a 100644 --- a/cmd/retrieve_device.go +++ b/cmd/retrieve_device.go @@ -46,7 +46,7 @@ packet device get --id [device_UUID] } else if deviceID == "" && projectID == "" { return fmt.Errorf("Either id or project-id should be set.") } else if projectID != "" { - devices, _, err := PacknGo.Devices.List(projectID, nil) + devices, _, err := PacknGo.Devices.List(projectID, listOptions(nil, nil)) if err != nil { return errors.Wrap(err, "Could not list Devices") } diff --git a/cmd/retrieve_event.go b/cmd/retrieve_event.go index 56bc00be..21e1d126 100644 --- a/cmd/retrieve_event.go +++ b/cmd/retrieve_event.go @@ -52,12 +52,21 @@ packet event get -d [device_UUID] Retrieve all events of a current user: packet event get + +When using "--json" or "--yaml", "--include=relationships" is implied. `, RunE: func(cmd *cobra.Command, args []string) error { var events []packngo.Event var err error header := []string{"ID", "Body", "Type", "Created"} - listOpt := &packngo.ListOptions{Includes: []string{"relationships"}} + + inc := []string{"relationships"} + + // don't fetch extra details that won't be rendered + if !isYaml && !isJSON { + inc = nil + } + listOpt := listOptions(inc, nil) if deviceID != "" && projectID != "" && organizationID != "" && eventID != "" { return fmt.Errorf("The id, project-id, device-id, and organization-id parameters are mutually exclusive") diff --git a/cmd/retrieve_facilities.go b/cmd/retrieve_facilities.go index d51592fa..df06fb78 100644 --- a/cmd/retrieve_facilities.go +++ b/cmd/retrieve_facilities.go @@ -37,7 +37,7 @@ packet facilities get `, RunE: func(cmd *cobra.Command, args []string) error { - facilities, _, err := PacknGo.Facilities.List(nil) + facilities, _, err := PacknGo.Facilities.List(listOptions(nil, nil)) if err != nil { return errors.Wrap(err, "Could not list Facilities") } diff --git a/cmd/retrieve_hardware_reservations.go b/cmd/retrieve_hardware_reservations.go index 4b670187..d258a940 100644 --- a/cmd/retrieve_hardware_reservations.go +++ b/cmd/retrieve_hardware_reservations.go @@ -36,10 +36,19 @@ var retrieveHardwareReservationsCmd = &cobra.Command{ Retrieve all hardware reservations of a project: packet hardware_reservations get -p [project_id] + +When using "--json" or "--yaml", "--include=project,facility,device" is implied. `, RunE: func(cmd *cobra.Command, args []string) error { header := []string{"ID", "Facility", "Plan", "Created"} - listOpt := &packngo.ListOptions{Includes: []string{"project,facility,device"}} + + inc := []string{"project", "facility", "device"} + + // don't fetch extra details that won't be rendered + if !isYaml && !isJSON { + inc = nil + } + listOpt := listOptions(inc, nil) if hardwareReservationID == "" && projectID == "" { return fmt.Errorf("Either id or project-id should be set.") @@ -59,8 +68,8 @@ packet hardware_reservations get -p [project_id] return output(reservations, header, &data) } else if hardwareReservationID != "" { - getOpt := &packngo.GetOptions{Includes: listOpt.Includes} - r, _, err := PacknGo.HardwareReservations.Get(hardwareReservationID, getOpt) + getOpts := &packngo.GetOptions{Includes: listOpt.Includes, Excludes: listOpt.Excludes} + r, _, err := PacknGo.HardwareReservations.Get(hardwareReservationID, getOpts) if err != nil { return errors.Wrap(err, "Could not get Hardware Reservation") } diff --git a/cmd/retrieve_organization.go b/cmd/retrieve_organization.go index 3fd6ebbb..d072ca06 100644 --- a/cmd/retrieve_organization.go +++ b/cmd/retrieve_organization.go @@ -21,6 +21,7 @@ package cmd import ( + "github.com/packethost/packngo" "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -39,8 +40,9 @@ packet organization get -i [organization-id] `, RunE: func(cmd *cobra.Command, args []string) error { + listOpts := listOptions(nil, nil) if organizationID == "" { - orgs, _, err := PacknGo.Organizations.List(nil) + orgs, _, err := PacknGo.Organizations.List(listOpts) if err != nil { return errors.Wrap(err, "Could not list Organizations") } @@ -54,7 +56,8 @@ packet organization get -i [organization-id] return output(orgs, header, &data) } else { - org, _, err := PacknGo.Organizations.Get(organizationID, nil) + getOpts := &packngo.GetOptions{Includes: listOpts.Includes, Excludes: listOpts.Excludes} + org, _, err := PacknGo.Organizations.Get(organizationID, getOpts) if err != nil { return errors.Wrap(err, "Could not get Organization") } diff --git a/cmd/retrieve_plans.go b/cmd/retrieve_plans.go index ff68aa09..dea3662d 100644 --- a/cmd/retrieve_plans.go +++ b/cmd/retrieve_plans.go @@ -35,7 +35,7 @@ var retrievePlansCmd = &cobra.Command{ `, RunE: func(cmd *cobra.Command, args []string) error { - plans, _, err := PacknGo.Plans.List(nil) + plans, _, err := PacknGo.Plans.List(listOptions(nil, nil)) if err != nil { return errors.Wrap(err, "Could not list Plans") } diff --git a/cmd/retrieve_project.go b/cmd/retrieve_project.go index 923a44e8..d7d5b3c0 100644 --- a/cmd/retrieve_project.go +++ b/cmd/retrieve_project.go @@ -40,17 +40,25 @@ packet project get Retrieve a specific project: packet project get -i [project_UUID] packet project get -n [project_name] + +When using "--json" or "--yaml", "--include=members" is implied. `, RunE: func(cmd *cobra.Command, args []string) error { if projectID != "" && projectName != "" { return fmt.Errorf("Must specify only one of project-id and project name") } - if projectID == "" { - listOpt := &packngo.ListOptions{ - Includes: []string{"members"}, - } - projects, _, err := PacknGo.Projects.List(listOpt) + inc := []string{"members"} + + // don't fetch extra details that won't be rendered + if !isYaml && !isJSON { + inc = nil + } + + listOpts := listOptions(inc, nil) + + if projectID == "" { + projects, _, err := PacknGo.Projects.List(listOpts) if err != nil { return errors.Wrap(err, "Could not list Projects") } @@ -77,7 +85,8 @@ packet project get -n [project_name] header := []string{"ID", "Name", "Created"} return output(projects, header, &data) } else { - p, _, err := PacknGo.Projects.Get(projectID, &packngo.GetOptions{Includes: []string{"members"}}) + getOpts := &packngo.GetOptions{Includes: listOpts.Includes, Excludes: listOpts.Excludes} + p, _, err := PacknGo.Projects.Get(projectID, getOpts) if err != nil { return errors.Wrap(err, "Could not get Project") } diff --git a/cmd/retrieve_virtual_network.go b/cmd/retrieve_virtual_network.go index b3d16735..63d6a055 100644 --- a/cmd/retrieve_virtual_network.go +++ b/cmd/retrieve_virtual_network.go @@ -37,7 +37,7 @@ packet virtual-network get -p [project_UUID] `, RunE: func(cmd *cobra.Command, args []string) error { - vnets, _, err := PacknGo.ProjectVirtualNetworks.List(projectID, nil) + vnets, _, err := PacknGo.ProjectVirtualNetworks.List(projectID, listOptions(nil, nil)) if err != nil { return errors.Wrap(err, "Could not list Project Virtual Networks") } diff --git a/cmd/retrieve_volume.go b/cmd/retrieve_volume.go index 008f56b5..d32e1677 100644 --- a/cmd/retrieve_volume.go +++ b/cmd/retrieve_volume.go @@ -51,7 +51,7 @@ packet volume get --id [volume_UUID] } else if projectID == "" && volumeID == "" { return fmt.Errorf("Either id or project-id should be set.") } else if projectID != "" { - volumes, _, err := PacknGo.Volumes.List(projectID, nil) + volumes, _, err := PacknGo.Volumes.List(projectID, listOptions(nil, nil)) if err != nil { return errors.Wrap(err, "Could not list Volumes") } diff --git a/cmd/root.go b/cmd/root.go index f8a6c0f4..cdd3165d 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -37,6 +37,8 @@ var ( cfgFile string isJSON bool isYaml bool + includes *[]string + excludes *[]string packetToken string ) @@ -78,9 +80,25 @@ func init() { rootCmd.PersistentFlags().BoolVarP(&isJSON, "json", "j", false, "JSON output") rootCmd.PersistentFlags().BoolVarP(&isYaml, "yaml", "y", false, "YAML output") + includes = rootCmd.PersistentFlags().StringSlice("include", nil, "Comma seperated Href references to expand in results, may be dotted three levels deep") + excludes = rootCmd.PersistentFlags().StringSlice("exclude", nil, "Comma seperated Href references to collapse in results, may be dotted three levels deep") + rootCmd.Version = Version } +// listOptions creates a ListOptions using the includes and excludes persistent +// flags. When not defined, the defaults given will be supplied. +func listOptions(defaultIncludes, defaultExcludes []string) *packngo.ListOptions { + listOptions := &packngo.ListOptions{} + if !rootCmd.Flags().Changed("include") { + listOptions.Includes = defaultIncludes + } + if !rootCmd.Flags().Changed("exclude") { + listOptions.Excludes = defaultExcludes + } + return listOptions +} + // initConfig reads in config file and ENV variables if set. func initConfig() { if cfgFile != "" {