From d54295702328a150108e17f389df32d68fa5440a Mon Sep 17 00:00:00 2001 From: Axel Christ Date: Fri, 21 Apr 2023 18:49:34 +0200 Subject: [PATCH] Implement additional orictl-machine columns This change allows `orictl-machine` to `get machines` with additional columns that may be specified in a config file. To make this possible, some parts of the table converters had to be heavily adapted and to simplify this, the directory structure of the different `ori-*` tools have been finally split. --- Dockerfile | 15 +- .../cmd/orictl-bucket/main.go | 6 +- .../orictlbucket/common/common.go | 10 +- .../orictlbucket/create/bucket/bucket.go | 10 +- .../orictlbucket/create/create.go | 8 +- .../orictlbucket/delete/bucket/bucket.go | 8 +- .../orictlbucket/delete/delete.go | 8 +- .../orictlbucket/get/bucket/bucket.go | 8 +- .../get/bucketclass/bucketclass.go | 8 +- .../cmd/orictl-bucket/orictlbucket/get/get.go | 10 +- .../orictlbucket/orictlbucket.go | 14 +- .../renderers}/register.go | 8 +- .../tableconverters}/bucket.go | 31 +- .../tableconverters}/bucketclass.go | 31 +- .../tableconverters}/register.go | 4 +- orictl-machine/clientcmd/clientcmd.go | 91 ++++++ .../cmd/orictl-machine/main.go | 4 +- .../orictlmachine/common/common.go | 166 +++++++++++ .../orictlmachine/create/create.go | 14 +- .../orictlmachine/create/machine/machine.go | 10 +- .../networkinterface/networkinterface.go | 10 +- .../orictlmachine/create/volume/volume.go | 8 +- .../volumeattachment/volumeattachment.go | 8 +- .../orictlmachine/delete/delete.go | 14 +- .../orictlmachine/delete/machine/machine.go | 8 +- .../networkinterface/networkinterface.go | 8 +- .../orictlmachine/delete/volume/volume.go | 8 +- .../volumeattachment/volumeattachment.go | 8 +- .../orictl-machine/orictlmachine/exec/exec.go | 8 +- .../orictl-machine/orictlmachine/get/get.go | 14 +- .../orictlmachine/get/machine/machine.go | 10 +- .../get/machineclass/machineclass.go | 10 +- .../get/networkinterface/networkinterface.go | 10 +- .../orictlmachine/get/volume/volume.go | 10 +- .../orictlmachine/orictlmachine.go | 16 +- .../orictlmachine/update/update.go | 6 +- .../samples/machine-networkinterface.yaml | 0 .../config/samples/machine-volume.yaml | 0 .../config/samples/machine.yaml | 0 .../config/samples/volumeattachment.yaml | 0 .../tableconverters}/machine.go | 34 +-- .../tableconverters}/machineclass.go | 35 +-- .../tableconverters}/networkinterface.go | 34 +-- orictl-machine/tableconverters/register.go | 49 ++++ .../tableconverters}/volume.go | 34 +-- .../cmd/orictl-volume/main.go | 4 +- .../orictlvolume/common/common.go | 6 +- .../orictlvolume/create/create.go | 6 +- .../orictlvolume/create/volume/volume.go | 4 +- .../orictlvolume/delete/delete.go | 6 +- .../orictlvolume/delete/volume/volume.go | 4 +- .../cmd/orictl-volume/orictlvolume/get/get.go | 8 +- .../orictlvolume/get/volume/volume.go | 4 +- .../get/volumeclass/volumeclass.go | 4 +- .../orictlvolume/orictlvolume.go | 12 +- .../config/samples/volume.yaml | 0 .../renderers}/register.go | 8 +- .../tableconverters}/register.go | 4 +- .../tableconverters}/volume.go | 31 +- .../tableconverters}/volumeclass.go | 31 +- orictl/{table => api}/table.go | 2 +- orictl/{cli/common => cmd}/common.go | 2 +- .../orictlmachine/common/common.go | 95 ------ orictl/renderer/table.go | 12 +- orictl/renderers/machine/register.go | 37 --- orictl/table/tableconverter/tableconverter.go | 168 ----------- orictl/tableconverter/tableconverter.go | 272 ++++++++++++++++++ .../tableconverter_suite_test.go} | 17 +- orictl/tableconverter/tableconverter_test.go | 57 ++++ orictl/tableconverter/utils.go | 46 +++ orictl/{table => }/tabwriter/tabwriter.go | 0 utils/generic/generic.go | 25 ++ 72 files changed, 1026 insertions(+), 645 deletions(-) rename {orictl => orictl-bucket}/cmd/orictl-bucket/main.go (80%) rename {orictl => orictl-bucket}/cmd/orictl-bucket/orictlbucket/common/common.go (87%) rename {orictl => orictl-bucket}/cmd/orictl-bucket/orictlbucket/create/bucket/bucket.go (87%) rename {orictl => orictl-bucket}/cmd/orictl-bucket/orictlbucket/create/create.go (72%) rename {orictl => orictl-bucket}/cmd/orictl-bucket/orictlbucket/delete/bucket/bucket.go (87%) rename {orictl => orictl-bucket}/cmd/orictl-bucket/orictlbucket/delete/delete.go (72%) rename {orictl => orictl-bucket}/cmd/orictl-bucket/orictlbucket/get/bucket/bucket.go (87%) rename {orictl => orictl-bucket}/cmd/orictl-bucket/orictlbucket/get/bucketclass/bucketclass.go (86%) rename {orictl => orictl-bucket}/cmd/orictl-bucket/orictlbucket/get/get.go (68%) rename {orictl => orictl-bucket}/cmd/orictl-bucket/orictlbucket/orictlbucket.go (72%) rename {orictl/renderers/bucket => orictl-bucket/renderers}/register.go (82%) rename {orictl/table/tableconverters/bucket => orictl-bucket/tableconverters}/bucket.go (64%) rename {orictl/table/tableconverters/bucket => orictl-bucket/tableconverters}/bucketclass.go (58%) rename {orictl/table/tableconverters/volume => orictl-bucket/tableconverters}/register.go (89%) create mode 100644 orictl-machine/clientcmd/clientcmd.go rename {orictl => orictl-machine}/cmd/orictl-machine/main.go (86%) create mode 100644 orictl-machine/cmd/orictl-machine/orictlmachine/common/common.go rename {orictl => orictl-machine}/cmd/orictl-machine/orictlmachine/create/create.go (59%) rename {orictl => orictl-machine}/cmd/orictl-machine/orictlmachine/create/machine/machine.go (87%) rename {orictl => orictl-machine}/cmd/orictl-machine/orictlmachine/create/networkinterface/networkinterface.go (88%) rename {orictl => orictl-machine}/cmd/orictl-machine/orictlmachine/create/volume/volume.go (89%) rename {orictl => orictl-machine}/cmd/orictl-machine/orictlmachine/create/volumeattachment/volumeattachment.go (89%) rename {orictl => orictl-machine}/cmd/orictl-machine/orictlmachine/delete/delete.go (59%) rename {orictl => orictl-machine}/cmd/orictl-machine/orictlmachine/delete/machine/machine.go (86%) rename {orictl => orictl-machine}/cmd/orictl-machine/orictlmachine/delete/networkinterface/networkinterface.go (88%) rename {orictl => orictl-machine}/cmd/orictl-machine/orictlmachine/delete/volume/volume.go (88%) rename {orictl => orictl-machine}/cmd/orictl-machine/orictlmachine/delete/volumeattachment/volumeattachment.go (89%) rename {orictl => orictl-machine}/cmd/orictl-machine/orictlmachine/exec/exec.go (91%) rename {orictl => orictl-machine}/cmd/orictl-machine/orictlmachine/get/get.go (59%) rename {orictl => orictl-machine}/cmd/orictl-machine/orictlmachine/get/machine/machine.go (87%) rename {orictl => orictl-machine}/cmd/orictl-machine/orictlmachine/get/machineclass/machineclass.go (84%) rename {orictl => orictl-machine}/cmd/orictl-machine/orictlmachine/get/networkinterface/networkinterface.go (87%) rename {orictl => orictl-machine}/cmd/orictl-machine/orictlmachine/get/volume/volume.go (86%) rename {orictl => orictl-machine}/cmd/orictl-machine/orictlmachine/orictlmachine.go (70%) rename {orictl => orictl-machine}/cmd/orictl-machine/orictlmachine/update/update.go (75%) rename {orictl => orictl-machine}/config/samples/machine-networkinterface.yaml (100%) rename {orictl => orictl-machine}/config/samples/machine-volume.yaml (100%) rename {orictl => orictl-machine}/config/samples/machine.yaml (100%) rename {orictl => orictl-machine}/config/samples/volumeattachment.yaml (100%) rename {orictl/table/tableconverters/machine => orictl-machine/tableconverters}/machine.go (65%) rename {orictl/table/tableconverters/machine => orictl-machine/tableconverters}/machineclass.go (63%) rename {orictl/table/tableconverters/machine => orictl-machine/tableconverters}/networkinterface.go (64%) create mode 100644 orictl-machine/tableconverters/register.go rename {orictl/table/tableconverters/machine => orictl-machine/tableconverters}/volume.go (64%) rename {orictl => orictl-volume}/cmd/orictl-volume/main.go (86%) rename {orictl => orictl-volume}/cmd/orictl-volume/orictlvolume/common/common.go (91%) rename {orictl => orictl-volume}/cmd/orictl-volume/orictlvolume/create/create.go (78%) rename {orictl => orictl-volume}/cmd/orictl-volume/orictlvolume/create/volume/volume.go (94%) rename {orictl => orictl-volume}/cmd/orictl-volume/orictlvolume/delete/delete.go (78%) rename {orictl => orictl-volume}/cmd/orictl-volume/orictlvolume/delete/volume/volume.go (93%) rename {orictl => orictl-volume}/cmd/orictl-volume/orictlvolume/get/get.go (73%) rename {orictl => orictl-volume}/cmd/orictl-volume/orictlvolume/get/volume/volume.go (93%) rename {orictl => orictl-volume}/cmd/orictl-volume/orictlvolume/get/volumeclass/volumeclass.go (93%) rename {orictl => orictl-volume}/cmd/orictl-volume/orictlvolume/orictlvolume.go (75%) rename {orictl => orictl-volume}/config/samples/volume.yaml (100%) rename {orictl/renderers/volume => orictl-volume/renderers}/register.go (82%) rename {orictl/table/tableconverters/bucket => orictl-volume/tableconverters}/register.go (89%) rename {orictl/table/tableconverters/volume => orictl-volume/tableconverters}/volume.go (65%) rename {orictl/table/tableconverters/volume => orictl-volume/tableconverters}/volumeclass.go (58%) rename orictl/{table => api}/table.go (98%) rename orictl/{cli/common => cmd}/common.go (99%) delete mode 100644 orictl/cmd/orictl-machine/orictlmachine/common/common.go delete mode 100644 orictl/renderers/machine/register.go delete mode 100644 orictl/table/tableconverter/tableconverter.go create mode 100644 orictl/tableconverter/tableconverter.go rename orictl/{table/tableconverters/machine/register.go => tableconverter/tableconverter_suite_test.go} (70%) create mode 100644 orictl/tableconverter/tableconverter_test.go create mode 100644 orictl/tableconverter/utils.go rename orictl/{table => }/tabwriter/tabwriter.go (100%) diff --git a/Dockerfile b/Dockerfile index 7c9861836..60a368daf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,6 +17,9 @@ COPY cmd/ cmd/ COPY internal/ internal/ COPY ori/ ori/ COPY orictl/ orictl/ +COPY orictl-bucket/ orictl-bucket/ +COPY orictl-machine/ orictl-machine/ +COPY orictl-volume/ orictl-volume/ COPY poollet/ poollet/ COPY utils/ utils/ @@ -49,13 +52,13 @@ FROM builder as machinebroker-builder RUN --mount=type=cache,target=/root/.cache/go-build \ --mount=type=cache,target=/go/pkg \ CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH GO111MODULE=on go build -ldflags="-s -w" -a -o bin/machinebroker ./broker/machinebroker/cmd/machinebroker/main.go && \ - CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH GO111MODULE=on go build -ldflags="-s -w" -a -o bin/orictl-machine ./orictl/cmd/orictl-machine/main.go + CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH GO111MODULE=on go build -ldflags="-s -w" -a -o bin/orictl-machine ./orictl-machine/cmd/orictl-machine/main.go FROM builder as orictl-machine-builder RUN --mount=type=cache,target=/root/.cache/go-build \ --mount=type=cache,target=/go/pkg \ - CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH GO111MODULE=on go build -ldflags="-s -w" -a -o bin/orictl-machine ./orictl/cmd/orictl-machine/main.go + CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH GO111MODULE=on go build -ldflags="-s -w" -a -o bin/orictl-machine ./orictl-machine/cmd/orictl-machine/main.go FROM builder as volumepoollet-builder @@ -70,13 +73,13 @@ FROM builder as volumebroker-builder RUN --mount=type=cache,target=/root/.cache/go-build \ --mount=type=cache,target=/go/pkg \ CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH GO111MODULE=on go build -ldflags="-s -w" -a -o bin/volumebroker ./broker/volumebroker/cmd/volumebroker/main.go && \ - CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH GO111MODULE=on go build -ldflags="-s -w" -a -o bin/orictl-volume ./orictl/cmd/orictl-volume/main.go + CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH GO111MODULE=on go build -ldflags="-s -w" -a -o bin/orictl-volume ./orictl-volume/cmd/orictl-volume/main.go FROM builder as orictl-volume-builder RUN --mount=type=cache,target=/root/.cache/go-build \ --mount=type=cache,target=/go/pkg \ - CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH GO111MODULE=on go build -ldflags="-s -w" -a -o bin/orictl-volume ./orictl/cmd/orictl-volume/main.go + CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH GO111MODULE=on go build -ldflags="-s -w" -a -o bin/orictl-volume ./orictl-volume/cmd/orictl-volume/main.go FROM builder as bucketpoollet-builder @@ -91,13 +94,13 @@ FROM builder as bucketbroker-builder RUN --mount=type=cache,target=/root/.cache/go-build \ --mount=type=cache,target=/go/pkg \ CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH GO111MODULE=on go build -ldflags="-s -w" -a -o bin/bucketbroker ./broker/bucketbroker/cmd/bucketbroker/main.go && \ - CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH GO111MODULE=on go build -ldflags="-s -w" -a -o bin/orictl-bucket ./orictl/cmd/orictl-bucket/main.go + CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH GO111MODULE=on go build -ldflags="-s -w" -a -o bin/orictl-bucket ./orictl-bucket/cmd/orictl-bucket/main.go FROM builder as orictl-bucket-builder RUN --mount=type=cache,target=/root/.cache/go-build \ --mount=type=cache,target=/go/pkg \ - CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH GO111MODULE=on go build -ldflags="-s -w" -a -o bin/orictl-bucket ./orictl/cmd/orictl-bucket/main.go + CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH GO111MODULE=on go build -ldflags="-s -w" -a -o bin/orictl-bucket ./orictl-bucket/cmd/orictl-bucket/main.go # Use distroless as minimal base image to package the manager binary # Refer to https://github.com/GoogleContainerTools/distroless for more details diff --git a/orictl/cmd/orictl-bucket/main.go b/orictl-bucket/cmd/orictl-bucket/main.go similarity index 80% rename from orictl/cmd/orictl-bucket/main.go rename to orictl-bucket/cmd/orictl-bucket/main.go index 9c20a7dbc..5272605bb 100644 --- a/orictl/cmd/orictl-bucket/main.go +++ b/orictl-bucket/cmd/orictl-bucket/main.go @@ -17,14 +17,14 @@ package main import ( "os" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-bucket/orictlbucket" + "github.com/onmetal/onmetal-api/orictl-bucket/cmd/orictl-bucket/orictlbucket" + orictlcmd "github.com/onmetal/onmetal-api/orictl/cmd" ctrl "sigs.k8s.io/controller-runtime" ) func main() { ctx := ctrl.SetupSignalHandler() - if err := orictlbucket.Command(clicommon.OSStreams).ExecuteContext(ctx); err != nil { + if err := orictlbucket.Command(orictlcmd.OSStreams).ExecuteContext(ctx); err != nil { ctrl.Log.Error(err, "Error running command") os.Exit(1) } diff --git a/orictl/cmd/orictl-bucket/orictlbucket/common/common.go b/orictl-bucket/cmd/orictl-bucket/orictlbucket/common/common.go similarity index 87% rename from orictl/cmd/orictl-bucket/orictlbucket/common/common.go rename to orictl-bucket/cmd/orictl-bucket/orictlbucket/common/common.go index d5b2699fa..b89c8699d 100644 --- a/orictl/cmd/orictl-bucket/orictlbucket/common/common.go +++ b/orictl-bucket/cmd/orictl-bucket/orictlbucket/common/common.go @@ -20,9 +20,9 @@ import ( ori "github.com/onmetal/onmetal-api/ori/apis/bucket/v1alpha1" oriremotebucket "github.com/onmetal/onmetal-api/ori/remote/bucket" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" + "github.com/onmetal/onmetal-api/orictl-bucket/renderers" + orictlcmd "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/onmetal/onmetal-api/orictl/renderer" - "github.com/onmetal/onmetal-api/orictl/renderers/bucket" "github.com/spf13/pflag" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" @@ -31,7 +31,7 @@ import ( var Renderer = renderer.NewRegistry() func init() { - if err := bucket.AddToRegistry(Renderer); err != nil { + if err := renderers.AddToRegistry(Renderer); err != nil { panic(err) } } @@ -62,8 +62,8 @@ func (o *ClientOptions) New() (ori.BucketRuntimeClient, func() error, error) { return ori.NewBucketRuntimeClient(conn), conn.Close, nil } -func NewOutputOptions() *clicommon.OutputOptions { - return &clicommon.OutputOptions{ +func NewOutputOptions() *orictlcmd.OutputOptions { + return &orictlcmd.OutputOptions{ Registry: Renderer, } } diff --git a/orictl/cmd/orictl-bucket/orictlbucket/create/bucket/bucket.go b/orictl-bucket/cmd/orictl-bucket/orictlbucket/create/bucket/bucket.go similarity index 87% rename from orictl/cmd/orictl-bucket/orictlbucket/create/bucket/bucket.go rename to orictl-bucket/cmd/orictl-bucket/orictlbucket/create/bucket/bucket.go index a62182405..9ddf9ff86 100644 --- a/orictl/cmd/orictl-bucket/orictlbucket/create/bucket/bucket.go +++ b/orictl-bucket/cmd/orictl-bucket/orictlbucket/create/bucket/bucket.go @@ -20,8 +20,8 @@ import ( "os" ori "github.com/onmetal/onmetal-api/ori/apis/bucket/v1alpha1" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-bucket/orictlbucket/common" + "github.com/onmetal/onmetal-api/orictl-bucket/cmd/orictl-bucket/orictlbucket/common" + orictlcmd "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/onmetal/onmetal-api/orictl/decoder" "github.com/onmetal/onmetal-api/orictl/renderer" "github.com/spf13/cobra" @@ -37,7 +37,7 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) { fs.StringVarP(&o.Filename, "filename", "f", o.Filename, "Path to a file to read.") } -func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cobra.Command { +func Command(streams orictlcmd.Streams, clientFactory common.ClientFactory) *cobra.Command { var ( outputOpts = common.NewOutputOptions() opts Options @@ -75,8 +75,8 @@ func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cob return cmd } -func Run(ctx context.Context, streams clicommon.Streams, client ori.BucketRuntimeClient, r renderer.Renderer, opts Options) error { - data, err := clicommon.ReadFileOrReader(opts.Filename, os.Stdin) +func Run(ctx context.Context, streams orictlcmd.Streams, client ori.BucketRuntimeClient, r renderer.Renderer, opts Options) error { + data, err := orictlcmd.ReadFileOrReader(opts.Filename, os.Stdin) if err != nil { return err } diff --git a/orictl/cmd/orictl-bucket/orictlbucket/create/create.go b/orictl-bucket/cmd/orictl-bucket/orictlbucket/create/create.go similarity index 72% rename from orictl/cmd/orictl-bucket/orictlbucket/create/create.go rename to orictl-bucket/cmd/orictl-bucket/orictlbucket/create/create.go index 1847e1a93..a40c0ee54 100644 --- a/orictl/cmd/orictl-bucket/orictlbucket/create/create.go +++ b/orictl-bucket/cmd/orictl-bucket/orictlbucket/create/create.go @@ -15,13 +15,13 @@ package create import ( - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-bucket/orictlbucket/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-bucket/orictlbucket/create/bucket" + "github.com/onmetal/onmetal-api/orictl-bucket/cmd/orictl-bucket/orictlbucket/common" + "github.com/onmetal/onmetal-api/orictl-bucket/cmd/orictl-bucket/orictlbucket/create/bucket" + orictlcmd "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/spf13/cobra" ) -func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cobra.Command { +func Command(streams orictlcmd.Streams, clientFactory common.ClientFactory) *cobra.Command { cmd := &cobra.Command{ Use: "create", } diff --git a/orictl/cmd/orictl-bucket/orictlbucket/delete/bucket/bucket.go b/orictl-bucket/cmd/orictl-bucket/orictlbucket/delete/bucket/bucket.go similarity index 87% rename from orictl/cmd/orictl-bucket/orictlbucket/delete/bucket/bucket.go rename to orictl-bucket/cmd/orictl-bucket/orictlbucket/delete/bucket/bucket.go index 04295db50..8bfbbeac9 100644 --- a/orictl/cmd/orictl-bucket/orictlbucket/delete/bucket/bucket.go +++ b/orictl-bucket/cmd/orictl-bucket/orictlbucket/delete/bucket/bucket.go @@ -19,15 +19,15 @@ import ( "fmt" ori "github.com/onmetal/onmetal-api/ori/apis/bucket/v1alpha1" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-bucket/orictlbucket/common" + "github.com/onmetal/onmetal-api/orictl-bucket/cmd/orictl-bucket/orictlbucket/common" + orictlcmd "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/spf13/cobra" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ctrl "sigs.k8s.io/controller-runtime" ) -func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cobra.Command { +func Command(streams orictlcmd.Streams, clientFactory common.ClientFactory) *cobra.Command { cmd := &cobra.Command{ Use: "bucket id [ids...]", Aliases: common.BucketAliases, @@ -55,7 +55,7 @@ func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cob return cmd } -func Run(ctx context.Context, streams clicommon.Streams, client ori.BucketRuntimeClient, ids []string) error { +func Run(ctx context.Context, streams orictlcmd.Streams, client ori.BucketRuntimeClient, ids []string) error { for _, id := range ids { if _, err := client.DeleteBucket(ctx, &ori.DeleteBucketRequest{ BucketId: id, diff --git a/orictl/cmd/orictl-bucket/orictlbucket/delete/delete.go b/orictl-bucket/cmd/orictl-bucket/orictlbucket/delete/delete.go similarity index 72% rename from orictl/cmd/orictl-bucket/orictlbucket/delete/delete.go rename to orictl-bucket/cmd/orictl-bucket/orictlbucket/delete/delete.go index ec7a3a3e4..b3ca1a354 100644 --- a/orictl/cmd/orictl-bucket/orictlbucket/delete/delete.go +++ b/orictl-bucket/cmd/orictl-bucket/orictlbucket/delete/delete.go @@ -15,13 +15,13 @@ package delete import ( - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-bucket/orictlbucket/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-bucket/orictlbucket/delete/bucket" + "github.com/onmetal/onmetal-api/orictl-bucket/cmd/orictl-bucket/orictlbucket/common" + "github.com/onmetal/onmetal-api/orictl-bucket/cmd/orictl-bucket/orictlbucket/delete/bucket" + orictlcmd "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/spf13/cobra" ) -func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cobra.Command { +func Command(streams orictlcmd.Streams, clientFactory common.ClientFactory) *cobra.Command { cmd := &cobra.Command{ Use: "delete", } diff --git a/orictl/cmd/orictl-bucket/orictlbucket/get/bucket/bucket.go b/orictl-bucket/cmd/orictl-bucket/orictlbucket/get/bucket/bucket.go similarity index 87% rename from orictl/cmd/orictl-bucket/orictlbucket/get/bucket/bucket.go rename to orictl-bucket/cmd/orictl-bucket/orictlbucket/get/bucket/bucket.go index db305d169..4fa7a6dcb 100644 --- a/orictl/cmd/orictl-bucket/orictlbucket/get/bucket/bucket.go +++ b/orictl-bucket/cmd/orictl-bucket/orictlbucket/get/bucket/bucket.go @@ -19,8 +19,8 @@ import ( "fmt" ori "github.com/onmetal/onmetal-api/ori/apis/bucket/v1alpha1" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-bucket/orictlbucket/common" + "github.com/onmetal/onmetal-api/orictl-bucket/cmd/orictl-bucket/orictlbucket/common" + orictlcmd "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/onmetal/onmetal-api/orictl/renderer" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -33,7 +33,7 @@ type Options struct { func (o *Options) AddFlags(fs *pflag.FlagSet) { } -func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cobra.Command { +func Command(streams orictlcmd.Streams, clientFactory common.ClientFactory) *cobra.Command { var ( opts Options outputOpts = common.NewOutputOptions() @@ -71,7 +71,7 @@ func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cob return cmd } -func Run(ctx context.Context, streams clicommon.Streams, client ori.BucketRuntimeClient, render renderer.Renderer, opts Options) error { +func Run(ctx context.Context, streams orictlcmd.Streams, client ori.BucketRuntimeClient, render renderer.Renderer, opts Options) error { res, err := client.ListBuckets(ctx, &ori.ListBucketsRequest{}) if err != nil { return fmt.Errorf("error listing buckets: %w", err) diff --git a/orictl/cmd/orictl-bucket/orictlbucket/get/bucketclass/bucketclass.go b/orictl-bucket/cmd/orictl-bucket/orictlbucket/get/bucketclass/bucketclass.go similarity index 86% rename from orictl/cmd/orictl-bucket/orictlbucket/get/bucketclass/bucketclass.go rename to orictl-bucket/cmd/orictl-bucket/orictlbucket/get/bucketclass/bucketclass.go index a58e0fb47..fa4e925f9 100644 --- a/orictl/cmd/orictl-bucket/orictlbucket/get/bucketclass/bucketclass.go +++ b/orictl-bucket/cmd/orictl-bucket/orictlbucket/get/bucketclass/bucketclass.go @@ -19,14 +19,14 @@ import ( "fmt" ori "github.com/onmetal/onmetal-api/ori/apis/bucket/v1alpha1" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-bucket/orictlbucket/common" + "github.com/onmetal/onmetal-api/orictl-bucket/cmd/orictl-bucket/orictlbucket/common" + orictlcmd "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/onmetal/onmetal-api/orictl/renderer" "github.com/spf13/cobra" ctrl "sigs.k8s.io/controller-runtime" ) -func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cobra.Command { +func Command(streams orictlcmd.Streams, clientFactory common.ClientFactory) *cobra.Command { var ( outputOpts = common.NewOutputOptions() ) @@ -62,7 +62,7 @@ func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cob return cmd } -func Run(ctx context.Context, streams clicommon.Streams, client ori.BucketRuntimeClient, render renderer.Renderer) error { +func Run(ctx context.Context, streams orictlcmd.Streams, client ori.BucketRuntimeClient, render renderer.Renderer) error { res, err := client.ListBucketClasses(ctx, &ori.ListBucketClassesRequest{}) if err != nil { return fmt.Errorf("error listing bucket classes: %w", err) diff --git a/orictl/cmd/orictl-bucket/orictlbucket/get/get.go b/orictl-bucket/cmd/orictl-bucket/orictlbucket/get/get.go similarity index 68% rename from orictl/cmd/orictl-bucket/orictlbucket/get/get.go rename to orictl-bucket/cmd/orictl-bucket/orictlbucket/get/get.go index ec9446709..cc23ff78c 100644 --- a/orictl/cmd/orictl-bucket/orictlbucket/get/get.go +++ b/orictl-bucket/cmd/orictl-bucket/orictlbucket/get/get.go @@ -15,14 +15,14 @@ package get import ( - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-bucket/orictlbucket/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-bucket/orictlbucket/get/bucket" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-bucket/orictlbucket/get/bucketclass" + "github.com/onmetal/onmetal-api/orictl-bucket/cmd/orictl-bucket/orictlbucket/common" + "github.com/onmetal/onmetal-api/orictl-bucket/cmd/orictl-bucket/orictlbucket/get/bucket" + "github.com/onmetal/onmetal-api/orictl-bucket/cmd/orictl-bucket/orictlbucket/get/bucketclass" + orictlcmd "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/spf13/cobra" ) -func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cobra.Command { +func Command(streams orictlcmd.Streams, clientFactory common.ClientFactory) *cobra.Command { cmd := &cobra.Command{ Use: "get", } diff --git a/orictl/cmd/orictl-bucket/orictlbucket/orictlbucket.go b/orictl-bucket/cmd/orictl-bucket/orictlbucket/orictlbucket.go similarity index 72% rename from orictl/cmd/orictl-bucket/orictlbucket/orictlbucket.go rename to orictl-bucket/cmd/orictl-bucket/orictlbucket/orictlbucket.go index 3bf581df7..f274deadb 100644 --- a/orictl/cmd/orictl-bucket/orictlbucket/orictlbucket.go +++ b/orictl-bucket/cmd/orictl-bucket/orictlbucket/orictlbucket.go @@ -17,17 +17,17 @@ package orictlbucket import ( goflag "flag" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-bucket/orictlbucket/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-bucket/orictlbucket/create" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-bucket/orictlbucket/delete" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-bucket/orictlbucket/get" + "github.com/onmetal/onmetal-api/orictl-bucket/cmd/orictl-bucket/orictlbucket/common" + "github.com/onmetal/onmetal-api/orictl-bucket/cmd/orictl-bucket/orictlbucket/create" + delete2 "github.com/onmetal/onmetal-api/orictl-bucket/cmd/orictl-bucket/orictlbucket/delete" + "github.com/onmetal/onmetal-api/orictl-bucket/cmd/orictl-bucket/orictlbucket/get" + orictlcmd "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/spf13/cobra" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/log/zap" ) -func Command(streams clicommon.Streams) *cobra.Command { +func Command(streams orictlcmd.Streams) *cobra.Command { var ( zapOpts zap.Options clientOpts common.ClientOptions @@ -50,7 +50,7 @@ func Command(streams clicommon.Streams) *cobra.Command { cmd.AddCommand( get.Command(streams, &clientOpts), - delete.Command(streams, &clientOpts), + delete2.Command(streams, &clientOpts), create.Command(streams, &clientOpts), ) diff --git a/orictl/renderers/bucket/register.go b/orictl-bucket/renderers/register.go similarity index 82% rename from orictl/renderers/bucket/register.go rename to orictl-bucket/renderers/register.go index ee1827ee0..295869941 100644 --- a/orictl/renderers/bucket/register.go +++ b/orictl-bucket/renderers/register.go @@ -12,12 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -package bucket +package renderers import ( + "github.com/onmetal/onmetal-api/orictl-bucket/tableconverters" "github.com/onmetal/onmetal-api/orictl/renderer" - "github.com/onmetal/onmetal-api/orictl/table/tableconverter" - "github.com/onmetal/onmetal-api/orictl/table/tableconverters/bucket" + "github.com/onmetal/onmetal-api/orictl/tableconverter" ) var ( @@ -29,7 +29,7 @@ func init() { RegistryBuilder.Add(renderer.AddToRegistry) RegistryBuilder.Add(func(registry *renderer.Registry) error { tableConverter := tableconverter.NewRegistry() - if err := bucket.AddToRegistry(tableConverter); err != nil { + if err := tableconverters.AddToRegistry(tableConverter); err != nil { return err } return registry.Register("table", renderer.NewTable(tableConverter)) diff --git a/orictl/table/tableconverters/bucket/bucket.go b/orictl-bucket/tableconverters/bucket.go similarity index 64% rename from orictl/table/tableconverters/bucket/bucket.go rename to orictl-bucket/tableconverters/bucket.go index 7b005aa07..fd2d7e1a5 100644 --- a/orictl/table/tableconverters/bucket/bucket.go +++ b/orictl-bucket/tableconverters/bucket.go @@ -12,19 +12,19 @@ // See the License for the specific language governing permissions and // limitations under the License. -package bucket +package tableconverters import ( "time" ori "github.com/onmetal/onmetal-api/ori/apis/bucket/v1alpha1" - "github.com/onmetal/onmetal-api/orictl/table" - "github.com/onmetal/onmetal-api/orictl/table/tableconverter" + "github.com/onmetal/onmetal-api/orictl/api" + "github.com/onmetal/onmetal-api/orictl/tableconverter" "k8s.io/apimachinery/pkg/util/duration" ) var ( - bucketHeaders = []table.Header{ + bucketHeaders = []api.Header{ {Name: "ID"}, {Name: "Class"}, {Name: "State"}, @@ -32,25 +32,24 @@ var ( } ) -var Bucket, BucketSlice = tableconverter.ForType[*ori.Bucket]( //nolint:revive - func() ([]table.Header, error) { - return bucketHeaders, nil - }, - func(bucket *ori.Bucket) ([]table.Row, error) { - return []table.Row{ - { +var ( + Bucket = tableconverter.Funcs[*ori.Bucket]{ + Headers: tableconverter.Headers(bucketHeaders), + Rows: tableconverter.SingleRowFrom(func(bucket *ori.Bucket) (api.Row, error) { + return api.Row{ bucket.Metadata.Id, bucket.Spec.Class, bucket.Status.State.String(), duration.HumanDuration(time.Since(time.Unix(0, bucket.Metadata.CreatedAt))), - }, - }, nil - }, + }, nil + }), + } + BucketSlice = tableconverter.SliceFuncs[*ori.Bucket](Bucket) ) func init() { RegistryBuilder.Register( - tableconverter.ToTaggedAny(Bucket), - tableconverter.ToTaggedAny(BucketSlice), + tableconverter.ToTagAndTypedAny[*ori.Bucket](Bucket), + tableconverter.ToTagAndTypedAny[[]*ori.Bucket](BucketSlice), ) } diff --git a/orictl/table/tableconverters/bucket/bucketclass.go b/orictl-bucket/tableconverters/bucketclass.go similarity index 58% rename from orictl/table/tableconverters/bucket/bucketclass.go rename to orictl-bucket/tableconverters/bucketclass.go index 4b974cf85..e547f2ce0 100644 --- a/orictl/table/tableconverters/bucket/bucketclass.go +++ b/orictl-bucket/tableconverters/bucketclass.go @@ -12,40 +12,39 @@ // See the License for the specific language governing permissions and // limitations under the License. -package bucket +package tableconverters import ( ori "github.com/onmetal/onmetal-api/ori/apis/bucket/v1alpha1" - "github.com/onmetal/onmetal-api/orictl/table" - "github.com/onmetal/onmetal-api/orictl/table/tableconverter" + "github.com/onmetal/onmetal-api/orictl/api" + "github.com/onmetal/onmetal-api/orictl/tableconverter" ) var ( - bucketClassHeaders = []table.Header{ + bucketClassHeaders = []api.Header{ {Name: "Name"}, {Name: "TPS"}, {Name: "IOPS"}, } ) -var BucketClass, BucketClassSlice = tableconverter.ForType[*ori.BucketClass]( //nolint:revive - func() ([]table.Header, error) { - return bucketClassHeaders, nil - }, - func(class *ori.BucketClass) ([]table.Row, error) { - return []table.Row{ - { +var ( + BucketClass = tableconverter.Funcs[*ori.BucketClass]{ + Headers: tableconverter.Headers(bucketClassHeaders), + Rows: tableconverter.SingleRowFrom(func(class *ori.BucketClass) (api.Row, error) { + return api.Row{ class.Name, class.Capabilities.Tps, class.Capabilities.Iops, - }, - }, nil - }, + }, nil + }), + } + BucketClassSlice = tableconverter.SliceFuncs[*ori.BucketClass](BucketClass) ) func init() { RegistryBuilder.Register( - tableconverter.ToTaggedAny(BucketClass), - tableconverter.ToTaggedAny(BucketClassSlice), + tableconverter.ToTagAndTypedAny[*ori.BucketClass](BucketClass), + tableconverter.ToTagAndTypedAny[[]*ori.BucketClass](BucketClassSlice), ) } diff --git a/orictl/table/tableconverters/volume/register.go b/orictl-bucket/tableconverters/register.go similarity index 89% rename from orictl/table/tableconverters/volume/register.go rename to orictl-bucket/tableconverters/register.go index 3f4f2faf9..b6f207fd8 100644 --- a/orictl/table/tableconverters/volume/register.go +++ b/orictl-bucket/tableconverters/register.go @@ -12,10 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -package volume +package tableconverters import ( - "github.com/onmetal/onmetal-api/orictl/table/tableconverter" + "github.com/onmetal/onmetal-api/orictl/tableconverter" ) var ( diff --git a/orictl-machine/clientcmd/clientcmd.go b/orictl-machine/clientcmd/clientcmd.go new file mode 100644 index 000000000..f87be20c9 --- /dev/null +++ b/orictl-machine/clientcmd/clientcmd.go @@ -0,0 +1,91 @@ +// Copyright 2023 OnMetal authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package clientcmd + +import ( + "errors" + "fmt" + "os" + "path/filepath" + + "github.com/onmetal/onmetal-api/orictl/decoder" + "k8s.io/client-go/util/homedir" +) + +const ( + RecommendedConfigPathFlag = "config" + RecommendedConfigPathEnvVar = "ORCITL_MACHINE_CONFIG" + RecommendedHomeDir = ".orictl-machine" + RecommendedFileName = "config" +) + +var ( + RecommendedConfigDir = filepath.Join(homedir.HomeDir(), RecommendedHomeDir) + RecommendedHomeFile = filepath.Join(RecommendedConfigDir, RecommendedFileName) +) + +type TableConfig struct { + WellKnownMachineLabels map[string]string `json:"wellKnownMachineLabels,omitempty"` +} + +type Config struct { + TableConfig *TableConfig `json:"tableConfig,omitempty"` +} + +func DefaultConfig() *Config { + return &Config{} +} + +func ReadConfig(data []byte) (*Config, error) { + cfg := &Config{} + if err := decoder.Decode(data, cfg); err != nil { + return nil, fmt.Errorf("error decoding config: %w", err) + } + return cfg, nil +} + +func ReadConfigFile(filename string) (*Config, error) { + data, err := os.ReadFile(filename) + if err != nil { + return nil, fmt.Errorf("error reading config file: %w", err) + } + return ReadConfig(data) +} + +func GetConfig(filename string) (*Config, error) { + if filename != "" { + return ReadConfigFile(filename) + } + + if configPath := os.Getenv(RecommendedConfigPathEnvVar); configPath != "" { + cfg, err := ReadConfigFile(configPath) + if err != nil && !errors.Is(err, os.ErrNotExist) { + return nil, err + } + if err == nil { + return cfg, nil + } + } + + cfg, err := ReadConfigFile(RecommendedHomeFile) + if err != nil && !errors.Is(err, os.ErrNotExist) { + return nil, err + } + if err == nil { + return cfg, nil + } + + return DefaultConfig(), nil +} diff --git a/orictl/cmd/orictl-machine/main.go b/orictl-machine/cmd/orictl-machine/main.go similarity index 86% rename from orictl/cmd/orictl-machine/main.go rename to orictl-machine/cmd/orictl-machine/main.go index 694922ca5..889035a39 100644 --- a/orictl/cmd/orictl-machine/main.go +++ b/orictl-machine/cmd/orictl-machine/main.go @@ -17,8 +17,8 @@ package main import ( "os" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" ctrl "sigs.k8s.io/controller-runtime" ) diff --git a/orictl-machine/cmd/orictl-machine/orictlmachine/common/common.go b/orictl-machine/cmd/orictl-machine/orictlmachine/common/common.go new file mode 100644 index 000000000..b3266743f --- /dev/null +++ b/orictl-machine/cmd/orictl-machine/orictlmachine/common/common.go @@ -0,0 +1,166 @@ +// Copyright 2022 OnMetal authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package common + +import ( + "fmt" + "time" + + ori "github.com/onmetal/onmetal-api/ori/apis/machine/v1alpha1" + oriremotemachine "github.com/onmetal/onmetal-api/ori/remote/machine" + "github.com/onmetal/onmetal-api/orictl-machine/clientcmd" + "github.com/onmetal/onmetal-api/orictl-machine/tableconverters" + "github.com/onmetal/onmetal-api/orictl/renderer" + "github.com/onmetal/onmetal-api/orictl/tableconverter" + "github.com/spf13/pflag" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" +) + +type Factory interface { + Client() (ori.MachineRuntimeClient, func() error, error) + Config() (*clientcmd.Config, error) + Registry() (*renderer.Registry, error) + OutputOptions() *OutputOptions +} + +type Options struct { + Address string + ConfigFile string +} + +func (o *Options) AddFlags(fs *pflag.FlagSet) { + fs.StringVar(&o.ConfigFile, clientcmd.RecommendedConfigPathFlag, "", "Config file to use") + fs.StringVar(&o.Address, "address", "", "Address to the ori server.") +} + +func (o *Options) Config() (*clientcmd.Config, error) { + return clientcmd.GetConfig(o.ConfigFile) +} + +func (o *Options) tableConvertersOptions(cfg *clientcmd.Config) tableconverters.Options { + tableCfg := cfg.TableConfig + if tableCfg == nil { + return tableconverters.Options{} + } + + opts := tableconverters.Options{} + if len(tableCfg.WellKnownMachineLabels) > 0 { + opts.TransformMachine = func(funcs tableconverter.Funcs[*ori.Machine]) tableconverter.TableConverter[*ori.Machine] { + return tableconverter.Merge[*ori.Machine]( + tableconverter.WellKnownLabels[*ori.Machine](tableCfg.WellKnownMachineLabels), + funcs, + ) + } + + opts.TransformMachineSlice = func(funcs tableconverter.SliceFuncs[*ori.Machine]) tableconverter.TableConverter[[]*ori.Machine] { + itemFuncs := tableconverter.Funcs[*ori.Machine](funcs) + merged := tableconverter.MergeFuncs[*ori.Machine]( + tableconverter.WellKnownLabels[*ori.Machine](tableCfg.WellKnownMachineLabels), + itemFuncs, + ) + return tableconverter.SliceFuncs[*ori.Machine](merged) + } + } + + return opts +} + +func (o *Options) Registry() (*renderer.Registry, error) { + cfg, err := o.Config() + if err != nil { + return nil, fmt.Errorf("error reading config: %w", err) + } + + registry := renderer.NewRegistry() + if err := renderer.AddToRegistry(registry); err != nil { + return nil, err + } + + tableConv := tableconverter.NewRegistry() + if err := tableconverters.MakeAddToRegistry(o.tableConvertersOptions(cfg))(tableConv); err != nil { + return nil, err + } + + if err := registry.Register("table", renderer.NewTable(tableConv)); err != nil { + return nil, err + } + + return registry, nil +} + +func (o *Options) Client() (ori.MachineRuntimeClient, func() error, error) { + address, err := oriremotemachine.GetAddressWithTimeout(3*time.Second, o.Address) + if err != nil { + return nil, nil, err + } + + conn, err := grpc.Dial(address, grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + return nil, nil, fmt.Errorf("error dialing: %w", err) + } + + return ori.NewMachineRuntimeClient(conn), conn.Close, nil +} + +func (o *Options) OutputOptions() *OutputOptions { + return &OutputOptions{ + factory: o, + } +} + +type OutputOptions struct { + factory Factory + Output string +} + +func (o *OutputOptions) AddFlags(fs *pflag.FlagSet) { + fs.StringVarP(&o.Output, "output", "o", o.Output, "Output format.") +} + +func (o *OutputOptions) Renderer(ifEmpty string) (renderer.Renderer, error) { + output := o.Output + if output == "" { + output = ifEmpty + } + + r, err := o.factory.Registry() + if err != nil { + return nil, err + } + + return r.Get(output) +} + +func (o *OutputOptions) RendererOrNil() (renderer.Renderer, error) { + output := o.Output + if output == "" { + return nil, nil + } + + r, err := o.factory.Registry() + if err != nil { + return nil, err + } + + return r.Get(output) +} + +var ( + MachineAliases = []string{"machines", "mach", "machs"} + MachineClassAliases = []string{"machineclasses", "mc", "mcs"} + VolumeAliases = []string{"volumes", "vol", "vols"} + NetworkInterfaceAliases = []string{"networkinterfaces", "nic", "nics"} +) diff --git a/orictl/cmd/orictl-machine/orictlmachine/create/create.go b/orictl-machine/cmd/orictl-machine/orictlmachine/create/create.go similarity index 59% rename from orictl/cmd/orictl-machine/orictlmachine/create/create.go rename to orictl-machine/cmd/orictl-machine/orictlmachine/create/create.go index 639ff9f5e..7e586896a 100644 --- a/orictl/cmd/orictl-machine/orictlmachine/create/create.go +++ b/orictl-machine/cmd/orictl-machine/orictlmachine/create/create.go @@ -15,16 +15,16 @@ package create import ( - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/create/machine" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/create/networkinterface" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/create/volume" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/create/volumeattachment" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/common" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/create/machine" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/create/networkinterface" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/create/volume" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/create/volumeattachment" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/spf13/cobra" ) -func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cobra.Command { +func Command(streams clicommon.Streams, clientFactory common.Factory) *cobra.Command { cmd := &cobra.Command{ Use: "create", } diff --git a/orictl/cmd/orictl-machine/orictlmachine/create/machine/machine.go b/orictl-machine/cmd/orictl-machine/orictlmachine/create/machine/machine.go similarity index 87% rename from orictl/cmd/orictl-machine/orictlmachine/create/machine/machine.go rename to orictl-machine/cmd/orictl-machine/orictlmachine/create/machine/machine.go index 02b6ba29e..419e6015b 100644 --- a/orictl/cmd/orictl-machine/orictlmachine/create/machine/machine.go +++ b/orictl-machine/cmd/orictl-machine/orictlmachine/create/machine/machine.go @@ -20,8 +20,8 @@ import ( "os" ori "github.com/onmetal/onmetal-api/ori/apis/machine/v1alpha1" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/common" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/common" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/onmetal/onmetal-api/orictl/decoder" "github.com/onmetal/onmetal-api/orictl/renderer" "github.com/spf13/cobra" @@ -37,9 +37,9 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) { fs.StringVarP(&o.Filename, "filename", "f", o.Filename, "Path to a file to read.") } -func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cobra.Command { +func Command(streams clicommon.Streams, clientFactory common.Factory) *cobra.Command { var ( - outputOpts common.OutputOptions + outputOpts = clientFactory.OutputOptions() opts Options ) @@ -50,7 +50,7 @@ func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cob ctx := cmd.Context() log := ctrl.LoggerFrom(ctx) - client, cleanup, err := clientFactory.New() + client, cleanup, err := clientFactory.Client() if err != nil { return err } diff --git a/orictl/cmd/orictl-machine/orictlmachine/create/networkinterface/networkinterface.go b/orictl-machine/cmd/orictl-machine/orictlmachine/create/networkinterface/networkinterface.go similarity index 88% rename from orictl/cmd/orictl-machine/orictlmachine/create/networkinterface/networkinterface.go rename to orictl-machine/cmd/orictl-machine/orictlmachine/create/networkinterface/networkinterface.go index 428b94805..2b2211d3a 100644 --- a/orictl/cmd/orictl-machine/orictlmachine/create/networkinterface/networkinterface.go +++ b/orictl-machine/cmd/orictl-machine/orictlmachine/create/networkinterface/networkinterface.go @@ -20,8 +20,8 @@ import ( "os" ori "github.com/onmetal/onmetal-api/ori/apis/machine/v1alpha1" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/common" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/common" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/onmetal/onmetal-api/orictl/decoder" "github.com/onmetal/onmetal-api/orictl/renderer" "github.com/spf13/cobra" @@ -40,9 +40,9 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) { func (o *Options) MarkFlagsRequired(cmd *cobra.Command) { } -func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cobra.Command { +func Command(streams clicommon.Streams, clientFactory common.Factory) *cobra.Command { var ( - outputOpts common.OutputOptions + outputOpts = clientFactory.OutputOptions() opts Options ) @@ -53,7 +53,7 @@ func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cob ctx := cmd.Context() log := ctrl.LoggerFrom(ctx) - client, cleanup, err := clientFactory.New() + client, cleanup, err := clientFactory.Client() if err != nil { return err } diff --git a/orictl/cmd/orictl-machine/orictlmachine/create/volume/volume.go b/orictl-machine/cmd/orictl-machine/orictlmachine/create/volume/volume.go similarity index 89% rename from orictl/cmd/orictl-machine/orictlmachine/create/volume/volume.go rename to orictl-machine/cmd/orictl-machine/orictlmachine/create/volume/volume.go index 95830cb9e..12ae7a595 100644 --- a/orictl/cmd/orictl-machine/orictlmachine/create/volume/volume.go +++ b/orictl-machine/cmd/orictl-machine/orictlmachine/create/volume/volume.go @@ -20,8 +20,8 @@ import ( "os" ori "github.com/onmetal/onmetal-api/ori/apis/machine/v1alpha1" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/common" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/common" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/onmetal/onmetal-api/orictl/decoder" "github.com/onmetal/onmetal-api/orictl/renderer" "github.com/spf13/cobra" @@ -40,7 +40,7 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) { func (o *Options) MarkFlagsRequired(cmd *cobra.Command) { } -func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cobra.Command { +func Command(streams clicommon.Streams, clientFactory common.Factory) *cobra.Command { var ( outputOpts common.OutputOptions opts Options @@ -53,7 +53,7 @@ func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cob ctx := cmd.Context() log := ctrl.LoggerFrom(ctx) - client, cleanup, err := clientFactory.New() + client, cleanup, err := clientFactory.Client() if err != nil { return err } diff --git a/orictl/cmd/orictl-machine/orictlmachine/create/volumeattachment/volumeattachment.go b/orictl-machine/cmd/orictl-machine/orictlmachine/create/volumeattachment/volumeattachment.go similarity index 89% rename from orictl/cmd/orictl-machine/orictlmachine/create/volumeattachment/volumeattachment.go rename to orictl-machine/cmd/orictl-machine/orictlmachine/create/volumeattachment/volumeattachment.go index f6a911e59..b274ed11a 100644 --- a/orictl/cmd/orictl-machine/orictlmachine/create/volumeattachment/volumeattachment.go +++ b/orictl-machine/cmd/orictl-machine/orictlmachine/create/volumeattachment/volumeattachment.go @@ -19,8 +19,8 @@ import ( "fmt" ori "github.com/onmetal/onmetal-api/ori/apis/machine/v1alpha1" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/common" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/common" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/onmetal/onmetal-api/orictl/decoder" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -41,7 +41,7 @@ func (o *Options) MarkFlagsRequired(cmd *cobra.Command) { _ = cmd.MarkFlagRequired("machine-id") } -func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cobra.Command { +func Command(streams clicommon.Streams, clientFactory common.Factory) *cobra.Command { var ( opts Options ) @@ -53,7 +53,7 @@ func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cob ctx := cmd.Context() log := ctrl.LoggerFrom(ctx) - client, cleanup, err := clientFactory.New() + client, cleanup, err := clientFactory.Client() if err != nil { return err } diff --git a/orictl/cmd/orictl-machine/orictlmachine/delete/delete.go b/orictl-machine/cmd/orictl-machine/orictlmachine/delete/delete.go similarity index 59% rename from orictl/cmd/orictl-machine/orictlmachine/delete/delete.go rename to orictl-machine/cmd/orictl-machine/orictlmachine/delete/delete.go index 905b42191..10b28576b 100644 --- a/orictl/cmd/orictl-machine/orictlmachine/delete/delete.go +++ b/orictl-machine/cmd/orictl-machine/orictlmachine/delete/delete.go @@ -15,16 +15,16 @@ package delete import ( - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/delete/machine" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/delete/networkinterface" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/delete/volume" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/delete/volumeattachment" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/common" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/delete/machine" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/delete/networkinterface" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/delete/volume" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/delete/volumeattachment" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/spf13/cobra" ) -func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cobra.Command { +func Command(streams clicommon.Streams, clientFactory common.Factory) *cobra.Command { cmd := &cobra.Command{ Use: "delete", } diff --git a/orictl/cmd/orictl-machine/orictlmachine/delete/machine/machine.go b/orictl-machine/cmd/orictl-machine/orictlmachine/delete/machine/machine.go similarity index 86% rename from orictl/cmd/orictl-machine/orictlmachine/delete/machine/machine.go rename to orictl-machine/cmd/orictl-machine/orictlmachine/delete/machine/machine.go index 89094a9ad..a6a0000ae 100644 --- a/orictl/cmd/orictl-machine/orictlmachine/delete/machine/machine.go +++ b/orictl-machine/cmd/orictl-machine/orictlmachine/delete/machine/machine.go @@ -19,15 +19,15 @@ import ( "fmt" ori "github.com/onmetal/onmetal-api/ori/apis/machine/v1alpha1" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/common" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/common" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/spf13/cobra" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ctrl "sigs.k8s.io/controller-runtime" ) -func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cobra.Command { +func Command(streams clicommon.Streams, clientFactory common.Factory) *cobra.Command { cmd := &cobra.Command{ Use: "machine id [ids...]", Aliases: common.MachineAliases, @@ -36,7 +36,7 @@ func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cob ctx := cmd.Context() log := ctrl.LoggerFrom(ctx) - client, cleanup, err := clientFactory.New() + client, cleanup, err := clientFactory.Client() if err != nil { return err } diff --git a/orictl/cmd/orictl-machine/orictlmachine/delete/networkinterface/networkinterface.go b/orictl-machine/cmd/orictl-machine/orictlmachine/delete/networkinterface/networkinterface.go similarity index 88% rename from orictl/cmd/orictl-machine/orictlmachine/delete/networkinterface/networkinterface.go rename to orictl-machine/cmd/orictl-machine/orictlmachine/delete/networkinterface/networkinterface.go index 7788d9451..c4faca016 100644 --- a/orictl/cmd/orictl-machine/orictlmachine/delete/networkinterface/networkinterface.go +++ b/orictl-machine/cmd/orictl-machine/orictlmachine/delete/networkinterface/networkinterface.go @@ -19,8 +19,8 @@ import ( "fmt" ori "github.com/onmetal/onmetal-api/ori/apis/machine/v1alpha1" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/common" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/common" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/spf13/cobra" "github.com/spf13/pflag" "google.golang.org/grpc/codes" @@ -37,7 +37,7 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) { func (o *Options) MarkFlagsRequired(cmd *cobra.Command) { } -func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cobra.Command { +func Command(streams clicommon.Streams, clientFactory common.Factory) *cobra.Command { var ( opts Options ) @@ -50,7 +50,7 @@ func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cob ctx := cmd.Context() log := ctrl.LoggerFrom(ctx) - client, cleanup, err := clientFactory.New() + client, cleanup, err := clientFactory.Client() if err != nil { return err } diff --git a/orictl/cmd/orictl-machine/orictlmachine/delete/volume/volume.go b/orictl-machine/cmd/orictl-machine/orictlmachine/delete/volume/volume.go similarity index 88% rename from orictl/cmd/orictl-machine/orictlmachine/delete/volume/volume.go rename to orictl-machine/cmd/orictl-machine/orictlmachine/delete/volume/volume.go index a84221e2b..48a22b6a7 100644 --- a/orictl/cmd/orictl-machine/orictlmachine/delete/volume/volume.go +++ b/orictl-machine/cmd/orictl-machine/orictlmachine/delete/volume/volume.go @@ -19,8 +19,8 @@ import ( "fmt" ori "github.com/onmetal/onmetal-api/ori/apis/machine/v1alpha1" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/common" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/common" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/spf13/cobra" "github.com/spf13/pflag" "google.golang.org/grpc/codes" @@ -37,7 +37,7 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) { func (o *Options) MarkFlagsRequired(cmd *cobra.Command) { } -func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cobra.Command { +func Command(streams clicommon.Streams, clientFactory common.Factory) *cobra.Command { var ( opts Options ) @@ -50,7 +50,7 @@ func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cob ctx := cmd.Context() log := ctrl.LoggerFrom(ctx) - client, cleanup, err := clientFactory.New() + client, cleanup, err := clientFactory.Client() if err != nil { return err } diff --git a/orictl/cmd/orictl-machine/orictlmachine/delete/volumeattachment/volumeattachment.go b/orictl-machine/cmd/orictl-machine/orictlmachine/delete/volumeattachment/volumeattachment.go similarity index 89% rename from orictl/cmd/orictl-machine/orictlmachine/delete/volumeattachment/volumeattachment.go rename to orictl-machine/cmd/orictl-machine/orictlmachine/delete/volumeattachment/volumeattachment.go index 4b511e5a2..7be6a757f 100644 --- a/orictl/cmd/orictl-machine/orictlmachine/delete/volumeattachment/volumeattachment.go +++ b/orictl-machine/cmd/orictl-machine/orictlmachine/delete/volumeattachment/volumeattachment.go @@ -19,8 +19,8 @@ import ( "fmt" ori "github.com/onmetal/onmetal-api/ori/apis/machine/v1alpha1" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/common" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/common" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/spf13/cobra" "github.com/spf13/pflag" "google.golang.org/grpc/codes" @@ -40,7 +40,7 @@ func (o *Options) MarkFlagsRequired(cmd *cobra.Command) { _ = cmd.MarkFlagRequired("machine-id") } -func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cobra.Command { +func Command(streams clicommon.Streams, clientFactory common.Factory) *cobra.Command { var ( opts Options ) @@ -53,7 +53,7 @@ func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cob ctx := cmd.Context() log := ctrl.LoggerFrom(ctx) - client, cleanup, err := clientFactory.New() + client, cleanup, err := clientFactory.Client() if err != nil { return err } diff --git a/orictl/cmd/orictl-machine/orictlmachine/exec/exec.go b/orictl-machine/cmd/orictl-machine/orictlmachine/exec/exec.go similarity index 91% rename from orictl/cmd/orictl-machine/orictlmachine/exec/exec.go rename to orictl-machine/cmd/orictl-machine/orictlmachine/exec/exec.go index a473538df..8ef18114d 100644 --- a/orictl/cmd/orictl-machine/orictlmachine/exec/exec.go +++ b/orictl-machine/cmd/orictl-machine/orictlmachine/exec/exec.go @@ -23,8 +23,8 @@ import ( "time" ori "github.com/onmetal/onmetal-api/ori/apis/machine/v1alpha1" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/common" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/common" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/spf13/cobra" "k8s.io/apimachinery/pkg/util/httpstream/spdy" "k8s.io/client-go/tools/remotecommand" @@ -32,7 +32,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" ) -func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cobra.Command { +func Command(streams clicommon.Streams, clientFactory common.Factory) *cobra.Command { cmd := &cobra.Command{ Use: "exec machine-id", Args: cobra.ExactArgs(1), @@ -40,7 +40,7 @@ func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cob ctx := cmd.Context() log := ctrl.LoggerFrom(ctx) - client, cleanup, err := clientFactory.New() + client, cleanup, err := clientFactory.Client() if err != nil { return err } diff --git a/orictl/cmd/orictl-machine/orictlmachine/get/get.go b/orictl-machine/cmd/orictl-machine/orictlmachine/get/get.go similarity index 59% rename from orictl/cmd/orictl-machine/orictlmachine/get/get.go rename to orictl-machine/cmd/orictl-machine/orictlmachine/get/get.go index 638a36855..6658bdb27 100644 --- a/orictl/cmd/orictl-machine/orictlmachine/get/get.go +++ b/orictl-machine/cmd/orictl-machine/orictlmachine/get/get.go @@ -15,16 +15,16 @@ package get import ( - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/get/machine" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/get/machineclass" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/get/networkinterface" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/get/volume" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/common" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/get/machine" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/get/machineclass" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/get/networkinterface" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/get/volume" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/spf13/cobra" ) -func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cobra.Command { +func Command(streams clicommon.Streams, clientFactory common.Factory) *cobra.Command { cmd := &cobra.Command{ Use: "get", } diff --git a/orictl/cmd/orictl-machine/orictlmachine/get/machine/machine.go b/orictl-machine/cmd/orictl-machine/orictlmachine/get/machine/machine.go similarity index 87% rename from orictl/cmd/orictl-machine/orictlmachine/get/machine/machine.go rename to orictl-machine/cmd/orictl-machine/orictlmachine/get/machine/machine.go index 381d6bfb0..ed1c1cd00 100644 --- a/orictl/cmd/orictl-machine/orictlmachine/get/machine/machine.go +++ b/orictl-machine/cmd/orictl-machine/orictlmachine/get/machine/machine.go @@ -19,8 +19,8 @@ import ( "fmt" ori "github.com/onmetal/onmetal-api/ori/apis/machine/v1alpha1" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/common" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/common" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/onmetal/onmetal-api/orictl/renderer" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -35,10 +35,10 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) { fs.StringToStringVarP(&o.Labels, "labels", "l", o.Labels, "Labels to filter the machines by.") } -func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cobra.Command { +func Command(streams clicommon.Streams, clientFactory common.Factory) *cobra.Command { var ( opts Options - outputOpts common.OutputOptions + outputOpts = clientFactory.OutputOptions() ) cmd := &cobra.Command{ @@ -49,7 +49,7 @@ func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cob ctx := cmd.Context() log := ctrl.LoggerFrom(ctx) - client, cleanup, err := clientFactory.New() + client, cleanup, err := clientFactory.Client() if err != nil { return err } diff --git a/orictl/cmd/orictl-machine/orictlmachine/get/machineclass/machineclass.go b/orictl-machine/cmd/orictl-machine/orictlmachine/get/machineclass/machineclass.go similarity index 84% rename from orictl/cmd/orictl-machine/orictlmachine/get/machineclass/machineclass.go rename to orictl-machine/cmd/orictl-machine/orictlmachine/get/machineclass/machineclass.go index 64eac0fe2..a43ffff8a 100644 --- a/orictl/cmd/orictl-machine/orictlmachine/get/machineclass/machineclass.go +++ b/orictl-machine/cmd/orictl-machine/orictlmachine/get/machineclass/machineclass.go @@ -19,16 +19,16 @@ import ( "fmt" ori "github.com/onmetal/onmetal-api/ori/apis/machine/v1alpha1" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/common" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/common" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/onmetal/onmetal-api/orictl/renderer" "github.com/spf13/cobra" ctrl "sigs.k8s.io/controller-runtime" ) -func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cobra.Command { +func Command(streams clicommon.Streams, clientFactory common.Factory) *cobra.Command { var ( - outputOpts common.OutputOptions + outputOpts = clientFactory.OutputOptions() ) cmd := &cobra.Command{ @@ -38,7 +38,7 @@ func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cob ctx := cmd.Context() log := ctrl.LoggerFrom(ctx) - client, cleanup, err := clientFactory.New() + client, cleanup, err := clientFactory.Client() if err != nil { return err } diff --git a/orictl/cmd/orictl-machine/orictlmachine/get/networkinterface/networkinterface.go b/orictl-machine/cmd/orictl-machine/orictlmachine/get/networkinterface/networkinterface.go similarity index 87% rename from orictl/cmd/orictl-machine/orictlmachine/get/networkinterface/networkinterface.go rename to orictl-machine/cmd/orictl-machine/orictlmachine/get/networkinterface/networkinterface.go index 90061e40e..59c2a44cb 100644 --- a/orictl/cmd/orictl-machine/orictlmachine/get/networkinterface/networkinterface.go +++ b/orictl-machine/cmd/orictl-machine/orictlmachine/get/networkinterface/networkinterface.go @@ -19,8 +19,8 @@ import ( "fmt" ori "github.com/onmetal/onmetal-api/ori/apis/machine/v1alpha1" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/common" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/common" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/onmetal/onmetal-api/orictl/renderer" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -33,10 +33,10 @@ type Options struct { func (o *Options) AddFlags(fs *pflag.FlagSet) { } -func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cobra.Command { +func Command(streams clicommon.Streams, clientFactory common.Factory) *cobra.Command { var ( opts Options - outputOpts common.OutputOptions + outputOpts = clientFactory.OutputOptions() ) cmd := &cobra.Command{ @@ -47,7 +47,7 @@ func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cob ctx := cmd.Context() log := ctrl.LoggerFrom(ctx) - client, cleanup, err := clientFactory.New() + client, cleanup, err := clientFactory.Client() if err != nil { return err } diff --git a/orictl/cmd/orictl-machine/orictlmachine/get/volume/volume.go b/orictl-machine/cmd/orictl-machine/orictlmachine/get/volume/volume.go similarity index 86% rename from orictl/cmd/orictl-machine/orictlmachine/get/volume/volume.go rename to orictl-machine/cmd/orictl-machine/orictlmachine/get/volume/volume.go index af9d4c3b4..4b5e14288 100644 --- a/orictl/cmd/orictl-machine/orictlmachine/get/volume/volume.go +++ b/orictl-machine/cmd/orictl-machine/orictlmachine/get/volume/volume.go @@ -19,8 +19,8 @@ import ( "fmt" ori "github.com/onmetal/onmetal-api/ori/apis/machine/v1alpha1" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/common" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/common" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/onmetal/onmetal-api/orictl/renderer" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -33,10 +33,10 @@ type Options struct { func (o *Options) AddFlags(fs *pflag.FlagSet) { } -func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cobra.Command { +func Command(streams clicommon.Streams, clientFactory common.Factory) *cobra.Command { var ( opts Options - outputOpts common.OutputOptions + outputOpts = clientFactory.OutputOptions() ) cmd := &cobra.Command{ @@ -47,7 +47,7 @@ func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cob ctx := cmd.Context() log := ctrl.LoggerFrom(ctx) - client, cleanup, err := clientFactory.New() + client, cleanup, err := clientFactory.Client() if err != nil { return err } diff --git a/orictl/cmd/orictl-machine/orictlmachine/orictlmachine.go b/orictl-machine/cmd/orictl-machine/orictlmachine/orictlmachine.go similarity index 70% rename from orictl/cmd/orictl-machine/orictlmachine/orictlmachine.go rename to orictl-machine/cmd/orictl-machine/orictlmachine/orictlmachine.go index e8169323d..f1128567c 100644 --- a/orictl/cmd/orictl-machine/orictlmachine/orictlmachine.go +++ b/orictl-machine/cmd/orictl-machine/orictlmachine/orictlmachine.go @@ -17,13 +17,13 @@ package orictlmachine import ( goflag "flag" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/create" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/delete" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/exec" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/get" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/update" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/common" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/create" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/delete" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/exec" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/get" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/update" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/spf13/cobra" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/log/zap" @@ -32,7 +32,7 @@ import ( func Command(streams clicommon.Streams) *cobra.Command { var ( zapOpts zap.Options - clientOpts common.ClientOptions + clientOpts common.Options ) cmd := &cobra.Command{ diff --git a/orictl/cmd/orictl-machine/orictlmachine/update/update.go b/orictl-machine/cmd/orictl-machine/orictlmachine/update/update.go similarity index 75% rename from orictl/cmd/orictl-machine/orictlmachine/update/update.go rename to orictl-machine/cmd/orictl-machine/orictlmachine/update/update.go index 639d25461..742c361a0 100644 --- a/orictl/cmd/orictl-machine/orictlmachine/update/update.go +++ b/orictl-machine/cmd/orictl-machine/orictlmachine/update/update.go @@ -15,12 +15,12 @@ package update import ( - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-machine/orictlmachine/common" + "github.com/onmetal/onmetal-api/orictl-machine/cmd/orictl-machine/orictlmachine/common" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/spf13/cobra" ) -func Command(streams clicommon.Streams, clientFactory common.ClientFactory) *cobra.Command { +func Command(streams clicommon.Streams, clientFactory common.Factory) *cobra.Command { cmd := &cobra.Command{ Use: "update", } diff --git a/orictl/config/samples/machine-networkinterface.yaml b/orictl-machine/config/samples/machine-networkinterface.yaml similarity index 100% rename from orictl/config/samples/machine-networkinterface.yaml rename to orictl-machine/config/samples/machine-networkinterface.yaml diff --git a/orictl/config/samples/machine-volume.yaml b/orictl-machine/config/samples/machine-volume.yaml similarity index 100% rename from orictl/config/samples/machine-volume.yaml rename to orictl-machine/config/samples/machine-volume.yaml diff --git a/orictl/config/samples/machine.yaml b/orictl-machine/config/samples/machine.yaml similarity index 100% rename from orictl/config/samples/machine.yaml rename to orictl-machine/config/samples/machine.yaml diff --git a/orictl/config/samples/volumeattachment.yaml b/orictl-machine/config/samples/volumeattachment.yaml similarity index 100% rename from orictl/config/samples/volumeattachment.yaml rename to orictl-machine/config/samples/volumeattachment.yaml diff --git a/orictl/table/tableconverters/machine/machine.go b/orictl-machine/tableconverters/machine.go similarity index 65% rename from orictl/table/tableconverters/machine/machine.go rename to orictl-machine/tableconverters/machine.go index ec29503fd..70df6aafd 100644 --- a/orictl/table/tableconverters/machine/machine.go +++ b/orictl-machine/tableconverters/machine.go @@ -12,19 +12,19 @@ // See the License for the specific language governing permissions and // limitations under the License. -package machine +package tableconverters import ( "time" ori "github.com/onmetal/onmetal-api/ori/apis/machine/v1alpha1" - "github.com/onmetal/onmetal-api/orictl/table" - "github.com/onmetal/onmetal-api/orictl/table/tableconverter" + "github.com/onmetal/onmetal-api/orictl/api" + "github.com/onmetal/onmetal-api/orictl/tableconverter" "k8s.io/apimachinery/pkg/util/duration" ) var ( - machineHeaders = []table.Header{ + machineHeaders = []api.Header{ {Name: "ID"}, {Name: "Class"}, {Name: "Image"}, @@ -33,26 +33,18 @@ var ( } ) -var Machine, MachineSlice = tableconverter.ForType[*ori.Machine]( //nolint:revive - func() ([]table.Header, error) { - return machineHeaders, nil - }, - func(machine *ori.Machine) ([]table.Row, error) { - return []table.Row{ - { +var ( + Machine = tableconverter.Funcs[*ori.Machine]{ + Headers: tableconverter.Headers(machineHeaders), + Rows: tableconverter.SingleRowFrom(func(machine *ori.Machine) (api.Row, error) { + return api.Row{ machine.Metadata.Id, machine.Spec.Class, machine.Spec.GetImage().GetImage(), machine.Status.State.String(), duration.HumanDuration(time.Since(time.Unix(0, machine.Metadata.CreatedAt))), - }, - }, nil - }, + }, nil + }), + } + MachineSlice = tableconverter.SliceFuncs[*ori.Machine](Machine) ) - -func init() { - RegistryBuilder.Register( - tableconverter.ToTaggedAny(Machine), - tableconverter.ToTaggedAny(MachineSlice), - ) -} diff --git a/orictl/table/tableconverters/machine/machineclass.go b/orictl-machine/tableconverters/machineclass.go similarity index 63% rename from orictl/table/tableconverters/machine/machineclass.go rename to orictl-machine/tableconverters/machineclass.go index 9cd9ab431..e1b133b98 100644 --- a/orictl/table/tableconverters/machine/machineclass.go +++ b/orictl-machine/tableconverters/machineclass.go @@ -12,41 +12,32 @@ // See the License for the specific language governing permissions and // limitations under the License. -package machine +package tableconverters import ( ori "github.com/onmetal/onmetal-api/ori/apis/machine/v1alpha1" - "github.com/onmetal/onmetal-api/orictl/table" - "github.com/onmetal/onmetal-api/orictl/table/tableconverter" + "github.com/onmetal/onmetal-api/orictl/api" + "github.com/onmetal/onmetal-api/orictl/tableconverter" "k8s.io/apimachinery/pkg/api/resource" ) var ( - machineClassHeaders = []table.Header{ + machineClassHeaders = []api.Header{ {Name: "Name"}, {Name: "CPU"}, {Name: "Memory"}, } -) -var MachineClass, MachineClassSlice = tableconverter.ForType[*ori.MachineClass]( //nolint:revive - func() ([]table.Header, error) { - return machineClassHeaders, nil - }, - func(class *ori.MachineClass) ([]table.Row, error) { - return []table.Row{ - { + MachineClass = tableconverter.Funcs[*ori.MachineClass]{ + Headers: tableconverter.Headers(machineClassHeaders), + Rows: tableconverter.SingleRowFrom(func(class *ori.MachineClass) (api.Row, error) { + return api.Row{ class.Name, resource.NewMilliQuantity(class.Capabilities.CpuMillis, resource.DecimalSI).String(), resource.NewQuantity(int64(class.Capabilities.MemoryBytes), resource.DecimalSI).String(), - }, - }, nil - }, -) + }, nil + }), + } -func init() { - RegistryBuilder.Register( - tableconverter.ToTaggedAny(MachineClass), - tableconverter.ToTaggedAny(MachineClassSlice), - ) -} + MachineClassSlice = tableconverter.SliceFuncs[*ori.MachineClass](MachineClass) +) diff --git a/orictl/table/tableconverters/machine/networkinterface.go b/orictl-machine/tableconverters/networkinterface.go similarity index 64% rename from orictl/table/tableconverters/machine/networkinterface.go rename to orictl-machine/tableconverters/networkinterface.go index 8ded30c90..0481955c4 100644 --- a/orictl/table/tableconverters/machine/networkinterface.go +++ b/orictl-machine/tableconverters/networkinterface.go @@ -12,20 +12,20 @@ // See the License for the specific language governing permissions and // limitations under the License. -package machine +package tableconverters import ( "strings" "time" ori "github.com/onmetal/onmetal-api/ori/apis/machine/v1alpha1" - "github.com/onmetal/onmetal-api/orictl/table" - "github.com/onmetal/onmetal-api/orictl/table/tableconverter" + "github.com/onmetal/onmetal-api/orictl/api" + "github.com/onmetal/onmetal-api/orictl/tableconverter" "k8s.io/apimachinery/pkg/util/duration" ) var ( - networkInterfaceHeaders = []table.Header{ + networkInterfaceHeaders = []api.Header{ {Name: "ID"}, {Name: "Network Handle"}, {Name: "IPs"}, @@ -34,26 +34,18 @@ var ( } ) -var NetworkInterface, NetworkInterfaceSlice = tableconverter.ForType[*ori.NetworkInterface]( //nolint:revive - func() ([]table.Header, error) { - return networkInterfaceHeaders, nil - }, - func(networkInterface *ori.NetworkInterface) ([]table.Row, error) { - return []table.Row{ - { +var ( + NetworkInterface = tableconverter.Funcs[*ori.NetworkInterface]{ + Headers: tableconverter.Headers(networkInterfaceHeaders), + Rows: tableconverter.SingleRowFrom(func(networkInterface *ori.NetworkInterface) (api.Row, error) { + return api.Row{ networkInterface.Metadata.Id, networkInterface.Spec.Network.Handle, strings.Join(networkInterface.Spec.Ips, ","), networkInterface.Spec.GetVirtualIp().GetIp(), duration.HumanDuration(time.Since(time.Unix(0, networkInterface.Metadata.CreatedAt))), - }, - }, nil - }, + }, nil + }), + } + NetworkInterfaceSlice = tableconverter.SliceFuncs[*ori.NetworkInterface](NetworkInterface) ) - -func init() { - RegistryBuilder.Register( - tableconverter.ToTaggedAny(NetworkInterface), - tableconverter.ToTaggedAny(NetworkInterfaceSlice), - ) -} diff --git a/orictl-machine/tableconverters/register.go b/orictl-machine/tableconverters/register.go new file mode 100644 index 000000000..1047327c9 --- /dev/null +++ b/orictl-machine/tableconverters/register.go @@ -0,0 +1,49 @@ +// Copyright 2022 OnMetal authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tableconverters + +import ( + ori "github.com/onmetal/onmetal-api/ori/apis/machine/v1alpha1" + "github.com/onmetal/onmetal-api/orictl/tableconverter" +) + +type Options struct { + TransformMachine func(funcs tableconverter.Funcs[*ori.Machine]) tableconverter.TableConverter[*ori.Machine] + TransformMachineSlice func(funcs tableconverter.SliceFuncs[*ori.Machine]) tableconverter.TableConverter[[]*ori.Machine] +} + +func transformIfNotNil[TC tableconverter.TableConverter[E], E any](tc TC, f func(TC) tableconverter.TableConverter[E]) tableconverter.TableConverter[E] { + if f != nil { + return f(tc) + } + return tc +} + +func MakeAddToRegistry(opts Options) func(*tableconverter.Registry) error { + var rb tableconverter.RegistryBuilder + + machine := transformIfNotNil[tableconverter.Funcs[*ori.Machine]](Machine, opts.TransformMachine) + machineSlice := transformIfNotNil[tableconverter.SliceFuncs[*ori.Machine]](MachineSlice, opts.TransformMachineSlice) + + rb.Register(tableconverter.ToTagAndTypedAny[*ori.Machine](machine)) + rb.Register(tableconverter.ToTagAndTypedAny[[]*ori.Machine](machineSlice)) + rb.Register(tableconverter.ToTagAndTypedAny[*ori.MachineClass](MachineClass)) + rb.Register(tableconverter.ToTagAndTypedAny[[]*ori.MachineClass](MachineClassSlice)) + rb.Register(tableconverter.ToTagAndTypedAny[*ori.NetworkInterface](NetworkInterface)) + rb.Register(tableconverter.ToTagAndTypedAny[[]*ori.NetworkInterface](NetworkInterfaceSlice)) + rb.Register(tableconverter.ToTagAndTypedAny[*ori.Volume](Volume)) + rb.Register(tableconverter.ToTagAndTypedAny[[]*ori.Volume](VolumeSlice)) + return rb.AddToRegistry +} diff --git a/orictl/table/tableconverters/machine/volume.go b/orictl-machine/tableconverters/volume.go similarity index 64% rename from orictl/table/tableconverters/machine/volume.go rename to orictl-machine/tableconverters/volume.go index e931f13e3..c43bd4a09 100644 --- a/orictl/table/tableconverters/machine/volume.go +++ b/orictl-machine/tableconverters/volume.go @@ -12,19 +12,19 @@ // See the License for the specific language governing permissions and // limitations under the License. -package machine +package tableconverters import ( "time" ori "github.com/onmetal/onmetal-api/ori/apis/machine/v1alpha1" - "github.com/onmetal/onmetal-api/orictl/table" - "github.com/onmetal/onmetal-api/orictl/table/tableconverter" + "github.com/onmetal/onmetal-api/orictl/api" + "github.com/onmetal/onmetal-api/orictl/tableconverter" "k8s.io/apimachinery/pkg/util/duration" ) var ( - volumeHeaders = []table.Header{ + volumeHeaders = []api.Header{ {Name: "ID"}, {Name: "Driver"}, {Name: "Handle"}, @@ -32,25 +32,17 @@ var ( } ) -var Volume, VolumeSlice = tableconverter.ForType[*ori.Volume]( //nolint:revive - func() ([]table.Header, error) { - return volumeHeaders, nil - }, - func(volume *ori.Volume) ([]table.Row, error) { - return []table.Row{ - { +var ( + Volume = tableconverter.Funcs[*ori.Volume]{ + Headers: tableconverter.Headers(volumeHeaders), + Rows: tableconverter.SingleRowFrom(func(volume *ori.Volume) (api.Row, error) { + return api.Row{ volume.Metadata.Id, volume.Spec.Driver, volume.Spec.Handle, duration.HumanDuration(time.Since(time.Unix(0, volume.Metadata.CreatedAt))), - }, - }, nil - }, + }, nil + }), + } + VolumeSlice = tableconverter.SliceFuncs[*ori.Volume](Volume) ) - -func init() { - RegistryBuilder.Register( - tableconverter.ToTaggedAny(Volume), - tableconverter.ToTaggedAny(VolumeSlice), - ) -} diff --git a/orictl/cmd/orictl-volume/main.go b/orictl-volume/cmd/orictl-volume/main.go similarity index 86% rename from orictl/cmd/orictl-volume/main.go rename to orictl-volume/cmd/orictl-volume/main.go index 64760d2f1..90767a5ff 100644 --- a/orictl/cmd/orictl-volume/main.go +++ b/orictl-volume/cmd/orictl-volume/main.go @@ -17,8 +17,8 @@ package main import ( "os" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-volume/orictlvolume" + "github.com/onmetal/onmetal-api/orictl-volume/cmd/orictl-volume/orictlvolume" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" ctrl "sigs.k8s.io/controller-runtime" ) diff --git a/orictl/cmd/orictl-volume/orictlvolume/common/common.go b/orictl-volume/cmd/orictl-volume/orictlvolume/common/common.go similarity index 91% rename from orictl/cmd/orictl-volume/orictlvolume/common/common.go rename to orictl-volume/cmd/orictl-volume/orictlvolume/common/common.go index 3e58ae214..964f99f1d 100644 --- a/orictl/cmd/orictl-volume/orictlvolume/common/common.go +++ b/orictl-volume/cmd/orictl-volume/orictlvolume/common/common.go @@ -20,9 +20,9 @@ import ( ori "github.com/onmetal/onmetal-api/ori/apis/volume/v1alpha1" oriremotevolume "github.com/onmetal/onmetal-api/ori/remote/volume" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" + "github.com/onmetal/onmetal-api/orictl-volume/renderers" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/onmetal/onmetal-api/orictl/renderer" - "github.com/onmetal/onmetal-api/orictl/renderers/volume" "github.com/spf13/pflag" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" @@ -31,7 +31,7 @@ import ( var Renderer = renderer.NewRegistry() func init() { - if err := volume.AddToRegistry(Renderer); err != nil { + if err := renderers.AddToRegistry(Renderer); err != nil { panic(err) } } diff --git a/orictl/cmd/orictl-volume/orictlvolume/create/create.go b/orictl-volume/cmd/orictl-volume/orictlvolume/create/create.go similarity index 78% rename from orictl/cmd/orictl-volume/orictlvolume/create/create.go rename to orictl-volume/cmd/orictl-volume/orictlvolume/create/create.go index 309573af1..9bcfb8928 100644 --- a/orictl/cmd/orictl-volume/orictlvolume/create/create.go +++ b/orictl-volume/cmd/orictl-volume/orictlvolume/create/create.go @@ -15,9 +15,9 @@ package create import ( - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-volume/orictlvolume/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-volume/orictlvolume/create/volume" + "github.com/onmetal/onmetal-api/orictl-volume/cmd/orictl-volume/orictlvolume/common" + "github.com/onmetal/onmetal-api/orictl-volume/cmd/orictl-volume/orictlvolume/create/volume" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/spf13/cobra" ) diff --git a/orictl/cmd/orictl-volume/orictlvolume/create/volume/volume.go b/orictl-volume/cmd/orictl-volume/orictlvolume/create/volume/volume.go similarity index 94% rename from orictl/cmd/orictl-volume/orictlvolume/create/volume/volume.go rename to orictl-volume/cmd/orictl-volume/orictlvolume/create/volume/volume.go index 93fdccf67..fea4943ab 100644 --- a/orictl/cmd/orictl-volume/orictlvolume/create/volume/volume.go +++ b/orictl-volume/cmd/orictl-volume/orictlvolume/create/volume/volume.go @@ -20,8 +20,8 @@ import ( "os" ori "github.com/onmetal/onmetal-api/ori/apis/volume/v1alpha1" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-volume/orictlvolume/common" + "github.com/onmetal/onmetal-api/orictl-volume/cmd/orictl-volume/orictlvolume/common" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/onmetal/onmetal-api/orictl/decoder" "github.com/onmetal/onmetal-api/orictl/renderer" "github.com/spf13/cobra" diff --git a/orictl/cmd/orictl-volume/orictlvolume/delete/delete.go b/orictl-volume/cmd/orictl-volume/orictlvolume/delete/delete.go similarity index 78% rename from orictl/cmd/orictl-volume/orictlvolume/delete/delete.go rename to orictl-volume/cmd/orictl-volume/orictlvolume/delete/delete.go index 74223472e..fec15bfe7 100644 --- a/orictl/cmd/orictl-volume/orictlvolume/delete/delete.go +++ b/orictl-volume/cmd/orictl-volume/orictlvolume/delete/delete.go @@ -15,9 +15,9 @@ package delete import ( - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-volume/orictlvolume/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-volume/orictlvolume/delete/volume" + "github.com/onmetal/onmetal-api/orictl-volume/cmd/orictl-volume/orictlvolume/common" + "github.com/onmetal/onmetal-api/orictl-volume/cmd/orictl-volume/orictlvolume/delete/volume" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/spf13/cobra" ) diff --git a/orictl/cmd/orictl-volume/orictlvolume/delete/volume/volume.go b/orictl-volume/cmd/orictl-volume/orictlvolume/delete/volume/volume.go similarity index 93% rename from orictl/cmd/orictl-volume/orictlvolume/delete/volume/volume.go rename to orictl-volume/cmd/orictl-volume/orictlvolume/delete/volume/volume.go index cf746636c..22092d716 100644 --- a/orictl/cmd/orictl-volume/orictlvolume/delete/volume/volume.go +++ b/orictl-volume/cmd/orictl-volume/orictlvolume/delete/volume/volume.go @@ -19,8 +19,8 @@ import ( "fmt" ori "github.com/onmetal/onmetal-api/ori/apis/volume/v1alpha1" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-volume/orictlvolume/common" + "github.com/onmetal/onmetal-api/orictl-volume/cmd/orictl-volume/orictlvolume/common" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/spf13/cobra" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" diff --git a/orictl/cmd/orictl-volume/orictlvolume/get/get.go b/orictl-volume/cmd/orictl-volume/orictlvolume/get/get.go similarity index 73% rename from orictl/cmd/orictl-volume/orictlvolume/get/get.go rename to orictl-volume/cmd/orictl-volume/orictlvolume/get/get.go index 0126c19f0..0aa287faa 100644 --- a/orictl/cmd/orictl-volume/orictlvolume/get/get.go +++ b/orictl-volume/cmd/orictl-volume/orictlvolume/get/get.go @@ -15,10 +15,10 @@ package get import ( - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-volume/orictlvolume/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-volume/orictlvolume/get/volume" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-volume/orictlvolume/get/volumeclass" + "github.com/onmetal/onmetal-api/orictl-volume/cmd/orictl-volume/orictlvolume/common" + "github.com/onmetal/onmetal-api/orictl-volume/cmd/orictl-volume/orictlvolume/get/volume" + "github.com/onmetal/onmetal-api/orictl-volume/cmd/orictl-volume/orictlvolume/get/volumeclass" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/spf13/cobra" ) diff --git a/orictl/cmd/orictl-volume/orictlvolume/get/volume/volume.go b/orictl-volume/cmd/orictl-volume/orictlvolume/get/volume/volume.go similarity index 93% rename from orictl/cmd/orictl-volume/orictlvolume/get/volume/volume.go rename to orictl-volume/cmd/orictl-volume/orictlvolume/get/volume/volume.go index 2755b55f2..52632371b 100644 --- a/orictl/cmd/orictl-volume/orictlvolume/get/volume/volume.go +++ b/orictl-volume/cmd/orictl-volume/orictlvolume/get/volume/volume.go @@ -19,8 +19,8 @@ import ( "fmt" ori "github.com/onmetal/onmetal-api/ori/apis/volume/v1alpha1" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-volume/orictlvolume/common" + "github.com/onmetal/onmetal-api/orictl-volume/cmd/orictl-volume/orictlvolume/common" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/onmetal/onmetal-api/orictl/renderer" "github.com/spf13/cobra" "github.com/spf13/pflag" diff --git a/orictl/cmd/orictl-volume/orictlvolume/get/volumeclass/volumeclass.go b/orictl-volume/cmd/orictl-volume/orictlvolume/get/volumeclass/volumeclass.go similarity index 93% rename from orictl/cmd/orictl-volume/orictlvolume/get/volumeclass/volumeclass.go rename to orictl-volume/cmd/orictl-volume/orictlvolume/get/volumeclass/volumeclass.go index 6b67ae695..c9fa43d43 100644 --- a/orictl/cmd/orictl-volume/orictlvolume/get/volumeclass/volumeclass.go +++ b/orictl-volume/cmd/orictl-volume/orictlvolume/get/volumeclass/volumeclass.go @@ -19,8 +19,8 @@ import ( "fmt" ori "github.com/onmetal/onmetal-api/ori/apis/volume/v1alpha1" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-volume/orictlvolume/common" + "github.com/onmetal/onmetal-api/orictl-volume/cmd/orictl-volume/orictlvolume/common" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/onmetal/onmetal-api/orictl/renderer" "github.com/spf13/cobra" ctrl "sigs.k8s.io/controller-runtime" diff --git a/orictl/cmd/orictl-volume/orictlvolume/orictlvolume.go b/orictl-volume/cmd/orictl-volume/orictlvolume/orictlvolume.go similarity index 75% rename from orictl/cmd/orictl-volume/orictlvolume/orictlvolume.go rename to orictl-volume/cmd/orictl-volume/orictlvolume/orictlvolume.go index 1a597184a..e2e06b6ff 100644 --- a/orictl/cmd/orictl-volume/orictlvolume/orictlvolume.go +++ b/orictl-volume/cmd/orictl-volume/orictlvolume/orictlvolume.go @@ -17,11 +17,11 @@ package orictlvolume import ( goflag "flag" - clicommon "github.com/onmetal/onmetal-api/orictl/cli/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-volume/orictlvolume/common" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-volume/orictlvolume/create" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-volume/orictlvolume/delete" - "github.com/onmetal/onmetal-api/orictl/cmd/orictl-volume/orictlvolume/get" + "github.com/onmetal/onmetal-api/orictl-volume/cmd/orictl-volume/orictlvolume/common" + "github.com/onmetal/onmetal-api/orictl-volume/cmd/orictl-volume/orictlvolume/create" + delete2 "github.com/onmetal/onmetal-api/orictl-volume/cmd/orictl-volume/orictlvolume/delete" + "github.com/onmetal/onmetal-api/orictl-volume/cmd/orictl-volume/orictlvolume/get" + clicommon "github.com/onmetal/onmetal-api/orictl/cmd" "github.com/spf13/cobra" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/log/zap" @@ -50,7 +50,7 @@ func Command(streams clicommon.Streams) *cobra.Command { cmd.AddCommand( get.Command(streams, &clientOpts), - delete.Command(streams, &clientOpts), + delete2.Command(streams, &clientOpts), create.Command(streams, &clientOpts), ) diff --git a/orictl/config/samples/volume.yaml b/orictl-volume/config/samples/volume.yaml similarity index 100% rename from orictl/config/samples/volume.yaml rename to orictl-volume/config/samples/volume.yaml diff --git a/orictl/renderers/volume/register.go b/orictl-volume/renderers/register.go similarity index 82% rename from orictl/renderers/volume/register.go rename to orictl-volume/renderers/register.go index aae770086..663bc8cb3 100644 --- a/orictl/renderers/volume/register.go +++ b/orictl-volume/renderers/register.go @@ -12,12 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -package volume +package renderers import ( + "github.com/onmetal/onmetal-api/orictl-volume/tableconverters" "github.com/onmetal/onmetal-api/orictl/renderer" - "github.com/onmetal/onmetal-api/orictl/table/tableconverter" - "github.com/onmetal/onmetal-api/orictl/table/tableconverters/volume" + "github.com/onmetal/onmetal-api/orictl/tableconverter" ) var ( @@ -29,7 +29,7 @@ func init() { RegistryBuilder.Add(renderer.AddToRegistry) RegistryBuilder.Add(func(registry *renderer.Registry) error { tableConverter := tableconverter.NewRegistry() - if err := volume.AddToRegistry(tableConverter); err != nil { + if err := tableconverters.AddToRegistry(tableConverter); err != nil { return err } return registry.Register("table", renderer.NewTable(tableConverter)) diff --git a/orictl/table/tableconverters/bucket/register.go b/orictl-volume/tableconverters/register.go similarity index 89% rename from orictl/table/tableconverters/bucket/register.go rename to orictl-volume/tableconverters/register.go index a14afe7f4..b6f207fd8 100644 --- a/orictl/table/tableconverters/bucket/register.go +++ b/orictl-volume/tableconverters/register.go @@ -12,10 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -package bucket +package tableconverters import ( - "github.com/onmetal/onmetal-api/orictl/table/tableconverter" + "github.com/onmetal/onmetal-api/orictl/tableconverter" ) var ( diff --git a/orictl/table/tableconverters/volume/volume.go b/orictl-volume/tableconverters/volume.go similarity index 65% rename from orictl/table/tableconverters/volume/volume.go rename to orictl-volume/tableconverters/volume.go index 11db6be37..9f5d202e0 100644 --- a/orictl/table/tableconverters/volume/volume.go +++ b/orictl-volume/tableconverters/volume.go @@ -12,19 +12,19 @@ // See the License for the specific language governing permissions and // limitations under the License. -package volume +package tableconverters import ( "time" ori "github.com/onmetal/onmetal-api/ori/apis/volume/v1alpha1" - "github.com/onmetal/onmetal-api/orictl/table" - "github.com/onmetal/onmetal-api/orictl/table/tableconverter" + "github.com/onmetal/onmetal-api/orictl/api" + "github.com/onmetal/onmetal-api/orictl/tableconverter" "k8s.io/apimachinery/pkg/util/duration" ) var ( - volumeHeaders = []table.Header{ + volumeHeaders = []api.Header{ {Name: "ID"}, {Name: "Class"}, {Name: "Image"}, @@ -33,26 +33,25 @@ var ( } ) -var Volume, VolumeSlice = tableconverter.ForType[*ori.Volume]( //nolint:revive - func() ([]table.Header, error) { - return volumeHeaders, nil - }, - func(volume *ori.Volume) ([]table.Row, error) { - return []table.Row{ - { +var ( + Volume = tableconverter.Funcs[*ori.Volume]{ + Headers: tableconverter.Headers(volumeHeaders), + Rows: tableconverter.SingleRowFrom(func(volume *ori.Volume) (api.Row, error) { + return api.Row{ volume.Metadata.Id, volume.Spec.Class, volume.Spec.Image, volume.Status.State.String(), duration.HumanDuration(time.Since(time.Unix(0, volume.Metadata.CreatedAt))), - }, - }, nil - }, + }, nil + }), + } + VolumeSlice = tableconverter.SliceFuncs[*ori.Volume](Volume) ) func init() { RegistryBuilder.Register( - tableconverter.ToTaggedAny(Volume), - tableconverter.ToTaggedAny(VolumeSlice), + tableconverter.ToTagAndTypedAny[*ori.Volume](Volume), + tableconverter.ToTagAndTypedAny[[]*ori.Volume](VolumeSlice), ) } diff --git a/orictl/table/tableconverters/volume/volumeclass.go b/orictl-volume/tableconverters/volumeclass.go similarity index 58% rename from orictl/table/tableconverters/volume/volumeclass.go rename to orictl-volume/tableconverters/volumeclass.go index ae2bd2678..6809eace1 100644 --- a/orictl/table/tableconverters/volume/volumeclass.go +++ b/orictl-volume/tableconverters/volumeclass.go @@ -12,40 +12,39 @@ // See the License for the specific language governing permissions and // limitations under the License. -package volume +package tableconverters import ( ori "github.com/onmetal/onmetal-api/ori/apis/volume/v1alpha1" - "github.com/onmetal/onmetal-api/orictl/table" - "github.com/onmetal/onmetal-api/orictl/table/tableconverter" + "github.com/onmetal/onmetal-api/orictl/api" + "github.com/onmetal/onmetal-api/orictl/tableconverter" ) var ( - volumeClassHeaders = []table.Header{ + volumeClassHeaders = []api.Header{ {Name: "Name"}, {Name: "TPS"}, {Name: "IOPS"}, } ) -var VolumeClass, VolumeClassSlice = tableconverter.ForType[*ori.VolumeClass]( //nolint:revive - func() ([]table.Header, error) { - return volumeClassHeaders, nil - }, - func(class *ori.VolumeClass) ([]table.Row, error) { - return []table.Row{ - { +var ( + VolumeClass = tableconverter.Funcs[*ori.VolumeClass]{ + Headers: tableconverter.Headers(volumeClassHeaders), + Rows: tableconverter.SingleRowFrom(func(class *ori.VolumeClass) (api.Row, error) { + return api.Row{ class.Name, class.Capabilities.Tps, class.Capabilities.Iops, - }, - }, nil - }, + }, nil + }), + } + VolumeClassSlice = tableconverter.SliceFuncs[*ori.VolumeClass](VolumeClass) ) func init() { RegistryBuilder.Register( - tableconverter.ToTaggedAny(VolumeClass), - tableconverter.ToTaggedAny(VolumeClassSlice), + tableconverter.ToTagAndTypedAny[*ori.VolumeClass](VolumeClass), + tableconverter.ToTagAndTypedAny[[]*ori.VolumeClass](VolumeClassSlice), ) } diff --git a/orictl/table/table.go b/orictl/api/table.go similarity index 98% rename from orictl/table/table.go rename to orictl/api/table.go index 1f901d945..9aa032ea2 100644 --- a/orictl/table/table.go +++ b/orictl/api/table.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package table +package api import ( "fmt" diff --git a/orictl/cli/common/common.go b/orictl/cmd/common.go similarity index 99% rename from orictl/cli/common/common.go rename to orictl/cmd/common.go index a8aab80dc..8dd782430 100644 --- a/orictl/cli/common/common.go +++ b/orictl/cmd/common.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package common +package cmd import ( "io" diff --git a/orictl/cmd/orictl-machine/orictlmachine/common/common.go b/orictl/cmd/orictl-machine/orictlmachine/common/common.go deleted file mode 100644 index 2736ba92f..000000000 --- a/orictl/cmd/orictl-machine/orictlmachine/common/common.go +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2022 OnMetal authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package common - -import ( - "fmt" - "time" - - ori "github.com/onmetal/onmetal-api/ori/apis/machine/v1alpha1" - oriremotemachine "github.com/onmetal/onmetal-api/ori/remote/machine" - "github.com/onmetal/onmetal-api/orictl/renderer" - "github.com/onmetal/onmetal-api/orictl/renderers/machine" - "github.com/spf13/pflag" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" -) - -var ( - Renderer = renderer.NewRegistry() -) - -func init() { - if err := machine.AddToRegistry(Renderer); err != nil { - panic(err) - } -} - -type ClientFactory interface { - New() (ori.MachineRuntimeClient, func() error, error) -} - -type ClientOptions struct { - Address string -} - -func (o *ClientOptions) AddFlags(fs *pflag.FlagSet) { - fs.StringVar(&o.Address, "address", "", "Address to the ori server.") -} - -func (o *ClientOptions) New() (ori.MachineRuntimeClient, func() error, error) { - address, err := oriremotemachine.GetAddressWithTimeout(3*time.Second, o.Address) - if err != nil { - return nil, nil, err - } - - conn, err := grpc.Dial(address, grpc.WithTransportCredentials(insecure.NewCredentials())) - if err != nil { - return nil, nil, fmt.Errorf("error dialing: %w", err) - } - - return ori.NewMachineRuntimeClient(conn), conn.Close, nil -} - -type OutputOptions struct { - Output string -} - -func (o *OutputOptions) AddFlags(fs *pflag.FlagSet) { - fs.StringVarP(&o.Output, "output", "o", o.Output, "Output format.") -} - -func (o *OutputOptions) Renderer(ifEmpty string) (renderer.Renderer, error) { - output := o.Output - if output == "" { - output = ifEmpty - } - return Renderer.Get(output) -} - -func (o *OutputOptions) RendererOrNil() (renderer.Renderer, error) { - output := o.Output - if output == "" { - return nil, nil - } - return Renderer.Get(output) -} - -var ( - MachineAliases = []string{"machines", "mach", "machs"} - MachineClassAliases = []string{"machineclasses", "mc", "mcs"} - VolumeAliases = []string{"volumes", "vol", "vols"} - NetworkInterfaceAliases = []string{"networkinterfaces", "nic", "nics"} -) diff --git a/orictl/renderer/table.go b/orictl/renderer/table.go index f0a07fbf6..bafe4794a 100644 --- a/orictl/renderer/table.go +++ b/orictl/renderer/table.go @@ -15,11 +15,12 @@ package renderer import ( + "fmt" "io" - oritable "github.com/onmetal/onmetal-api/orictl/table" - "github.com/onmetal/onmetal-api/orictl/table/tableconverter" - "github.com/onmetal/onmetal-api/orictl/table/tabwriter" + oritable "github.com/onmetal/onmetal-api/orictl/api" + "github.com/onmetal/onmetal-api/orictl/tableconverter" + "github.com/onmetal/onmetal-api/orictl/tabwriter" ) type table struct { @@ -38,6 +39,11 @@ func (t *table) Render(v any, w io.Writer) error { return err } + if tab == nil || len(tab.Headers) == 0 && len(tab.Rows) == 0 { + _, err := fmt.Fprintln(w, "No resources found") + return err + } + oritable.Write(tab, tw) return tw.Flush() } diff --git a/orictl/renderers/machine/register.go b/orictl/renderers/machine/register.go deleted file mode 100644 index b52d796da..000000000 --- a/orictl/renderers/machine/register.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2022 OnMetal authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package machine - -import ( - "github.com/onmetal/onmetal-api/orictl/renderer" - "github.com/onmetal/onmetal-api/orictl/table/tableconverter" - "github.com/onmetal/onmetal-api/orictl/table/tableconverters/machine" -) - -var ( - RegistryBuilder renderer.RegistryBuilder - AddToRegistry = RegistryBuilder.AddToRegistry -) - -func init() { - RegistryBuilder.Add(renderer.AddToRegistry) - RegistryBuilder.Add(func(registry *renderer.Registry) error { - tableConverter := tableconverter.NewRegistry() - if err := machine.AddToRegistry(tableConverter); err != nil { - return err - } - return registry.Register("table", renderer.NewTable(tableConverter)) - }) -} diff --git a/orictl/table/tableconverter/tableconverter.go b/orictl/table/tableconverter/tableconverter.go deleted file mode 100644 index 7260af4b1..000000000 --- a/orictl/table/tableconverter/tableconverter.go +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright 2022 OnMetal authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package tableconverter - -import ( - "fmt" - "reflect" - - "github.com/onmetal/onmetal-api/orictl/table" -) - -type TableConverter[E any] interface { - ConvertToTable(v E) (*table.Table, error) -} - -type TaggedAnyTableConverter interface { - TableConverter[any] - Tag() reflect.Type -} - -type Func[E any] func(e E) (*table.Table, error) - -func (f Func[E]) ConvertToTable(v E) (*table.Table, error) { - return f(v) -} - -func ForType[E any]( - headersFunc func() ([]table.Header, error), - rowsFunc func(e E) ([]table.Row, error), -) (TableConverter[E], TableConverter[[]E]) { - return Func[E](func(e E) (*table.Table, error) { - headers, err := headersFunc() - if err != nil { - return nil, err - } - - rows, err := rowsFunc(e) - if err != nil { - return nil, err - } - - return &table.Table{ - Headers: headers, - Rows: rows, - }, nil - }), Func[[]E](func(es []E) (*table.Table, error) { - headers, err := headersFunc() - if err != nil { - return nil, err - } - - var rows []table.Row - for _, e := range es { - moreRows, err := rowsFunc(e) - if err != nil { - return nil, err - } - - rows = append(rows, moreRows...) - } - return &table.Table{ - Headers: headers, - Rows: rows, - }, nil - }) -} - -type taggedAnyTableConverter struct { - tag reflect.Type - convert func(e any) (*table.Table, error) -} - -func (t *taggedAnyTableConverter) Tag() reflect.Type { - return t.tag -} - -func (t *taggedAnyTableConverter) ConvertToTable(e any) (*table.Table, error) { - actualType := reflect.TypeOf(e) - if actualType != t.tag { - return nil, fmt.Errorf("expected type %s but got %T", t.tag, e) - } - return t.convert(e) -} - -func ToTaggedAny[E any](conv TableConverter[E]) TaggedAnyTableConverter { - var zero E - tag := reflect.TypeOf(zero) - return &taggedAnyTableConverter{ - tag: tag, - convert: func(e any) (*table.Table, error) { - if asE, ok := e.(E); ok { - return conv.ConvertToTable(asE) - } - return nil, fmt.Errorf("cannot convert %T to %T", e, zero) - }, - } -} - -type Registry struct { - convertersByTag map[reflect.Type]TableConverter[any] -} - -func NewRegistry() *Registry { - return &Registry{ - convertersByTag: map[reflect.Type]TableConverter[any]{}, - } -} - -func (r *Registry) ConvertToTable(e any) (*table.Table, error) { - tag := reflect.TypeOf(e) - converter, ok := r.convertersByTag[tag] - if !ok { - return nil, fmt.Errorf("no converter found for type %T", e) - } - return converter.ConvertToTable(e) -} - -func (r *Registry) Register(tag reflect.Type, conv TableConverter[any]) error { - if _, ok := r.convertersByTag[tag]; ok { - return fmt.Errorf("converter for type %s already registered", tag) - } - - r.convertersByTag[tag] = conv - return nil -} - -func RegisterToRegistry[E any](registry *Registry, conv TableConverter[E]) error { - tagged := ToTaggedAny(conv) - return registry.Register(tagged.Tag(), tagged) -} - -type RegistryBuilder []func(*Registry) error - -func (b *RegistryBuilder) RegisterFunc(funcs ...func(*Registry) error) { - *b = append(*b, funcs...) -} - -func (b *RegistryBuilder) Register(taggedConvs ...TaggedAnyTableConverter) { - b.RegisterFunc(func(registry *Registry) error { - for _, taggedConv := range taggedConvs { - if err := registry.Register(taggedConv.Tag(), taggedConv); err != nil { - return err - } - } - return nil - }) -} - -func (b *RegistryBuilder) AddToRegistry(r *Registry) error { - for _, f := range *b { - if err := f(r); err != nil { - return err - } - } - return nil -} diff --git a/orictl/tableconverter/tableconverter.go b/orictl/tableconverter/tableconverter.go new file mode 100644 index 000000000..143ebb494 --- /dev/null +++ b/orictl/tableconverter/tableconverter.go @@ -0,0 +1,272 @@ +// Copyright 2022 OnMetal authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tableconverter + +import ( + "fmt" + "reflect" + + "github.com/onmetal/onmetal-api/orictl/api" + "github.com/onmetal/onmetal-api/utils/generic" +) + +type TableConverter[E any] interface { + ConvertToTable(v E) (*api.Table, error) +} + +type TaggedAnyTableConverter interface { + TableConverter[any] + Tag() reflect.Type +} + +type Func[E any] func(e E) (*api.Table, error) + +func (f Func[E]) ConvertToTable(v E) (*api.Table, error) { + return f(v) +} + +type Funcs[E any] struct { + Headers func() ([]api.Header, error) + Rows func(e E) ([]api.Row, error) +} + +func Headers(headers []api.Header) func() ([]api.Header, error) { + return func() ([]api.Header, error) { + return headers, nil + } +} + +func SingleRowFrom[E any](f func(e E) (api.Row, error)) func(e E) ([]api.Row, error) { + return func(e E) ([]api.Row, error) { + row, err := f(e) + if err != nil { + return nil, err + } + return []api.Row{row}, nil + } +} + +func (f Funcs[E]) ConvertToTable(v E) (*api.Table, error) { + headers, err := f.Headers() + if err != nil { + return nil, err + } + + rows, err := f.Rows(v) + if err != nil { + return nil, err + } + + return &api.Table{ + Headers: headers, + Rows: rows, + }, nil +} + +type SliceFuncs[E any] Funcs[E] + +func (f SliceFuncs[E]) ConvertToTable(es []E) (*api.Table, error) { + headers, err := f.Headers() + if err != nil { + return nil, err + } + + var rows []api.Row + for _, e := range es { + moreRows, err := f.Rows(e) + if err != nil { + return nil, err + } + + rows = append(rows, moreRows...) + } + + return &api.Table{ + Headers: headers, + Rows: rows, + }, nil +} + +func Table[E any](table *api.Table) TableConverter[E] { + return Func[E](func(E) (*api.Table, error) { + return table, nil + }) +} + +func MergeFuncs[E any](funcs ...Funcs[E]) Funcs[E] { + if len(funcs) == 1 { + return funcs[0] + } + + return Funcs[E]{ + Headers: func() ([]api.Header, error) { + var headers []api.Header + for _, f := range funcs { + h, err := f.Headers() + if err != nil { + return nil, err + } + headers = append(headers, h...) + } + return headers, nil + }, + Rows: func(e E) ([]api.Row, error) { + var rows []api.Row + for _, f := range funcs { + r, err := f.Rows(e) + if err != nil { + return nil, err + } + + rows = permuteRows(rows, r) + } + return rows, nil + }, + } +} + +func permuteRows(r1, r2 []api.Row) []api.Row { + if len(r1) == 0 { + return r2 + } + if len(r2) == 0 { + return r1 + } + + perm := make([]api.Row, 0, len(r1)*len(r2)) + for i := 0; i < len(r1); i++ { + for j := 0; j < len(r2); j++ { + perm = append(perm, append(append(make(api.Row, 0, len(r1[i])+len(r2[j])), r1[i]...), r2[j]...)) + } + } + return perm +} + +func Merge[E any](convs ...TableConverter[E]) TableConverter[E] { + if len(convs) == 0 { + return Table[E](nil) + } + if len(convs) == 1 { + return convs[0] + } + + return Func[E](func(e E) (*api.Table, error) { + var ( + headers []api.Header + rows []api.Row + ) + + for _, conv := range convs { + tab, err := conv.ConvertToTable(e) + if err != nil { + return nil, err + } + + if tab == nil { + continue + } + + headers = append(headers, tab.Headers...) + rows = permuteRows(rows, tab.Rows) + } + + return &api.Table{ + Headers: headers, + Rows: rows, + }, nil + }) +} + +type TypedAnyConverter[E any, TC TableConverter[E]] struct { + Converter TC +} + +func (c TypedAnyConverter[E, TC]) ConvertToTable(v any) (*api.Table, error) { + e, err := generic.Cast[E](v) + if err != nil { + return nil, err + } + return c.Converter.ConvertToTable(e) +} + +type Registry struct { + convertersByTag map[reflect.Type]TableConverter[any] +} + +func NewRegistry() *Registry { + return &Registry{ + convertersByTag: map[reflect.Type]TableConverter[any]{}, + } +} + +func (r *Registry) ConvertToTable(e any) (*api.Table, error) { + tag := reflect.TypeOf(e) + converter, ok := r.convertersByTag[tag] + if !ok { + return nil, fmt.Errorf("no converter found for type %T", e) + } + return converter.ConvertToTable(e) +} + +func (r *Registry) Register(tag reflect.Type, conv TableConverter[any]) error { + if _, ok := r.convertersByTag[tag]; ok { + return fmt.Errorf("converter for type %s already registered", tag) + } + + r.convertersByTag[tag] = conv + return nil +} + +func (r *Registry) RegisterTagged(conv TaggedAnyTableConverter) error { + return r.Register(conv.Tag(), conv) +} + +type RegistryBuilder []func(*Registry) error + +func (b *RegistryBuilder) RegisterFunc(funcs ...func(*Registry) error) { + *b = append(*b, funcs...) +} + +type TagAndAnyConverter struct { + Tag reflect.Type + Converter TableConverter[any] +} + +func ToTagAndTypedAny[E any](conv TableConverter[E]) TagAndAnyConverter { + return TagAndAnyConverter{ + Tag: generic.ReflectType[E](), + Converter: TypedAnyConverter[E, TableConverter[E]]{conv}, + } +} + +func (b *RegistryBuilder) Register(taggedConvs ...TagAndAnyConverter) { + b.RegisterFunc(func(registry *Registry) error { + for _, taggedConv := range taggedConvs { + if err := registry.Register(taggedConv.Tag, taggedConv.Converter); err != nil { + return err + } + } + return nil + }) +} + +func (b *RegistryBuilder) AddToRegistry(r *Registry) error { + for _, f := range *b { + if err := f(r); err != nil { + return err + } + } + return nil +} diff --git a/orictl/table/tableconverters/machine/register.go b/orictl/tableconverter/tableconverter_suite_test.go similarity index 70% rename from orictl/table/tableconverters/machine/register.go rename to orictl/tableconverter/tableconverter_suite_test.go index 5e6d51cbf..abb6f584c 100644 --- a/orictl/table/tableconverters/machine/register.go +++ b/orictl/tableconverter/tableconverter_suite_test.go @@ -1,4 +1,4 @@ -// Copyright 2022 OnMetal authors +// Copyright 2023 OnMetal authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,13 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -package machine +package tableconverter_test import ( - "github.com/onmetal/onmetal-api/orictl/table/tableconverter" -) + "testing" -var ( - RegistryBuilder tableconverter.RegistryBuilder - AddToRegistry = RegistryBuilder.AddToRegistry + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" ) + +func TestTableconverter(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Tableconverter Suite") +} diff --git a/orictl/tableconverter/tableconverter_test.go b/orictl/tableconverter/tableconverter_test.go new file mode 100644 index 000000000..eb47d5be8 --- /dev/null +++ b/orictl/tableconverter/tableconverter_test.go @@ -0,0 +1,57 @@ +// Copyright 2023 OnMetal authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tableconverter_test + +import ( + "github.com/onmetal/onmetal-api/orictl/api" + . "github.com/onmetal/onmetal-api/orictl/tableconverter" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +var _ = Describe("Tableconverter", func() { + Describe("Merge", func() { + It("should return the permutation of both table converters", func() { + h1 := []api.Header{{Name: "foo"}} + f1 := Funcs[int]{ + Headers: Headers(h1), + Rows: func(n int) ([]api.Row, error) { + return []api.Row{{n}, {n + 1}}, nil + }, + } + + h2 := []api.Header{{Name: "bar"}} + f2 := Funcs[int]{ + Headers: Headers(h2), + Rows: func(n int) ([]api.Row, error) { + return []api.Row{{n}, {n * n}}, nil + }, + } + + f := Merge[int](f1, f2) + table, err := f.ConvertToTable(2) + Expect(err).NotTo(HaveOccurred()) + Expect(table).To(Equal(&api.Table{ + Headers: []api.Header{{Name: "foo"}, {Name: "bar"}}, + Rows: []api.Row{ + {2, 2}, + {2, 4}, + {3, 2}, + {3, 4}, + }, + })) + }) + }) +}) diff --git a/orictl/tableconverter/utils.go b/orictl/tableconverter/utils.go new file mode 100644 index 000000000..d0f3a44d8 --- /dev/null +++ b/orictl/tableconverter/utils.go @@ -0,0 +1,46 @@ +// Copyright 2023 OnMetal authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tableconverter + +import ( + "sort" + + orimeta "github.com/onmetal/onmetal-api/ori/apis/meta/v1alpha1" + "github.com/onmetal/onmetal-api/orictl/api" +) + +func WellKnownLabels[E orimeta.Object](labels map[string]string) Funcs[E] { + headers := make([]api.Header, 0, len(labels)) + for name := range labels { + headers = append(headers, api.Header{Name: name}) + } + sort.Slice(headers, func(i, j int) bool { + return headers[i].Name < headers[j].Name + }) + + return Funcs[E]{ + Headers: Headers(headers), + Rows: SingleRowFrom(func(e E) (api.Row, error) { + row := make(api.Row, len(headers)) + + objLabels := e.GetMetadata().GetLabels() + for i := range headers { + row[i] = objLabels[labels[headers[i].Name]] + } + + return row, nil + }), + } +} diff --git a/orictl/table/tabwriter/tabwriter.go b/orictl/tabwriter/tabwriter.go similarity index 100% rename from orictl/table/tabwriter/tabwriter.go rename to orictl/tabwriter/tabwriter.go diff --git a/utils/generic/generic.go b/utils/generic/generic.go index 1e2d9fec8..b86fcb4aa 100644 --- a/utils/generic/generic.go +++ b/utils/generic/generic.go @@ -14,6 +14,11 @@ package generic +import ( + "fmt" + "reflect" +) + // Identity is a function that returns its given parameters. func Identity[E any](e E) E { return e @@ -25,6 +30,19 @@ func Zero[E any]() E { return zero } +func Cast[E any](v any) (E, error) { + e, ok := v.(E) + if !ok { + return Zero[E](), fmt.Errorf("expected %T but got %T", e, v) + } + return e, nil +} + +func ReflectType[E any]() reflect.Type { + var ePtr *E // use a pointer to avoid initializing the entire type + return reflect.TypeOf(ePtr).Elem() +} + // Pointer returns a pointer for the given value. func Pointer[E any](e E) *E { return &e @@ -44,3 +62,10 @@ func Deref[E any](e *E, defaultValue E) E { return defaultValue }) } + +func PipeMap[E any](e E, fs ...func(E) E) E { + for _, f := range fs { + e = f(e) + } + return e +}