From d447b0cadf0f6255ab3f38ced7d9a0fd972b57c6 Mon Sep 17 00:00:00 2001 From: phm07 <22707808+phm07@users.noreply.github.com> Date: Fri, 31 Jan 2025 17:11:38 +0100 Subject: [PATCH] refactor: make base describe command generic (#972) More type safety <3 --- internal/cmd/base/describe.go | 10 +++++----- internal/cmd/base/describe_test.go | 7 +++---- internal/cmd/certificate/describe.go | 7 +++---- internal/cmd/datacenter/describe.go | 8 +++----- internal/cmd/firewall/describe.go | 8 +++----- internal/cmd/floatingip/describe.go | 8 +++----- internal/cmd/image/describe.go | 8 +++----- internal/cmd/iso/describe.go | 8 +++----- internal/cmd/loadbalancer/describe.go | 7 +++---- internal/cmd/loadbalancertype/describe.go | 8 +++----- internal/cmd/location/describe.go | 8 +++----- internal/cmd/network/describe.go | 8 +++----- internal/cmd/placementgroup/describe.go | 8 +++----- internal/cmd/primaryip/describe.go | 8 +++----- internal/cmd/server/describe.go | 8 +++----- internal/cmd/servertype/describe.go | 8 +++----- internal/cmd/sshkey/describe.go | 7 +++---- internal/cmd/volume/describe.go | 8 +++----- 18 files changed, 56 insertions(+), 86 deletions(-) diff --git a/internal/cmd/base/describe.go b/internal/cmd/base/describe.go index 73fa8925..55615ff3 100644 --- a/internal/cmd/base/describe.go +++ b/internal/cmd/base/describe.go @@ -16,7 +16,7 @@ import ( ) // DescribeCmd allows defining commands for describing a resource. -type DescribeCmd struct { +type DescribeCmd[T any] struct { ResourceNameSingular string // e.g. "server" ShortDescription string // key in API response JSON to use for extracting object from response body for JSON output. @@ -26,12 +26,12 @@ type DescribeCmd struct { AdditionalFlags func(*cobra.Command) // Fetch is called to fetch the resource to describe. // The first returned interface is the resource itself as a hcloud struct, the second is the schema for the resource. - Fetch func(s state.State, cmd *cobra.Command, idOrName string) (interface{}, interface{}, error) - PrintText func(s state.State, cmd *cobra.Command, resource interface{}) error + Fetch func(s state.State, cmd *cobra.Command, idOrName string) (T, any, error) + PrintText func(s state.State, cmd *cobra.Command, resource T) error } // CobraCommand creates a command that can be registered with cobra. -func (dc *DescribeCmd) CobraCommand(s state.State) *cobra.Command { +func (dc *DescribeCmd[T]) CobraCommand(s state.State) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("describe [options] <%s>", util.ToKebabCase(dc.ResourceNameSingular)), Short: dc.ShortDescription, @@ -52,7 +52,7 @@ func (dc *DescribeCmd) CobraCommand(s state.State) *cobra.Command { } // Run executes a describe command. -func (dc *DescribeCmd) Run(s state.State, cmd *cobra.Command, args []string) error { +func (dc *DescribeCmd[T]) Run(s state.State, cmd *cobra.Command, args []string) error { outputFlags := output.FlagsForCommand(cmd) quiet, err := config.OptionQuiet.Get(s.Config()) diff --git a/internal/cmd/base/describe_test.go b/internal/cmd/base/describe_test.go index dad57bf7..c973857c 100644 --- a/internal/cmd/base/describe_test.go +++ b/internal/cmd/base/describe_test.go @@ -12,10 +12,10 @@ import ( "github.com/hetznercloud/cli/internal/testutil" ) -var fakeDescribeCmd = &base.DescribeCmd{ +var fakeDescribeCmd = &base.DescribeCmd[*fakeResource]{ ResourceNameSingular: "Fake resource", - Fetch: func(_ state.State, cmd *cobra.Command, _ string) (interface{}, interface{}, error) { + Fetch: func(_ state.State, cmd *cobra.Command, _ string) (*fakeResource, any, error) { cmd.Println("Fetching fake resource") resource := &fakeResource{ @@ -26,8 +26,7 @@ var fakeDescribeCmd = &base.DescribeCmd{ return resource, util.Wrap("resource", resource), nil }, - PrintText: func(_ state.State, cmd *cobra.Command, resource interface{}) error { - rsc := resource.(*fakeResource) + PrintText: func(_ state.State, cmd *cobra.Command, rsc *fakeResource) error { cmd.Printf("ID: %d\n", rsc.ID) cmd.Printf("Name: %s\n", rsc.Name) return nil diff --git a/internal/cmd/certificate/describe.go b/internal/cmd/certificate/describe.go index dc34fe93..c6bc11a5 100644 --- a/internal/cmd/certificate/describe.go +++ b/internal/cmd/certificate/describe.go @@ -11,21 +11,20 @@ import ( "github.com/hetznercloud/hcloud-go/v2/hcloud" ) -var DescribeCmd = base.DescribeCmd{ +var DescribeCmd = base.DescribeCmd[*hcloud.Certificate]{ ResourceNameSingular: "certificate", ShortDescription: "Describe an certificate", JSONKeyGetByID: "certificate", JSONKeyGetByName: "certificates", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Certificate().Names }, - Fetch: func(s state.State, _ *cobra.Command, idOrName string) (interface{}, interface{}, error) { + Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.Certificate, any, error) { cert, _, err := s.Client().Certificate().Get(s, idOrName) if err != nil { return nil, nil, err } return cert, hcloud.SchemaFromCertificate(cert), nil }, - PrintText: func(s state.State, cmd *cobra.Command, resource interface{}) error { - cert := resource.(*hcloud.Certificate) + PrintText: func(s state.State, cmd *cobra.Command, cert *hcloud.Certificate) error { cmd.Printf("ID:\t\t\t%d\n", cert.ID) cmd.Printf("Name:\t\t\t%s\n", cert.Name) cmd.Printf("Type:\t\t\t%s\n", cert.Type) diff --git a/internal/cmd/datacenter/describe.go b/internal/cmd/datacenter/describe.go index 16e3e213..7786266d 100644 --- a/internal/cmd/datacenter/describe.go +++ b/internal/cmd/datacenter/describe.go @@ -12,22 +12,20 @@ import ( "github.com/hetznercloud/hcloud-go/v2/hcloud" ) -var DescribeCmd = base.DescribeCmd{ +var DescribeCmd = base.DescribeCmd[*hcloud.Datacenter]{ ResourceNameSingular: "datacenter", ShortDescription: "Describe an datacenter", JSONKeyGetByID: "datacenter", JSONKeyGetByName: "datacenters", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Datacenter().Names }, - Fetch: func(s state.State, _ *cobra.Command, idOrName string) (interface{}, interface{}, error) { + Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.Datacenter, any, error) { dc, _, err := s.Client().Datacenter().Get(s, idOrName) if err != nil { return nil, nil, err } return dc, hcloud.SchemaFromDatacenter(dc), nil }, - PrintText: func(s state.State, cmd *cobra.Command, resource interface{}) error { - datacenter := resource.(*hcloud.Datacenter) - + PrintText: func(s state.State, cmd *cobra.Command, datacenter *hcloud.Datacenter) error { cmd.Printf("ID:\t\t%d\n", datacenter.ID) cmd.Printf("Name:\t\t%s\n", datacenter.Name) cmd.Printf("Description:\t%s\n", datacenter.Description) diff --git a/internal/cmd/firewall/describe.go b/internal/cmd/firewall/describe.go index 956ab359..14e56cd6 100644 --- a/internal/cmd/firewall/describe.go +++ b/internal/cmd/firewall/describe.go @@ -13,22 +13,20 @@ import ( "github.com/hetznercloud/hcloud-go/v2/hcloud" ) -var DescribeCmd = base.DescribeCmd{ +var DescribeCmd = base.DescribeCmd[*hcloud.Firewall]{ ResourceNameSingular: "firewall", ShortDescription: "Describe an firewall", JSONKeyGetByID: "firewall", JSONKeyGetByName: "firewalls", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Firewall().Names }, - Fetch: func(s state.State, _ *cobra.Command, idOrName string) (interface{}, interface{}, error) { + Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.Firewall, any, error) { fw, _, err := s.Client().Firewall().Get(s, idOrName) if err != nil { return nil, nil, err } return fw, hcloud.SchemaFromFirewall(fw), nil }, - PrintText: func(s state.State, cmd *cobra.Command, resource interface{}) error { - firewall := resource.(*hcloud.Firewall) - + PrintText: func(s state.State, cmd *cobra.Command, firewall *hcloud.Firewall) error { cmd.Printf("ID:\t\t%d\n", firewall.ID) cmd.Printf("Name:\t\t%s\n", firewall.Name) cmd.Printf("Created:\t%s (%s)\n", util.Datetime(firewall.Created), humanize.Time(firewall.Created)) diff --git a/internal/cmd/floatingip/describe.go b/internal/cmd/floatingip/describe.go index 4909ae53..3f63852a 100644 --- a/internal/cmd/floatingip/describe.go +++ b/internal/cmd/floatingip/describe.go @@ -11,22 +11,20 @@ import ( "github.com/hetznercloud/hcloud-go/v2/hcloud" ) -var DescribeCmd = base.DescribeCmd{ +var DescribeCmd = base.DescribeCmd[*hcloud.FloatingIP]{ ResourceNameSingular: "Floating IP", ShortDescription: "Describe an Floating IP", JSONKeyGetByID: "floating_ip", JSONKeyGetByName: "floating_ips", NameSuggestions: func(c hcapi2.Client) func() []string { return c.FloatingIP().Names }, - Fetch: func(s state.State, _ *cobra.Command, idOrName string) (interface{}, interface{}, error) { + Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.FloatingIP, any, error) { ip, _, err := s.Client().FloatingIP().Get(s, idOrName) if err != nil { return nil, nil, err } return ip, hcloud.SchemaFromFloatingIP(ip), nil }, - PrintText: func(s state.State, cmd *cobra.Command, resource interface{}) error { - floatingIP := resource.(*hcloud.FloatingIP) - + PrintText: func(s state.State, cmd *cobra.Command, floatingIP *hcloud.FloatingIP) error { cmd.Printf("ID:\t\t%d\n", floatingIP.ID) cmd.Printf("Type:\t\t%s\n", floatingIP.Type) cmd.Printf("Name:\t\t%s\n", floatingIP.Name) diff --git a/internal/cmd/image/describe.go b/internal/cmd/image/describe.go index d547858a..eabe5526 100644 --- a/internal/cmd/image/describe.go +++ b/internal/cmd/image/describe.go @@ -16,7 +16,7 @@ import ( "github.com/hetznercloud/hcloud-go/v2/hcloud" ) -var DescribeCmd = base.DescribeCmd{ +var DescribeCmd = base.DescribeCmd[*hcloud.Image]{ ResourceNameSingular: "image", ShortDescription: "Describe an image", JSONKeyGetByID: "image", @@ -26,7 +26,7 @@ var DescribeCmd = base.DescribeCmd{ _ = cmd.RegisterFlagCompletionFunc("architecture", cmpl.SuggestCandidates(string(hcloud.ArchitectureX86), string(hcloud.ArchitectureARM))) }, NameSuggestions: func(c hcapi2.Client) func() []string { return c.Image().Names }, - Fetch: func(s state.State, cmd *cobra.Command, idOrName string) (interface{}, interface{}, error) { + Fetch: func(s state.State, cmd *cobra.Command, idOrName string) (*hcloud.Image, any, error) { _, err := strconv.ParseInt(idOrName, 10, 64) isID := err == nil @@ -45,9 +45,7 @@ var DescribeCmd = base.DescribeCmd{ } return img, hcloud.SchemaFromImage(img), nil }, - PrintText: func(_ state.State, cmd *cobra.Command, resource interface{}) error { - image := resource.(*hcloud.Image) - + PrintText: func(_ state.State, cmd *cobra.Command, image *hcloud.Image) error { cmd.Printf("ID:\t\t%d\n", image.ID) cmd.Printf("Type:\t\t%s\n", image.Type) cmd.Printf("Status:\t\t%s\n", image.Status) diff --git a/internal/cmd/iso/describe.go b/internal/cmd/iso/describe.go index 1eac82e4..148b1441 100644 --- a/internal/cmd/iso/describe.go +++ b/internal/cmd/iso/describe.go @@ -11,22 +11,20 @@ import ( ) // DescribeCmd defines a command for describing a iso. -var DescribeCmd = base.DescribeCmd{ +var DescribeCmd = base.DescribeCmd[*hcloud.ISO]{ ResourceNameSingular: "iso", ShortDescription: "Describe a iso", JSONKeyGetByID: "iso", JSONKeyGetByName: "isos", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Location().Names }, - Fetch: func(s state.State, _ *cobra.Command, idOrName string) (interface{}, interface{}, error) { + Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.ISO, any, error) { iso, _, err := s.Client().ISO().Get(s, idOrName) if err != nil { return nil, nil, err } return iso, hcloud.SchemaFromISO(iso), nil }, - PrintText: func(_ state.State, cmd *cobra.Command, resource interface{}) error { - iso := resource.(*hcloud.ISO) - + PrintText: func(_ state.State, cmd *cobra.Command, iso *hcloud.ISO) error { cmd.Printf("ID:\t\t%d\n", iso.ID) cmd.Printf("Name:\t\t%s\n", iso.Name) cmd.Printf("Description:\t%s\n", iso.Description) diff --git a/internal/cmd/loadbalancer/describe.go b/internal/cmd/loadbalancer/describe.go index afd23363..808f21cd 100644 --- a/internal/cmd/loadbalancer/describe.go +++ b/internal/cmd/loadbalancer/describe.go @@ -12,13 +12,13 @@ import ( ) // DescribeCmd defines a command for describing a LoadBalancer. -var DescribeCmd = base.DescribeCmd{ +var DescribeCmd = base.DescribeCmd[*hcloud.LoadBalancer]{ ResourceNameSingular: "Load Balancer", ShortDescription: "Describe a Load Balancer", JSONKeyGetByID: "load_balancer", JSONKeyGetByName: "load_balancers", NameSuggestions: func(c hcapi2.Client) func() []string { return c.LoadBalancer().Names }, - Fetch: func(s state.State, _ *cobra.Command, idOrName string) (interface{}, interface{}, error) { + Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.LoadBalancer, any, error) { lb, _, err := s.Client().LoadBalancer().Get(s, idOrName) if err != nil { return nil, nil, err @@ -28,9 +28,8 @@ var DescribeCmd = base.DescribeCmd{ AdditionalFlags: func(cmd *cobra.Command) { cmd.Flags().Bool("expand-targets", false, "Expand all label_selector targets") }, - PrintText: func(s state.State, cmd *cobra.Command, resource interface{}) error { + PrintText: func(s state.State, cmd *cobra.Command, loadBalancer *hcloud.LoadBalancer) error { withLabelSelectorTargets, _ := cmd.Flags().GetBool("expand-targets") - loadBalancer := resource.(*hcloud.LoadBalancer) cmd.Printf("ID:\t\t\t\t%d\n", loadBalancer.ID) cmd.Printf("Name:\t\t\t\t%s\n", loadBalancer.Name) cmd.Printf("Created:\t\t\t%s (%s)\n", util.Datetime(loadBalancer.Created), humanize.Time(loadBalancer.Created)) diff --git a/internal/cmd/loadbalancertype/describe.go b/internal/cmd/loadbalancertype/describe.go index 5c3ea103..5561f322 100644 --- a/internal/cmd/loadbalancertype/describe.go +++ b/internal/cmd/loadbalancertype/describe.go @@ -11,22 +11,20 @@ import ( "github.com/hetznercloud/hcloud-go/v2/hcloud" ) -var DescribeCmd = base.DescribeCmd{ +var DescribeCmd = base.DescribeCmd[*hcloud.LoadBalancerType]{ ResourceNameSingular: "Load Balancer Type", ShortDescription: "Describe a Load Balancer type", JSONKeyGetByID: "load_balancer_type", JSONKeyGetByName: "load_balancer_types", NameSuggestions: func(c hcapi2.Client) func() []string { return c.LoadBalancerType().Names }, - Fetch: func(s state.State, _ *cobra.Command, idOrName string) (interface{}, interface{}, error) { + Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.LoadBalancerType, any, error) { lbt, _, err := s.Client().LoadBalancerType().Get(s, idOrName) if err != nil { return nil, nil, err } return lbt, hcloud.SchemaFromLoadBalancerType(lbt), nil }, - PrintText: func(s state.State, cmd *cobra.Command, resource interface{}) error { - loadBalancerType := resource.(*hcloud.LoadBalancerType) - + PrintText: func(s state.State, cmd *cobra.Command, loadBalancerType *hcloud.LoadBalancerType) error { cmd.Printf("ID:\t\t\t\t%d\n", loadBalancerType.ID) cmd.Printf("Name:\t\t\t\t%s\n", loadBalancerType.Name) cmd.Printf("Description:\t\t\t%s\n", loadBalancerType.Description) diff --git a/internal/cmd/location/describe.go b/internal/cmd/location/describe.go index e72ef0e7..294eddd1 100644 --- a/internal/cmd/location/describe.go +++ b/internal/cmd/location/describe.go @@ -10,22 +10,20 @@ import ( ) // DescribeCmd defines a command for describing a location. -var DescribeCmd = base.DescribeCmd{ +var DescribeCmd = base.DescribeCmd[*hcloud.Location]{ ResourceNameSingular: "location", ShortDescription: "Describe a location", JSONKeyGetByID: "location", JSONKeyGetByName: "locations", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Location().Names }, - Fetch: func(s state.State, _ *cobra.Command, idOrName string) (interface{}, interface{}, error) { + Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.Location, any, error) { l, _, err := s.Client().Location().Get(s, idOrName) if err != nil { return nil, nil, err } return l, hcloud.SchemaFromLocation(l), nil }, - PrintText: func(_ state.State, cmd *cobra.Command, resource interface{}) error { - location := resource.(*hcloud.Location) - + PrintText: func(_ state.State, cmd *cobra.Command, location *hcloud.Location) error { cmd.Printf("ID:\t\t%d\n", location.ID) cmd.Printf("Name:\t\t%s\n", location.Name) cmd.Printf("Description:\t%s\n", location.Description) diff --git a/internal/cmd/network/describe.go b/internal/cmd/network/describe.go index c599892a..37d6dc30 100644 --- a/internal/cmd/network/describe.go +++ b/internal/cmd/network/describe.go @@ -12,22 +12,20 @@ import ( ) // DescribeCmd defines a command for describing a network. -var DescribeCmd = base.DescribeCmd{ +var DescribeCmd = base.DescribeCmd[*hcloud.Network]{ ResourceNameSingular: "network", ShortDescription: "Describe a network", JSONKeyGetByID: "network", JSONKeyGetByName: "networks", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Network().Names }, - Fetch: func(s state.State, _ *cobra.Command, idOrName string) (interface{}, interface{}, error) { + Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.Network, any, error) { n, _, err := s.Client().Network().Get(s, idOrName) if err != nil { return nil, nil, err } return n, hcloud.SchemaFromNetwork(n), nil }, - PrintText: func(_ state.State, cmd *cobra.Command, resource interface{}) error { - network := resource.(*hcloud.Network) - + PrintText: func(_ state.State, cmd *cobra.Command, network *hcloud.Network) error { cmd.Printf("ID:\t\t%d\n", network.ID) cmd.Printf("Name:\t\t%s\n", network.Name) cmd.Printf("Created:\t%s (%s)\n", util.Datetime(network.Created), humanize.Time(network.Created)) diff --git a/internal/cmd/placementgroup/describe.go b/internal/cmd/placementgroup/describe.go index 23de63ec..8b9161af 100644 --- a/internal/cmd/placementgroup/describe.go +++ b/internal/cmd/placementgroup/describe.go @@ -11,22 +11,20 @@ import ( "github.com/hetznercloud/hcloud-go/v2/hcloud" ) -var DescribeCmd = base.DescribeCmd{ +var DescribeCmd = base.DescribeCmd[*hcloud.PlacementGroup]{ ResourceNameSingular: "placement group", ShortDescription: "Describe a placement group", JSONKeyGetByID: "placement_group", JSONKeyGetByName: "placement_groups", NameSuggestions: func(c hcapi2.Client) func() []string { return c.PlacementGroup().Names }, - Fetch: func(s state.State, _ *cobra.Command, idOrName string) (interface{}, interface{}, error) { + Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.PlacementGroup, any, error) { pg, _, err := s.Client().PlacementGroup().Get(s, idOrName) if err != nil { return nil, nil, err } return pg, hcloud.SchemaFromPlacementGroup(pg), nil }, - PrintText: func(s state.State, cmd *cobra.Command, resource interface{}) error { - placementGroup := resource.(*hcloud.PlacementGroup) - + PrintText: func(s state.State, cmd *cobra.Command, placementGroup *hcloud.PlacementGroup) error { cmd.Printf("ID:\t\t%d\n", placementGroup.ID) cmd.Printf("Name:\t\t%s\n", placementGroup.Name) cmd.Printf("Created:\t%s (%s)\n", util.Datetime(placementGroup.Created), humanize.Time(placementGroup.Created)) diff --git a/internal/cmd/primaryip/describe.go b/internal/cmd/primaryip/describe.go index 670628d9..6c274f94 100644 --- a/internal/cmd/primaryip/describe.go +++ b/internal/cmd/primaryip/describe.go @@ -11,22 +11,20 @@ import ( "github.com/hetznercloud/hcloud-go/v2/hcloud" ) -var DescribeCmd = base.DescribeCmd{ +var DescribeCmd = base.DescribeCmd[*hcloud.PrimaryIP]{ ResourceNameSingular: "Primary IP", ShortDescription: "Describe an Primary IP", JSONKeyGetByID: "primary_ip", JSONKeyGetByName: "primary_ips", NameSuggestions: func(c hcapi2.Client) func() []string { return c.PrimaryIP().Names }, - Fetch: func(s state.State, _ *cobra.Command, idOrName string) (interface{}, interface{}, error) { + Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.PrimaryIP, any, error) { ip, _, err := s.Client().PrimaryIP().Get(s, idOrName) if err != nil { return nil, nil, err } return ip, hcloud.SchemaFromPrimaryIP(ip), nil }, - PrintText: func(_ state.State, cmd *cobra.Command, resource interface{}) error { - primaryIP := resource.(*hcloud.PrimaryIP) - + PrintText: func(_ state.State, cmd *cobra.Command, primaryIP *hcloud.PrimaryIP) error { cmd.Printf("ID:\t\t%d\n", primaryIP.ID) cmd.Printf("Name:\t\t%s\n", primaryIP.Name) cmd.Printf("Created:\t%s (%s)\n", util.Datetime(primaryIP.Created), humanize.Time(primaryIP.Created)) diff --git a/internal/cmd/server/describe.go b/internal/cmd/server/describe.go index f775390f..b7a593a5 100644 --- a/internal/cmd/server/describe.go +++ b/internal/cmd/server/describe.go @@ -13,22 +13,20 @@ import ( "github.com/hetznercloud/hcloud-go/v2/hcloud" ) -var DescribeCmd = base.DescribeCmd{ +var DescribeCmd = base.DescribeCmd[*hcloud.Server]{ ResourceNameSingular: "server", ShortDescription: "Describe a server", JSONKeyGetByID: "server", JSONKeyGetByName: "servers", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Server().Names }, - Fetch: func(s state.State, _ *cobra.Command, idOrName string) (interface{}, interface{}, error) { + Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.Server, any, error) { srv, _, err := s.Client().Server().Get(s, idOrName) if err != nil { return nil, nil, err } return srv, hcloud.SchemaFromServer(srv), nil }, - PrintText: func(s state.State, cmd *cobra.Command, resource interface{}) error { - server := resource.(*hcloud.Server) - + PrintText: func(s state.State, cmd *cobra.Command, server *hcloud.Server) error { cmd.Printf("ID:\t\t%d\n", server.ID) cmd.Printf("Name:\t\t%s\n", server.Name) cmd.Printf("Status:\t\t%s\n", server.Status) diff --git a/internal/cmd/servertype/describe.go b/internal/cmd/servertype/describe.go index 00f749f5..29510e24 100644 --- a/internal/cmd/servertype/describe.go +++ b/internal/cmd/servertype/describe.go @@ -11,22 +11,20 @@ import ( "github.com/hetznercloud/hcloud-go/v2/hcloud" ) -var DescribeCmd = base.DescribeCmd{ +var DescribeCmd = base.DescribeCmd[*hcloud.ServerType]{ ResourceNameSingular: "serverType", ShortDescription: "Describe a server type", JSONKeyGetByID: "server_type", JSONKeyGetByName: "server_types", NameSuggestions: func(c hcapi2.Client) func() []string { return c.ServerType().Names }, - Fetch: func(s state.State, _ *cobra.Command, idOrName string) (interface{}, interface{}, error) { + Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.ServerType, any, error) { st, _, err := s.Client().ServerType().Get(s, idOrName) if err != nil { return nil, nil, err } return st, hcloud.SchemaFromServerType(st), nil }, - PrintText: func(s state.State, cmd *cobra.Command, resource interface{}) error { - serverType := resource.(*hcloud.ServerType) - + PrintText: func(s state.State, cmd *cobra.Command, serverType *hcloud.ServerType) error { cmd.Printf("ID:\t\t\t%d\n", serverType.ID) cmd.Printf("Name:\t\t\t%s\n", serverType.Name) cmd.Printf("Description:\t\t%s\n", serverType.Description) diff --git a/internal/cmd/sshkey/describe.go b/internal/cmd/sshkey/describe.go index 92175877..024276c4 100644 --- a/internal/cmd/sshkey/describe.go +++ b/internal/cmd/sshkey/describe.go @@ -13,21 +13,20 @@ import ( "github.com/hetznercloud/hcloud-go/v2/hcloud" ) -var DescribeCmd = base.DescribeCmd{ +var DescribeCmd = base.DescribeCmd[*hcloud.SSHKey]{ ResourceNameSingular: "SSH Key", ShortDescription: "Describe a SSH Key", JSONKeyGetByID: "ssh_key", JSONKeyGetByName: "ssh_keys", NameSuggestions: func(c hcapi2.Client) func() []string { return c.SSHKey().Names }, - Fetch: func(s state.State, _ *cobra.Command, idOrName string) (interface{}, interface{}, error) { + Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.SSHKey, any, error) { key, _, err := s.Client().SSHKey().Get(s, idOrName) if err != nil { return nil, nil, err } return key, hcloud.SchemaFromSSHKey(key), nil }, - PrintText: func(_ state.State, cmd *cobra.Command, resource interface{}) error { - sshKey := resource.(*hcloud.SSHKey) + PrintText: func(_ state.State, cmd *cobra.Command, sshKey *hcloud.SSHKey) error { cmd.Printf("ID:\t\t%d\n", sshKey.ID) cmd.Printf("Name:\t\t%s\n", sshKey.Name) cmd.Printf("Created:\t%s (%s)\n", util.Datetime(sshKey.Created), humanize.Time(sshKey.Created)) diff --git a/internal/cmd/volume/describe.go b/internal/cmd/volume/describe.go index cebe5d2f..f99d4f26 100644 --- a/internal/cmd/volume/describe.go +++ b/internal/cmd/volume/describe.go @@ -11,22 +11,20 @@ import ( "github.com/hetznercloud/hcloud-go/v2/hcloud" ) -var DescribeCmd = base.DescribeCmd{ +var DescribeCmd = base.DescribeCmd[*hcloud.Volume]{ ResourceNameSingular: "volume", ShortDescription: "Describe an Volume", JSONKeyGetByID: "volume", JSONKeyGetByName: "volumes", NameSuggestions: func(c hcapi2.Client) func() []string { return c.Volume().Names }, - Fetch: func(s state.State, _ *cobra.Command, idOrName string) (interface{}, interface{}, error) { + Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.Volume, any, error) { v, _, err := s.Client().Volume().Get(s, idOrName) if err != nil { return nil, nil, err } return v, hcloud.SchemaFromVolume(v), nil }, - PrintText: func(s state.State, cmd *cobra.Command, resource interface{}) error { - volume := resource.(*hcloud.Volume) - + PrintText: func(s state.State, cmd *cobra.Command, volume *hcloud.Volume) error { cmd.Printf("ID:\t\t%d\n", volume.ID) cmd.Printf("Name:\t\t%s\n", volume.Name) cmd.Printf("Created:\t%s (%s)\n", util.Datetime(volume.Created), humanize.Time(volume.Created))