mirror of
https://github.com/rancher/k3k.git
synced 2026-08-19 04:16:16 +00:00
Added k3kcli cluster list and k3kcli policy list commands (#368)
* list commands * go mod tidy * moved logic to separate file, small refactor
This commit is contained in:
@@ -14,7 +14,11 @@ spec:
|
||||
singular: cluster
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
- additionalPrinterColumns:
|
||||
- jsonPath: .spec.mode
|
||||
name: Mode
|
||||
type: string
|
||||
name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: |-
|
||||
|
||||
@@ -20,9 +20,6 @@ spec:
|
||||
- jsonPath: .spec.allowedMode
|
||||
name: Mode
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: Age
|
||||
type: date
|
||||
name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
|
||||
@@ -11,6 +11,7 @@ func NewClusterCmd(appCtx *AppContext) *cli.Command {
|
||||
Subcommands: []*cli.Command{
|
||||
NewClusterCreateCmd(appCtx),
|
||||
NewClusterDeleteCmd(appCtx),
|
||||
NewClusterListCmd(appCtx),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package cmds
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/rancher/k3k/pkg/apis/k3k.io/v1alpha1"
|
||||
"github.com/urfave/cli/v2"
|
||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/cli-runtime/pkg/printers"
|
||||
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
func NewClusterListCmd(appCtx *AppContext) *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "list",
|
||||
Usage: "List all the existing cluster",
|
||||
UsageText: "k3kcli cluster list [command options]",
|
||||
Action: list(appCtx),
|
||||
Flags: WithCommonFlags(appCtx),
|
||||
HideHelpCommand: true,
|
||||
}
|
||||
}
|
||||
|
||||
func list(appCtx *AppContext) cli.ActionFunc {
|
||||
return func(clx *cli.Context) error {
|
||||
ctx := context.Background()
|
||||
client := appCtx.Client
|
||||
|
||||
if clx.NArg() > 0 {
|
||||
return cli.ShowSubcommandHelp(clx)
|
||||
}
|
||||
|
||||
var clusters v1alpha1.ClusterList
|
||||
if err := client.List(ctx, &clusters, ctrlclient.InNamespace(appCtx.namespace)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
crd := &apiextensionsv1.CustomResourceDefinition{}
|
||||
if err := client.Get(ctx, types.NamespacedName{Name: "clusters.k3k.io"}, crd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
items := toPointerSlice(clusters.Items)
|
||||
table := createTable(crd, items)
|
||||
|
||||
printer := printers.NewTablePrinter(printers.PrintOptions{WithNamespace: true})
|
||||
|
||||
return printer.PrintObj(table, clx.App.Writer)
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ func NewPolicyCmd(appCtx *AppContext) *cli.Command {
|
||||
Subcommands: []*cli.Command{
|
||||
NewPolicyCreateCmd(appCtx),
|
||||
NewPolicyDeleteCmd(appCtx),
|
||||
NewPolicyListCmd(appCtx),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package cmds
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/rancher/k3k/pkg/apis/k3k.io/v1alpha1"
|
||||
"github.com/urfave/cli/v2"
|
||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/cli-runtime/pkg/printers"
|
||||
)
|
||||
|
||||
func NewPolicyListCmd(appCtx *AppContext) *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "list",
|
||||
Usage: "List all the existing policies",
|
||||
UsageText: "k3kcli policy list [command options]",
|
||||
Action: policyList(appCtx),
|
||||
Flags: WithCommonFlags(appCtx),
|
||||
HideHelpCommand: true,
|
||||
}
|
||||
}
|
||||
|
||||
func policyList(appCtx *AppContext) cli.ActionFunc {
|
||||
return func(clx *cli.Context) error {
|
||||
ctx := context.Background()
|
||||
client := appCtx.Client
|
||||
|
||||
if clx.NArg() > 0 {
|
||||
return cli.ShowSubcommandHelp(clx)
|
||||
}
|
||||
|
||||
var policies v1alpha1.VirtualClusterPolicyList
|
||||
if err := client.List(ctx, &policies); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
crd := &apiextensionsv1.CustomResourceDefinition{}
|
||||
if err := client.Get(ctx, types.NamespacedName{Name: "virtualclusterpolicies.k3k.io"}, crd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
items := toPointerSlice(policies.Items)
|
||||
table := createTable(crd, items)
|
||||
|
||||
printer := printers.NewTablePrinter(printers.PrintOptions{})
|
||||
|
||||
return printer.PrintObj(table, clx.App.Writer)
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/rancher/k3k/pkg/buildinfo"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli/v2"
|
||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
"k8s.io/client-go/rest"
|
||||
@@ -45,6 +46,7 @@ func NewApp() *cli.App {
|
||||
scheme := runtime.NewScheme()
|
||||
_ = clientgoscheme.AddToScheme(scheme)
|
||||
_ = v1alpha1.AddToScheme(scheme)
|
||||
_ = apiextensionsv1.AddToScheme(scheme)
|
||||
|
||||
ctrlClient, err := client.New(restConfig, client.Options{Scheme: scheme})
|
||||
if err != nil {
|
||||
@@ -109,6 +111,7 @@ func WithCommonFlags(appCtx *AppContext, flags ...cli.Flag) []cli.Flag {
|
||||
&cli.StringFlag{
|
||||
Name: "namespace",
|
||||
Usage: "namespace to create the k3k cluster in",
|
||||
Aliases: []string{"n"},
|
||||
Destination: &appCtx.namespace,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
package cmds
|
||||
|
||||
import (
|
||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/util/jsonpath"
|
||||
)
|
||||
|
||||
// createTable creates a table to print from the printerColumn defined in the CRD spec, plus the name at the beginning
|
||||
func createTable[T runtime.Object](crd *apiextensionsv1.CustomResourceDefinition, objs []T) *metav1.Table {
|
||||
printerColumns := getPrinterColumnsFromCRD(crd)
|
||||
|
||||
return &metav1.Table{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: "meta.k8s.io/v1", Kind: "Table"},
|
||||
ColumnDefinitions: convertToTableColumns(printerColumns),
|
||||
Rows: createTableRows(objs, printerColumns),
|
||||
}
|
||||
}
|
||||
|
||||
func getPrinterColumnsFromCRD(crd *apiextensionsv1.CustomResourceDefinition) []apiextensionsv1.CustomResourceColumnDefinition {
|
||||
printerColumns := []apiextensionsv1.CustomResourceColumnDefinition{
|
||||
{Name: "Name", Type: "string", Format: "name", Description: "Name of the Resource", JSONPath: ".metadata.name"},
|
||||
}
|
||||
|
||||
for _, version := range crd.Spec.Versions {
|
||||
if version.Name == "v1alpha1" {
|
||||
printerColumns = append(printerColumns, version.AdditionalPrinterColumns...)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return printerColumns
|
||||
}
|
||||
|
||||
func convertToTableColumns(printerColumns []apiextensionsv1.CustomResourceColumnDefinition) []metav1.TableColumnDefinition {
|
||||
var columnDefinitions []metav1.TableColumnDefinition
|
||||
|
||||
for _, col := range printerColumns {
|
||||
columnDefinitions = append(columnDefinitions, metav1.TableColumnDefinition{
|
||||
Name: col.Name,
|
||||
Type: col.Type,
|
||||
Format: col.Format,
|
||||
Description: col.Description,
|
||||
Priority: col.Priority,
|
||||
})
|
||||
}
|
||||
|
||||
return columnDefinitions
|
||||
}
|
||||
|
||||
func createTableRows[T runtime.Object](objs []T, printerColumns []apiextensionsv1.CustomResourceColumnDefinition) []metav1.TableRow {
|
||||
var rows []metav1.TableRow
|
||||
|
||||
for _, obj := range objs {
|
||||
objMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&obj)
|
||||
if err != nil {
|
||||
rows = append(rows, metav1.TableRow{Cells: []any{"<error: " + err.Error() + ">"}})
|
||||
continue
|
||||
}
|
||||
|
||||
rows = append(rows, metav1.TableRow{
|
||||
Cells: buildRowCells(objMap, printerColumns),
|
||||
Object: runtime.RawExtension{Object: obj},
|
||||
})
|
||||
}
|
||||
|
||||
return rows
|
||||
}
|
||||
|
||||
func buildRowCells(objMap map[string]any, printerColumns []apiextensionsv1.CustomResourceColumnDefinition) []any {
|
||||
var cells []any
|
||||
|
||||
for _, printCol := range printerColumns {
|
||||
j := jsonpath.New(printCol.Name)
|
||||
|
||||
err := j.Parse("{" + printCol.JSONPath + "}")
|
||||
if err != nil {
|
||||
cells = append(cells, "<error>")
|
||||
continue
|
||||
}
|
||||
|
||||
results, err := j.FindResults(objMap)
|
||||
if err != nil || len(results) == 0 || len(results[0]) == 0 {
|
||||
cells = append(cells, "<none>")
|
||||
continue
|
||||
}
|
||||
|
||||
cells = append(cells, results[0][0].Interface())
|
||||
}
|
||||
|
||||
return cells
|
||||
}
|
||||
|
||||
func toPointerSlice[T any](v []T) []*T {
|
||||
var vPtr = make([]*T, len(v))
|
||||
|
||||
for i := range v {
|
||||
vPtr[i] = &v[i]
|
||||
}
|
||||
|
||||
return vPtr
|
||||
}
|
||||
+31
-7
@@ -9,7 +9,7 @@ k3kcli
|
||||
```
|
||||
[--debug]
|
||||
[--kubeconfig]=[value]
|
||||
[--namespace]=[value]
|
||||
[--namespace|-n]=[value]
|
||||
```
|
||||
|
||||
**Usage**:
|
||||
@@ -24,7 +24,7 @@ k3kcli [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...]
|
||||
|
||||
**--kubeconfig**="": kubeconfig path (default: $HOME/.kube/config or $KUBECONFIG if set)
|
||||
|
||||
**--namespace**="": namespace to create the k3k cluster in
|
||||
**--namespace, -n**="": namespace to create the k3k cluster in
|
||||
|
||||
|
||||
# COMMANDS
|
||||
@@ -55,7 +55,7 @@ Create new cluster
|
||||
|
||||
**--mode**="": k3k mode type (shared, virtual) (default: "shared")
|
||||
|
||||
**--namespace**="": namespace to create the k3k cluster in
|
||||
**--namespace, -n**="": namespace to create the k3k cluster in
|
||||
|
||||
**--persistence-type**="": persistence mode for the nodes (dynamic, ephemeral, static) (default: "dynamic")
|
||||
|
||||
@@ -87,7 +87,19 @@ Delete an existing cluster
|
||||
|
||||
**--kubeconfig**="": kubeconfig path (default: $HOME/.kube/config or $KUBECONFIG if set)
|
||||
|
||||
**--namespace**="": namespace to create the k3k cluster in
|
||||
**--namespace, -n**="": namespace to create the k3k cluster in
|
||||
|
||||
### list
|
||||
|
||||
List all the existing cluster
|
||||
|
||||
>k3kcli cluster list [command options]
|
||||
|
||||
**--debug**: Turn on debug logs
|
||||
|
||||
**--kubeconfig**="": kubeconfig path (default: $HOME/.kube/config or $KUBECONFIG if set)
|
||||
|
||||
**--namespace, -n**="": namespace to create the k3k cluster in
|
||||
|
||||
## policy
|
||||
|
||||
@@ -105,7 +117,7 @@ Create new policy
|
||||
|
||||
**--mode**="": The allowed mode type of the policy (default: "shared")
|
||||
|
||||
**--namespace**="": namespace to create the k3k cluster in
|
||||
**--namespace, -n**="": namespace to create the k3k cluster in
|
||||
|
||||
### delete
|
||||
|
||||
@@ -117,7 +129,19 @@ Delete an existing policy
|
||||
|
||||
**--kubeconfig**="": kubeconfig path (default: $HOME/.kube/config or $KUBECONFIG if set)
|
||||
|
||||
**--namespace**="": namespace to create the k3k cluster in
|
||||
**--namespace, -n**="": namespace to create the k3k cluster in
|
||||
|
||||
### list
|
||||
|
||||
List all the existing policies
|
||||
|
||||
>k3kcli policy list [command options]
|
||||
|
||||
**--debug**: Turn on debug logs
|
||||
|
||||
**--kubeconfig**="": kubeconfig path (default: $HOME/.kube/config or $KUBECONFIG if set)
|
||||
|
||||
**--namespace, -n**="": namespace to create the k3k cluster in
|
||||
|
||||
## kubeconfig
|
||||
|
||||
@@ -143,6 +167,6 @@ Generate kubeconfig for clusters
|
||||
|
||||
**--name**="": cluster name
|
||||
|
||||
**--namespace**="": namespace to create the k3k cluster in
|
||||
**--namespace, -n**="": namespace to create the k3k cluster in
|
||||
|
||||
**--org**="": Organization name (ORG) of the generated certificates for the kubeconfig
|
||||
|
||||
@@ -28,8 +28,10 @@ require (
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
helm.sh/helm/v3 v3.14.4
|
||||
k8s.io/api v0.29.11
|
||||
k8s.io/apiextensions-apiserver v0.29.11
|
||||
k8s.io/apimachinery v0.29.11
|
||||
k8s.io/apiserver v0.29.11
|
||||
k8s.io/cli-runtime v0.29.11
|
||||
k8s.io/client-go v0.29.11
|
||||
k8s.io/component-base v0.29.11
|
||||
k8s.io/component-helpers v0.29.11
|
||||
@@ -203,8 +205,6 @@ require (
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.29.11 // indirect
|
||||
k8s.io/cli-runtime v0.29.11 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
k8s.io/kms v0.29.11 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
// +kubebuilder:object:root=true
|
||||
// +kubebuilder:storageversion
|
||||
// +kubebuilder:subresource:status
|
||||
// +kubebuilder:printcolumn:JSONPath=".spec.mode",name=Mode,type=string
|
||||
|
||||
// Cluster defines a virtual Kubernetes cluster managed by k3k.
|
||||
// It specifies the desired state of a virtual cluster, including version, node configuration, and networking.
|
||||
@@ -334,7 +335,6 @@ type ClusterList struct {
|
||||
// +kubebuilder:subresource:status
|
||||
// +kubebuilder:object:root=true
|
||||
// +kubebuilder:printcolumn:JSONPath=".spec.allowedMode",name=Mode,type=string
|
||||
// +kubebuilder:printcolumn:JSONPath=".metadata.creationTimestamp",name=Age,type=date
|
||||
// +kubebuilder:resource:scope=Cluster,shortName=vcp
|
||||
|
||||
// VirtualClusterPolicy allows defining common configurations and constraints
|
||||
|
||||
Reference in New Issue
Block a user