Skip to content

Commit

Permalink
Move certificate commands to new structure (#334)
Browse files Browse the repository at this point in the history
Signed-off-by: Lukas Kämmerling <[email protected]>
  • Loading branch information
LKaemmerling authored Jun 23, 2021
1 parent 39f4786 commit fe852a5
Show file tree
Hide file tree
Showing 18 changed files with 1,161 additions and 411 deletions.
6 changes: 6 additions & 0 deletions internal/cmd/base/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,17 @@ func (lc *LabelCmds) RunAdd(ctx context.Context, client hcapi2.Client, cmd *cobr
if err != nil {
return err
}

if labels == nil {
labels = map[string]string{}
}

key, val := util.SplitLabelVars(args[1])

if _, ok := labels[key]; ok && !overwrite {
return fmt.Errorf("label %s on %s %d already exists", key, lc.ResourceNameSingular, id)
}

labels[key] = val

if err := lc.SetLabels(ctx, client, id, labels); err != nil {
Expand Down
68 changes: 0 additions & 68 deletions internal/cmd/certificate/add_label.go

This file was deleted.

11 changes: 6 additions & 5 deletions internal/cmd/certificate/certificate.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package certificate

import (
"github.com/hetznercloud/cli/internal/hcapi2"
"github.com/hetznercloud/cli/internal/state"
"github.com/spf13/cobra"
)
Expand All @@ -14,13 +15,13 @@ func NewCommand(cli *state.State) *cobra.Command {
DisableFlagsInUseLine: true,
}
cmd.AddCommand(
newListCommand(cli),
listCmd.CobraCommand(cli.Context, hcapi2.NewClient(cli.Client()), cli),
newCreateCommand(cli),
newUpdateCommand(cli),
newAddLabelCommand(cli),
newRemoveLabelCommand(cli),
newDeleteCommand(cli),
newDescribeCommand(cli),
labelCmds.AddCobraCommand(cli.Context, hcapi2.NewClient(cli.Client()), cli),
labelCmds.RemoveCobraCommand(cli.Context, hcapi2.NewClient(cli.Client()), cli),
deleteCmd.CobraCommand(cli.Context, hcapi2.NewClient(cli.Client()), cli),
describeCmd.CobraCommand(cli.Context, hcapi2.NewClient(cli.Client()), cli),
)

return cmd
Expand Down
50 changes: 18 additions & 32 deletions internal/cmd/certificate/delete.go
Original file line number Diff line number Diff line change
@@ -1,39 +1,25 @@
package certificate

import (
"fmt"
"context"

"github.com/hetznercloud/cli/internal/cmd/cmpl"
"github.com/hetznercloud/cli/internal/state"
"github.com/spf13/cobra"
"github.com/hetznercloud/cli/internal/cmd/base"
"github.com/hetznercloud/cli/internal/hcapi2"
"github.com/hetznercloud/hcloud-go/hcloud"
)

func newDeleteCommand(cli *state.State) *cobra.Command {
return &cobra.Command{
Use: "delete CERTIFICATE",
Short: "Delete a certificate",
Args: cobra.ExactArgs(1),
ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(cli.CertificateNames)),
TraverseChildren: true,
DisableFlagsInUseLine: true,
PreRunE: cli.EnsureToken,
RunE: cli.Wrap(runDelete),
}
}

func runDelete(cli *state.State, cmd *cobra.Command, args []string) error {
idOrName := args[0]
cert, _, err := cli.Client().Certificate.Get(cli.Context, idOrName)
if err != nil {
return err
}
if cert == nil {
return fmt.Errorf("Certificate %s not found", idOrName)
}
_, err = cli.Client().Certificate.Delete(cli.Context, cert)
if err != nil {
return err
}
fmt.Printf("Certificate %d deleted\n", cert.ID)
return nil
var deleteCmd = base.DeleteCmd{
ResourceNameSingular: "certificate",
ShortDescription: "Delete a certificate",
NameSuggestions: func(c hcapi2.Client) func() []string { return c.Firewall().Names },
Fetch: func(ctx context.Context, client hcapi2.Client, idOrName string) (interface{}, *hcloud.Response, error) {
return client.Certificate().Get(ctx, idOrName)
},
Delete: func(ctx context.Context, client hcapi2.Client, resource interface{}) error {
certificate := resource.(*hcloud.Certificate)
if _, err := client.Certificate().Delete(ctx, certificate); err != nil {
return err
}
return nil
},
}
155 changes: 57 additions & 98 deletions internal/cmd/certificate/describe.go
Original file line number Diff line number Diff line change
@@ -1,112 +1,71 @@
package certificate

import (
"encoding/json"
"context"
"fmt"

humanize "github.com/dustin/go-humanize"
"github.com/hetznercloud/cli/internal/cmd/cmpl"
"github.com/hetznercloud/cli/internal/cmd/output"
"github.com/hetznercloud/cli/internal/cmd/base"
"github.com/hetznercloud/cli/internal/hcapi2"

"github.com/dustin/go-humanize"
"github.com/hetznercloud/cli/internal/cmd/util"
"github.com/hetznercloud/cli/internal/state"
"github.com/hetznercloud/hcloud-go/hcloud"
"github.com/spf13/cobra"
)

func newDescribeCommand(cli *state.State) *cobra.Command {
cmd := &cobra.Command{
Use: "describe [FLAGS] CERTIFICATE",
Short: "Describe a certificate",
Args: cobra.ExactArgs(1),
ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(cli.CertificateNames)),
TraverseChildren: true,
DisableFlagsInUseLine: true,
PreRunE: cli.EnsureToken,
RunE: cli.Wrap(runDescribe),
}
output.AddFlag(cmd, output.OptionJSON(), output.OptionFormat())
return cmd
}

func runDescribe(cli *state.State, cmd *cobra.Command, args []string) error {
outputFlags := output.FlagsForCommand(cmd)

idOrName := args[0]
cert, resp, err := cli.Client().Certificate.Get(cli.Context, idOrName)
if err != nil {
return err
}
if cert == nil {
return fmt.Errorf("certificate not found: %s", idOrName)
}

switch {
case outputFlags.IsSet("json"):
return describeJSON(resp)
case outputFlags.IsSet("format"):
return util.DescribeFormat(cert, outputFlags["format"][0])
default:
return describeText(cli, cert)
}
}

func describeJSON(resp *hcloud.Response) error {
var data map[string]interface{}
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
return err
}
if server, ok := data["certificate"]; ok {
return util.DescribeJSON(server)
}
if servers, ok := data["certificates"].([]interface{}); ok {
return util.DescribeJSON(servers[0])
}
return util.DescribeJSON(data)
}

func describeText(cli *state.State, cert *hcloud.Certificate) error {
fmt.Printf("ID:\t\t\t%d\n", cert.ID)
fmt.Printf("Name:\t\t\t%s\n", cert.Name)
fmt.Printf("Type:\t\t\t%s\n", cert.Type)
fmt.Printf("Fingerprint:\t\t%s\n", cert.Fingerprint)
fmt.Printf("Created:\t\t%s (%s)\n", util.Datetime(cert.Created), humanize.Time(cert.Created))
fmt.Printf("Not valid before:\t%s (%s)\n", util.Datetime(cert.NotValidBefore), humanize.Time(cert.NotValidBefore))
fmt.Printf("Not valid after:\t%s (%s)\n", util.Datetime(cert.NotValidAfter), humanize.Time(cert.NotValidAfter))
if cert.Status != nil {
fmt.Printf("Status:\n")
fmt.Printf(" Issuance: %s\n", cert.Status.Issuance)
fmt.Printf(" Renewal: %s\n", cert.Status.Renewal)
if cert.Status.IsFailed() {
fmt.Printf(" Failure reason: %s\n", cert.Status.Error.Message)
var describeCmd = base.DescribeCmd{
ResourceNameSingular: "certificate",
ShortDescription: "Describe an certificate",
JSONKeyGetByID: "certificate",
JSONKeyGetByName: "certificates",
NameSuggestions: func(c hcapi2.Client) func() []string { return c.Certificate().Names },
Fetch: func(ctx context.Context, client hcapi2.Client, idOrName string) (interface{}, *hcloud.Response, error) {
return client.Certificate().Get(ctx, idOrName)
},
PrintText: func(_ context.Context, client hcapi2.Client, resource interface{}) error {
cert := resource.(*hcloud.Certificate)
fmt.Printf("ID:\t\t\t%d\n", cert.ID)
fmt.Printf("Name:\t\t\t%s\n", cert.Name)
fmt.Printf("Type:\t\t\t%s\n", cert.Type)
fmt.Printf("Fingerprint:\t\t%s\n", cert.Fingerprint)
fmt.Printf("Created:\t\t%s (%s)\n", util.Datetime(cert.Created), humanize.Time(cert.Created))
fmt.Printf("Not valid before:\t%s (%s)\n", util.Datetime(cert.NotValidBefore), humanize.Time(cert.NotValidBefore))
fmt.Printf("Not valid after:\t%s (%s)\n", util.Datetime(cert.NotValidAfter), humanize.Time(cert.NotValidAfter))
if cert.Status != nil {
fmt.Printf("Status:\n")
fmt.Printf(" Issuance: %s\n", cert.Status.Issuance)
fmt.Printf(" Renewal: %s\n", cert.Status.Renewal)
if cert.Status.IsFailed() {
fmt.Printf(" Failure reason: %s\n", cert.Status.Error.Message)
}
}
fmt.Printf("Domain names:\n")
for _, domainName := range cert.DomainNames {
fmt.Printf(" - %s\n", domainName)
}
}
fmt.Printf("Domain names:\n")
for _, domainName := range cert.DomainNames {
fmt.Printf(" - %s\n", domainName)
}
fmt.Print("Labels:\n")
if len(cert.Labels) == 0 {
fmt.Print(" No labels\n")
} else {
for key, value := range cert.Labels {
fmt.Printf(" %s:\t%s\n", key, value)
fmt.Print("Labels:\n")
if len(cert.Labels) == 0 {
fmt.Print(" No labels\n")
} else {
for key, value := range cert.Labels {
fmt.Printf(" %s:\t%s\n", key, value)
}
}
}
fmt.Println("Used By:")
if len(cert.UsedBy) == 0 {
fmt.Println(" Certificate unused")
} else {
for _, ub := range cert.UsedBy {
fmt.Printf(" - Type: %s", ub.Type)
// Currently certificates can be only attached to load balancers.
// If we ever get something that is not a load balancer fall back
// to printing the ID.
if ub.Type != hcloud.CertificateUsedByRefTypeLoadBalancer {
fmt.Printf(" - ID: %d", ub.ID)
continue
fmt.Println("Used By:")
if len(cert.UsedBy) == 0 {
fmt.Println(" Certificate unused")
} else {
for _, ub := range cert.UsedBy {
fmt.Printf(" - Type: %s", ub.Type)
// Currently certificates can be only attached to load balancers.
// If we ever get something that is not a load balancer fall back
// to printing the ID.
if ub.Type != hcloud.CertificateUsedByRefTypeLoadBalancer {
fmt.Printf(" - ID: %d", ub.ID)
continue
}
fmt.Printf(" - Name: %s", client.LoadBalancer().LoadBalancerName(ub.ID))
}
fmt.Printf(" - Name: %s", cli.LoadBalancerName(ub.ID))
}
}
return nil
return nil
},
}
35 changes: 35 additions & 0 deletions internal/cmd/certificate/labels.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package certificate

import (
"context"
"fmt"

"github.com/hetznercloud/cli/internal/cmd/base"
"github.com/hetznercloud/cli/internal/hcapi2"
"github.com/hetznercloud/hcloud-go/hcloud"
)

var labelCmds = base.LabelCmds{
ResourceNameSingular: "certificate",
ShortDescriptionAdd: "Add a label to an certificate",
ShortDescriptionRemove: "Remove a label from an certificate",
NameSuggestions: func(c hcapi2.Client) func() []string { return c.Certificate().Names },
LabelKeySuggestions: func(c hcapi2.Client) func(idOrName string) []string { return c.Certificate().LabelKeys },
FetchLabels: func(ctx context.Context, client hcapi2.Client, idOrName string) (map[string]string, int, error) {
certificate, _, err := client.Certificate().Get(ctx, idOrName)
if err != nil {
return nil, 0, err
}
if certificate == nil {
return nil, 0, fmt.Errorf("certificate not found: %s", idOrName)
}
return certificate.Labels, certificate.ID, nil
},
SetLabels: func(ctx context.Context, client hcapi2.Client, id int, labels map[string]string) error {
opts := hcloud.CertificateUpdateOpts{
Labels: labels,
}
_, _, err := client.Certificate().Update(ctx, &hcloud.Certificate{ID: id}, opts)
return err
},
}
Loading

0 comments on commit fe852a5

Please sign in to comment.