Skip to content

Commit a3d5c32

Browse files
committed
Add vpn command
1 parent b67bc1e commit a3d5c32

42 files changed

Lines changed: 1013 additions & 30 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package v1
1+
package v2
22

33
import (
44
"github.com/metal-stack/cli/cmd/config"
@@ -21,6 +21,8 @@ func AddCmds(cmd *cobra.Command, c *config.Config) {
2121
adminCmd.AddCommand(newTenantCmd(c))
2222
adminCmd.AddCommand(newTokenCmd(c))
2323
adminCmd.AddCommand(newProjectCmd(c))
24+
adminCmd.AddCommand(newVPNCmd(c))
25+
adminCmd.AddCommand(newMachineCmd(c))
2426

2527
cmd.AddCommand(adminCmd)
2628
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package v1
1+
package v2
22

33
import (
44
"fmt"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package v1
1+
package v2
22

33
import (
44
adminv2 "github.com/metal-stack/api/go/metalstack/admin/v2"

cmd/admin/v2/machine.go

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package v2
2+
3+
import (
4+
"fmt"
5+
6+
adminv2 "github.com/metal-stack/api/go/metalstack/admin/v2"
7+
apiv2 "github.com/metal-stack/api/go/metalstack/api/v2"
8+
"github.com/metal-stack/cli/cmd/config"
9+
"github.com/metal-stack/cli/cmd/sorters"
10+
"github.com/metal-stack/metal-lib/pkg/genericcli"
11+
"github.com/metal-stack/metal-lib/pkg/genericcli/printers"
12+
"github.com/spf13/cobra"
13+
"github.com/spf13/viper"
14+
)
15+
16+
type machine struct {
17+
c *config.Config
18+
}
19+
20+
func newMachineCmd(c *config.Config) *cobra.Command {
21+
w := &machine{
22+
c: c,
23+
}
24+
25+
cmdsConfig := &genericcli.CmdsConfig[any, any, *apiv2.Machine]{
26+
BinaryName: config.BinaryName,
27+
GenericCLI: genericcli.NewGenericCLI(w).WithFS(c.Fs),
28+
Singular: "machine",
29+
Plural: "machines",
30+
Description: "an machine of metal-stack.io",
31+
Sorter: sorters.MachineSorter(),
32+
DescribePrinter: func() printers.Printer { return c.DescribePrinter },
33+
ListPrinter: func() printers.Printer { return c.ListPrinter },
34+
ListCmdMutateFn: func(cmd *cobra.Command) {
35+
cmd.Flags().StringP("project", "p", "", "project from where machines should be listed")
36+
37+
genericcli.Must(cmd.RegisterFlagCompletionFunc("project", c.Completion.ProjectListCompletion))
38+
},
39+
DescribeCmdMutateFn: func(cmd *cobra.Command) {
40+
cmd.Flags().StringP("project", "p", "", "project of the machine")
41+
42+
genericcli.Must(cmd.RegisterFlagCompletionFunc("project", c.Completion.ProjectListCompletion))
43+
},
44+
ValidArgsFn: c.Completion.MachineListCompletion,
45+
}
46+
47+
bmcCommandCmd := &cobra.Command{
48+
Use: "bmc-command",
49+
Short: "send a command to the bmc of a machine",
50+
RunE: func(cmd *cobra.Command, args []string) error {
51+
return w.bmcCommand()
52+
},
53+
}
54+
bmcCommandCmd.Flags().String("id", "", "id of the machine where the command should be sent to")
55+
bmcCommandCmd.Flags().String("command", "", "the actual command to send to the machine")
56+
bmcCommandCmd.RegisterFlagCompletionFunc("id", c.Completion.MachineListCompletion)
57+
bmcCommandCmd.RegisterFlagCompletionFunc("command", c.Completion.BMCCommandListCompletion)
58+
genericcli.Must(bmcCommandCmd.MarkFlagRequired("id"))
59+
genericcli.Must(bmcCommandCmd.MarkFlagRequired("command"))
60+
61+
return genericcli.NewCmds(cmdsConfig, bmcCommandCmd)
62+
}
63+
64+
func (c *machine) bmcCommand() error {
65+
ctx, cancel := c.c.NewRequestContext()
66+
defer cancel()
67+
68+
commandString := viper.GetString("command")
69+
70+
cmd, ok := apiv2.MachineBMCCommand_value[commandString]
71+
if !ok {
72+
return fmt.Errorf("unknown command: %s", commandString)
73+
}
74+
_, err := c.c.Client.Adminv2().Machine().BMCCommand(ctx, &adminv2.MachineServiceBMCCommandRequest{
75+
Uuid: viper.GetString("id"),
76+
Command: apiv2.MachineBMCCommand(cmd),
77+
})
78+
if err != nil {
79+
return err
80+
}
81+
return err
82+
}
83+
84+
func (c *machine) updateFromCLI(args []string) (any, error) {
85+
panic("unimplemented")
86+
}
87+
88+
func (c *machine) Create(rq any) (*apiv2.Machine, error) {
89+
panic("unimplemented")
90+
}
91+
92+
func (c *machine) Delete(id string) (*apiv2.Machine, error) {
93+
panic("unimplemented")
94+
}
95+
96+
func (c *machine) Get(id string) (*apiv2.Machine, error) {
97+
ctx, cancel := c.c.NewRequestContext()
98+
defer cancel()
99+
100+
resp, err := c.c.Client.Adminv2().Machine().Get(ctx, &adminv2.MachineServiceGetRequest{
101+
Uuid: id,
102+
})
103+
if err != nil {
104+
return nil, err
105+
}
106+
107+
return resp.Machine, nil
108+
}
109+
110+
func (c *machine) List() ([]*apiv2.Machine, error) {
111+
ctx, cancel := c.c.NewRequestContext()
112+
defer cancel()
113+
114+
resp, err := c.c.Client.Adminv2().Machine().List(ctx, &adminv2.MachineServiceListRequest{
115+
Query: &apiv2.MachineQuery{
116+
// FIXME implement
117+
},
118+
})
119+
if err != nil {
120+
return nil, err
121+
}
122+
123+
return resp.Machines, nil
124+
}
125+
126+
func (c *machine) Update(rq any) (*apiv2.Machine, error) {
127+
panic("unimplemented")
128+
}
129+
130+
func (c *machine) Convert(r *apiv2.Machine) (string, any, any, error) {
131+
panic("unimplemented")
132+
133+
}
134+
135+
func (c *machine) MachineResponseToCreate(r *apiv2.Machine) any {
136+
panic("unimplemented")
137+
}
138+
139+
func (c *machine) MachineResponseToUpdate(desired *apiv2.Machine) (any, error) {
140+
panic("unimplemented")
141+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package v1
1+
package v2
22

33
import (
44
"github.com/metal-stack/api/go/enum"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package v1
1+
package v2
22

33
import (
44
"fmt"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package v1
1+
package v2
22

33
import (
44
"fmt"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package v1
1+
package v2
22

33
import (
44
"fmt"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package v1
1+
package v2
22

33
import (
44
"fmt"

cmd/admin/v2/vpn.go

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package v2
2+
3+
import (
4+
"fmt"
5+
"time"
6+
7+
adminv2 "github.com/metal-stack/api/go/metalstack/admin/v2"
8+
apiv2 "github.com/metal-stack/api/go/metalstack/api/v2"
9+
"github.com/metal-stack/cli/cmd/config"
10+
"github.com/metal-stack/metal-lib/pkg/genericcli"
11+
"github.com/metal-stack/metal-lib/pkg/genericcli/printers"
12+
"github.com/metal-stack/metal-lib/pkg/pointer"
13+
"github.com/spf13/cobra"
14+
"github.com/spf13/viper"
15+
"google.golang.org/protobuf/types/known/durationpb"
16+
)
17+
18+
type vpn struct {
19+
c *config.Config
20+
}
21+
22+
func newVPNCmd(c *config.Config) *cobra.Command {
23+
w := &vpn{
24+
c: c,
25+
}
26+
27+
cmdsConfig := &genericcli.CmdsConfig[any, any, *apiv2.VPNNode]{
28+
BinaryName: config.BinaryName,
29+
GenericCLI: genericcli.NewGenericCLI(w).WithFS(c.Fs),
30+
Singular: "vpn",
31+
Plural: "vpn",
32+
Description: "manage vpn keys and list nodes connected",
33+
DescribePrinter: func() printers.Printer { return c.DescribePrinter },
34+
ListPrinter: func() printers.Printer { return c.ListPrinter },
35+
ListCmdMutateFn: func(cmd *cobra.Command) {
36+
cmd.Flags().String("project", "", "the project for which vpn nodes should be listed")
37+
},
38+
OnlyCmds: genericcli.OnlyCmds(genericcli.ListCmd),
39+
ValidArgsFn: w.c.Completion.ProjectListCompletion,
40+
}
41+
42+
authKeyCmd := &cobra.Command{
43+
Use: "authkey",
44+
Short: "generate a authkey to connect to the vpn",
45+
RunE: func(cmd *cobra.Command, args []string) error {
46+
return w.authKey()
47+
},
48+
ValidArgsFunction: c.Completion.ProjectListCompletion,
49+
}
50+
authKeyCmd.Flags().String("project", "", "the project for which the authkey should be generated")
51+
authKeyCmd.Flags().Bool("ephemeral", true, "ephemeral defines if the key can only be used once")
52+
authKeyCmd.Flags().Duration("expires", 1*time.Hour, "the duration after the generated key is not valid anymore")
53+
genericcli.Must(authKeyCmd.MarkFlagRequired("project"))
54+
55+
return genericcli.NewCmds(cmdsConfig, authKeyCmd)
56+
}
57+
58+
func (v *vpn) authKey() error {
59+
ctx, cancel := v.c.NewRequestContext()
60+
defer cancel()
61+
62+
req := &adminv2.VPNServiceAuthKeyRequest{
63+
Project: viper.GetString("project"),
64+
Ephemeral: viper.GetBool("ephemeral"),
65+
Expires: durationpb.New(viper.GetDuration("expires")),
66+
}
67+
68+
resp, err := v.c.Client.Adminv2().VPN().AuthKey(ctx, req)
69+
if err != nil {
70+
return err
71+
}
72+
73+
_, _ = fmt.Fprintf(v.c.Out, "authkey: %s\n", resp.AuthKey)
74+
_, _ = fmt.Fprintf(v.c.Out, "vpn endpoint: %s\n", resp.Address)
75+
76+
return nil
77+
}
78+
79+
func (v *vpn) Get(id string) (*apiv2.VPNNode, error) {
80+
panic("unimplemented")
81+
}
82+
83+
func (v *vpn) List() ([]*apiv2.VPNNode, error) {
84+
ctx, cancel := v.c.NewRequestContext()
85+
defer cancel()
86+
87+
req := &adminv2.VPNServiceListNodesRequest{}
88+
89+
if viper.IsSet("project") {
90+
req.Project = pointer.Pointer(viper.GetString("project"))
91+
}
92+
93+
resp, err := v.c.Client.Adminv2().VPN().ListNodes(ctx, req)
94+
if err != nil {
95+
return nil, fmt.Errorf("failed to list vpn nodes: %w", err)
96+
}
97+
98+
return resp.Nodes, nil
99+
}
100+
101+
func (v *vpn) Create(rq any) (*apiv2.VPNNode, error) {
102+
panic("unimplemented")
103+
}
104+
105+
func (v *vpn) Delete(id string) (*apiv2.VPNNode, error) {
106+
panic("unimplemented")
107+
}
108+
109+
func (v *vpn) Convert(r *apiv2.VPNNode) (string, any, any, error) {
110+
panic("unimplemented")
111+
}
112+
113+
func (v *vpn) Update(rq any) (*apiv2.VPNNode, error) {
114+
panic("unimplemented")
115+
}

0 commit comments

Comments
 (0)