Skip to content
Open
6 changes: 3 additions & 3 deletions .github/workflows/docker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v5
uses: actions/checkout@v6

- name: Setup Go
uses: actions/setup-go@v6
Expand All @@ -30,7 +30,7 @@ jobs:
cache: false

- name: Lint
uses: golangci/golangci-lint-action@v8
uses: golangci/golangci-lint-action@v9
with:
args: --build-tags integration --timeout=5m

Expand Down Expand Up @@ -58,7 +58,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v5
uses: actions/checkout@v6

- name: Setup Go
uses: actions/setup-go@v6
Expand Down
8 changes: 7 additions & 1 deletion cmd/admin/v2/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,15 @@ func AddCmds(cmd *cobra.Command, c *config.Config) {
}

adminCmd.AddCommand(newImageCmd(c))
adminCmd.AddCommand(newIPCmd(c))
adminCmd.AddCommand(newMachineCmd(c))
adminCmd.AddCommand(newNetworkCmd(c))
adminCmd.AddCommand(newProjectCmd(c))
adminCmd.AddCommand(newSizeCmd(c))
adminCmd.AddCommand(newTaskCmd(c))
adminCmd.AddCommand(newTenantCmd(c))
adminCmd.AddCommand(newTokenCmd(c))
adminCmd.AddCommand(newProjectCmd(c))
adminCmd.AddCommand(newVPNCmd(c))

cmd.AddCommand(adminCmd)
}
74 changes: 74 additions & 0 deletions cmd/admin/v2/ip.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package v2

import (
adminv2 "github.com/metal-stack/api/go/metalstack/admin/v2"
apiv2 "github.com/metal-stack/api/go/metalstack/api/v2"
"github.com/metal-stack/cli/cmd/config"
"github.com/metal-stack/cli/cmd/sorters"
"github.com/metal-stack/metal-lib/pkg/genericcli"
"github.com/metal-stack/metal-lib/pkg/genericcli/printers"
"github.com/spf13/cobra"
)

type ip struct {
c *config.Config
}

func newIPCmd(c *config.Config) *cobra.Command {
w := &ip{
c: c,
}

cmdsConfig := &genericcli.CmdsConfig[any, any, *apiv2.IP]{
BinaryName: config.BinaryName,
GenericCLI: genericcli.NewGenericCLI(w).WithFS(c.Fs),
Singular: "ip",
Plural: "ips",
Description: "manage ip addresses",
Sorter: sorters.IPSorter(),
DescribePrinter: func() printers.Printer { return c.DescribePrinter },
ListPrinter: func() printers.Printer { return c.ListPrinter },
OnlyCmds: genericcli.OnlyCmds(genericcli.ListCmd),
ListCmdMutateFn: func(cmd *cobra.Command) {
cmd.Flags().String("ip", "", "ipaddress to filter [optional]")
cmd.Flags().String("name", "", "name to filter [optional]")
cmd.Flags().String("network", "", "network to filter [optional]")
cmd.Flags().String("description", "", "description to filter [optional]")
genericcli.Must(cmd.RegisterFlagCompletionFunc("network", c.Completion.NetworkListCompletion))
},
ValidArgsFn: c.Completion.IpListCompletion,
}

return genericcli.NewCmds(cmdsConfig)
}

func (c *ip) List() ([]*apiv2.IP, error) {
ctx, cancel := c.c.NewRequestContext()
defer cancel()

resp, err := c.c.Client.Adminv2().IP().List(ctx, &adminv2.IPServiceListRequest{
Query: &apiv2.IPQuery{},
})
if err != nil {
return nil, err
}

return resp.Ips, nil
}

func (t *ip) Get(id string) (*apiv2.IP, error) {
panic("unimplemented")
}
func (c *ip) Delete(id string) (*apiv2.IP, error) {
panic("unimplemented")
}
func (t *ip) Create(rq any) (*apiv2.IP, error) {
panic("unimplemented")
}
func (t *ip) Convert(r *apiv2.IP) (string, any, any, error) {
panic("unimplemented")
}

func (t *ip) Update(rq any) (*apiv2.IP, error) {
panic("unimplemented")
}
187 changes: 187 additions & 0 deletions cmd/admin/v2/machine.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
package v2

import (
"fmt"

adminv2 "github.com/metal-stack/api/go/metalstack/admin/v2"
apiv2 "github.com/metal-stack/api/go/metalstack/api/v2"
"github.com/metal-stack/cli/cmd/config"
"github.com/metal-stack/cli/cmd/sorters"
"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/spf13/cobra"
"github.com/spf13/viper"
)

type machine struct {
c *config.Config
}

func newMachineCmd(c *config.Config) *cobra.Command {
w := &machine{
c: c,
}

cmdsConfig := &genericcli.CmdsConfig[any, any, *apiv2.Machine]{
BinaryName: config.BinaryName,
GenericCLI: genericcli.NewGenericCLI(w).WithFS(c.Fs),
Singular: "machine",
Plural: "machines",
Description: "manage machines",
Sorter: sorters.MachineSorter(),
DescribePrinter: func() printers.Printer { return c.DescribePrinter },
ListPrinter: func() printers.Printer { return c.ListPrinter },
ListCmdMutateFn: func(cmd *cobra.Command) {
cmd.Flags().StringP("project", "p", "", "project from where machines should be listed")

genericcli.Must(cmd.RegisterFlagCompletionFunc("project", c.Completion.ProjectListCompletion))
},
DescribeCmdMutateFn: func(cmd *cobra.Command) {
cmd.Flags().StringP("project", "p", "", "project of the machine")

genericcli.Must(cmd.RegisterFlagCompletionFunc("project", c.Completion.ProjectListCompletion))
},
ValidArgsFn: c.Completion.MachineListCompletion,
}

bmcCommandCmd := &cobra.Command{
Use: "bmc-command",
Short: "send a command to the bmc of a machine",
RunE: func(cmd *cobra.Command, args []string) error {
return w.bmcCommand()
},
}
bmcCommandCmd.Flags().String("id", "", "id of the machine where the command should be sent to")
bmcCommandCmd.Flags().String("command", "", "the actual command to send to the machine")
genericcli.Must(bmcCommandCmd.RegisterFlagCompletionFunc("id", c.Completion.MachineListCompletion))
genericcli.Must(bmcCommandCmd.RegisterFlagCompletionFunc("command", c.Completion.BMCCommandListCompletion))
genericcli.Must(bmcCommandCmd.MarkFlagRequired("id"))
genericcli.Must(bmcCommandCmd.MarkFlagRequired("command"))

return genericcli.NewCmds(cmdsConfig, bmcCommandCmd)
}

func (c *machine) bmcCommand() error {
ctx, cancel := c.c.NewRequestContext()
defer cancel()

commandString := viper.GetString("command")

cmd, ok := apiv2.MachineBMCCommand_value[commandString]
if !ok {
return fmt.Errorf("unknown command: %s", commandString)
}
_, err := c.c.Client.Adminv2().Machine().BMCCommand(ctx, &adminv2.MachineServiceBMCCommandRequest{
Uuid: viper.GetString("id"),
Command: apiv2.MachineBMCCommand(cmd),
})
if err != nil {
return err
}
return err
}

func (c *machine) Create(rq any) (*apiv2.Machine, error) {
panic("unimplemented")
}

func (c *machine) Delete(id string) (*apiv2.Machine, error) {
panic("unimplemented")
}

func (c *machine) Get(id string) (*apiv2.Machine, error) {
ctx, cancel := c.c.NewRequestContext()
defer cancel()

resp, err := c.c.Client.Adminv2().Machine().Get(ctx, &adminv2.MachineServiceGetRequest{
Uuid: id,
})
if err != nil {
return nil, err
}

return resp.Machine, nil
}

func (c *machine) List() ([]*apiv2.Machine, error) {
ctx, cancel := c.c.NewRequestContext()
defer cancel()

resp, err := c.c.Client.Adminv2().Machine().List(ctx, &adminv2.MachineServiceListRequest{
Query: &apiv2.MachineQuery{
Uuid: pointer.PointerOrNil(viper.GetString("id")),
Name: pointer.PointerOrNil(viper.GetString("name")),
Partition: pointer.PointerOrNil(viper.GetString("partition")),
Size: pointer.PointerOrNil(viper.GetString("size")),
Rack: pointer.PointerOrNil(viper.GetString("rack")),
Labels: &apiv2.Labels{
Labels: tag.NewTagMap(viper.GetStringSlice("labels")),
},
Allocation: &apiv2.MachineAllocationQuery{
Uuid: pointer.PointerOrNil(viper.GetString("allocation-uuid")),
Name: pointer.PointerOrNil(viper.GetString("allocation-name")),
Project: pointer.PointerOrNil(viper.GetString("project")),
Image: pointer.PointerOrNil(viper.GetString("image")),
FilesystemLayout: pointer.PointerOrNil(viper.GetString("file-system-layout-id")),
Hostname: pointer.PointerOrNil(viper.GetString("hostname")),
// AllocationType: &0,
Labels: &apiv2.Labels{
Labels: tag.NewTagMap(viper.GetStringSlice("allocation-labels")),
},
// Vpn: &apiv2.MachineVPN{}, these query fields are no pointers and somehow seem wrong? how to search for vpn key?
},
Network: &apiv2.MachineNetworkQuery{},
Nic: &apiv2.MachineNicQuery{},
Disk: &apiv2.MachineDiskQuery{
Names: viper.GetStringSlice("disk-names"),
// Sizes:
},
Bmc: &apiv2.MachineBMCQuery{
Address: pointer.PointerOrNil(viper.GetString("bmc-address")),
Mac: pointer.PointerOrNil(viper.GetString("bmc-mac")),
User: pointer.PointerOrNil(viper.GetString("bmc-user")),
Interface: pointer.PointerOrNil(viper.GetString("bmc-interface")),
},
Fru: &apiv2.MachineFRUQuery{
ChassisPartNumber: pointer.PointerOrNil(viper.GetString("chassis-part-number")),
ChassisPartSerial: pointer.PointerOrNil(viper.GetString("chassis-part-serial")),
BoardMfg: pointer.PointerOrNil(viper.GetString("board-mfg")),
BoardSerial: pointer.PointerOrNil(viper.GetString("board-serial")),
BoardPartNumber: pointer.PointerOrNil(viper.GetString("board-part-number")),
ProductManufacturer: pointer.PointerOrNil(viper.GetString("product-manufacturer")),
ProductPartNumber: pointer.PointerOrNil(viper.GetString("product-part-number")),
ProductSerial: pointer.PointerOrNil(viper.GetString("product-serial")),
},
Hardware: &apiv2.MachineHardwareQuery{
Memory: pointer.PointerOrNil(viper.GetUint64("memory")),
CpuCores: pointer.PointerOrNil(viper.GetUint32("cpu-cores")),
},
// State: &0,
},
Partition: nil, // again partition?
})
if err != nil {
return nil, err
}

return resp.Machines, nil
}

func (c *machine) Update(rq any) (*apiv2.Machine, error) {
panic("unimplemented")
}

func (c *machine) Convert(r *apiv2.Machine) (string, any, any, error) {
panic("unimplemented")

}

func (c *machine) MachineResponseToCreate(r *apiv2.Machine) any {
panic("unimplemented")
}

func (c *machine) MachineResponseToUpdate(desired *apiv2.Machine) (any, error) {
panic("unimplemented")
}
Loading