Flatten the cli structure, add docs generation in the Makefile and remove crds/Makefile

This commit is contained in:
jpgouin
2025-03-03 13:21:07 +00:00
parent 5e8bc0d3cd
commit 4ca5203df1
11 changed files with 186 additions and 80 deletions
+5 -2
View File
@@ -9,10 +9,12 @@ CONTROLLER_TOOLS_VERSION ?= v0.14.0
GINKGO_VERSION ?= v2.21.0
ENVTEST_VERSION ?= latest
ENVTEST_K8S_VERSION := 1.31.0
CRD_REF_DOCS_VER ?= v0.1.0
GOLANGCI_LINT ?= go run github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION)
CONTROLLER_GEN ?= go run sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION)
GINKGO ?= go run github.com/onsi/ginkgo/v2/ginkgo@$(GINKGO_VERSION)
CRD_REF_DOCS := go run github.com/elastic/crd-ref-docs@$(CRD_REF_DOCS_VER)
ENVTEST ?= go run sigs.k8s.io/controller-runtime/tools/setup-envtest@$(ENVTEST_VERSION)
ENVTEST_DIR ?= $(shell pwd)/.envtest
@@ -75,8 +77,9 @@ build-crds: ## Build the CRDs specs
output:crd:dir=./charts/k3k/crds
.PHONY: docs
docs: ## Build the CRDs docs
$(MAKE) -C docs/crds
docs: ## Build the CRDs and CLI docs
$(CRD_REF_DOCS) --config=./docs/crds/config.yaml --renderer=markdown --source-path=./pkg/apis/k3k.io/v1alpha1 --output-path=./docs/crds/crd-docs.md
@go run ./docs/cli/genclidoc.go
.PHONY: lint
lint: ## Find any linting issues in the project
@@ -1,16 +1,16 @@
package cluster
package cmds
import (
"github.com/urfave/cli/v2"
)
func NewCommand() *cli.Command {
func NewClusterCommand() *cli.Command {
return &cli.Command{
Name: "cluster",
Usage: "cluster command",
Subcommands: []*cli.Command{
NewCreateCmd(),
NewDeleteCmd(),
NewClusterCreateCmd(),
NewClusterDeleteCmd(),
},
}
}
@@ -1,4 +1,4 @@
package cluster
package cmds
import (
"context"
@@ -9,7 +9,6 @@ import (
"strings"
"time"
"github.com/rancher/k3k/cli/cmds"
"github.com/rancher/k3k/pkg/apis/k3k.io/v1alpha1"
k3kcluster "github.com/rancher/k3k/pkg/controller/cluster"
"github.com/rancher/k3k/pkg/controller/kubeconfig"
@@ -18,9 +17,7 @@ import (
v1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
"k8s.io/client-go/util/retry"
@@ -28,13 +25,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
)
var Scheme = runtime.NewScheme()
func init() {
_ = clientgoscheme.AddToScheme(Scheme)
_ = v1alpha1.AddToScheme(Scheme)
}
type CreateConfig struct {
token string
clusterCIDR string
@@ -50,7 +40,7 @@ type CreateConfig struct {
kubeconfigServerHost string
}
func NewCreateCmd() *cli.Command {
func NewClusterCreateCmd() *cli.Command {
createConfig := &CreateConfig{}
createFlags := NewCreateFlags(createConfig)
@@ -59,7 +49,7 @@ func NewCreateCmd() *cli.Command {
Usage: "Create new cluster",
UsageText: "k3kcli cluster create [command options] NAME",
Action: createAction(createConfig),
Flags: append(cmds.CommonFlags, createFlags...),
Flags: append(CommonFlags, createFlags...),
HideHelpCommand: true,
}
}
@@ -77,7 +67,7 @@ func createAction(config *CreateConfig) cli.ActionFunc {
return errors.New("invalid cluster name")
}
restConfig, err := clientcmd.BuildConfigFromFlags("", cmds.Kubeconfig)
restConfig, err := clientcmd.BuildConfigFromFlags("", Kubeconfig)
if err != nil {
return err
}
@@ -97,8 +87,7 @@ func createAction(config *CreateConfig) cli.ActionFunc {
if config.token != "" {
logrus.Infof("Creating cluster token secret")
obj := k3kcluster.TokenSecretObj(config.token, name, cmds.Namespace())
obj := k3kcluster.TokenSecretObj(config.token, name, Namespace())
if err := ctrlClient.Create(ctx, &obj); err != nil {
return err
}
@@ -106,7 +95,7 @@ func createAction(config *CreateConfig) cli.ActionFunc {
logrus.Infof("Creating a new cluster [%s]", name)
cluster := newCluster(name, cmds.Namespace(), config)
cluster := newCluster(name, Namespace(), config)
cluster.Spec.Expose = &v1alpha1.ExposeConfig{
NodePort: &v1alpha1.NodePortConfig{},
@@ -117,12 +106,10 @@ func createAction(config *CreateConfig) cli.ActionFunc {
if err != nil {
return err
}
host := strings.Split(url.Host, ":")
if config.kubeconfigServerHost != "" {
host = []string{config.kubeconfigServerHost}
}
cluster.Spec.TLSSANs = []string{host[0]}
if err := ctrlClient.Create(ctx, cluster); err != nil {
@@ -147,7 +134,6 @@ func createAction(config *CreateConfig) cli.ActionFunc {
cfg := kubeconfig.New()
var kubeconfig *clientcmdapi.Config
if err := retry.OnError(availableBackoff, apierrors.IsNotFound, func() error {
kubeconfig, err = cfg.Extract(ctx, ctrlClient, cluster, host[0])
return err
@@ -203,7 +189,6 @@ func newCluster(name, namespace string, config *CreateConfig) *v1alpha1.Cluster
if config.storageClassName == "" {
cluster.Spec.Persistence.StorageClassName = nil
}
if config.token != "" {
cluster.Spec.TokenSecretRef = &v1.SecretReference{
Name: k3kcluster.TokenSecretName(name),
@@ -1,4 +1,4 @@
package cluster
package cmds
import (
"errors"
@@ -1,10 +1,9 @@
package cluster
package cmds
import (
"context"
"errors"
"github.com/rancher/k3k/cli/cmds"
"github.com/rancher/k3k/pkg/apis/k3k.io/v1alpha1"
k3kcluster "github.com/rancher/k3k/pkg/controller/cluster"
"github.com/sirupsen/logrus"
@@ -14,13 +13,13 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
)
func NewDeleteCmd() *cli.Command {
func NewClusterDeleteCmd() *cli.Command {
return &cli.Command{
Name: "delete",
Usage: "Delete an existing cluster",
UsageText: "k3kcli cluster delete [command options] NAME",
Action: delete,
Flags: cmds.CommonFlags,
Flags: CommonFlags,
HideHelpCommand: true,
}
}
@@ -37,7 +36,7 @@ func delete(clx *cli.Context) error {
return errors.New("invalid cluster name")
}
restConfig, err := clientcmd.BuildConfigFromFlags("", cmds.Kubeconfig)
restConfig, err := clientcmd.BuildConfigFromFlags("", Kubeconfig)
if err != nil {
return err
}
@@ -54,9 +53,8 @@ func delete(clx *cli.Context) error {
cluster := v1alpha1.Cluster{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: cmds.Namespace(),
Namespace: Namespace(),
},
}
return ctrlClient.Delete(ctx, &cluster)
}
@@ -1,4 +1,4 @@
package kubeconfig
package cmds
import (
"context"
@@ -8,7 +8,6 @@ import (
"strings"
"time"
"github.com/rancher/k3k/cli/cmds"
"github.com/rancher/k3k/pkg/apis/k3k.io/v1alpha1"
"github.com/rancher/k3k/pkg/controller"
"github.com/rancher/k3k/pkg/controller/certs"
@@ -16,23 +15,15 @@ import (
"github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apiserver/pkg/authentication/user"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
"k8s.io/client-go/util/retry"
"sigs.k8s.io/controller-runtime/pkg/client"
)
func init() {
_ = clientgoscheme.AddToScheme(Scheme)
_ = v1alpha1.AddToScheme(Scheme)
}
var (
Scheme = runtime.NewScheme()
name string
cn string
org cli.StringSlice
@@ -88,11 +79,11 @@ var subcommands = []*cli.Command{
Usage: "Generate kubeconfig for clusters",
SkipFlagParsing: false,
Action: generate,
Flags: append(cmds.CommonFlags, generateKubeconfigFlags...),
Flags: append(CommonFlags, generateKubeconfigFlags...),
},
}
func NewCommand() *cli.Command {
func NewKubeconfigCommand() *cli.Command {
return &cli.Command{
Name: "kubeconfig",
Usage: "Manage kubeconfig for clusters",
@@ -102,10 +93,9 @@ func NewCommand() *cli.Command {
func generate(clx *cli.Context) error {
var cluster v1alpha1.Cluster
ctx := context.Background()
restConfig, err := clientcmd.BuildConfigFromFlags("", cmds.Kubeconfig)
restConfig, err := clientcmd.BuildConfigFromFlags("", Kubeconfig)
if err != nil {
return err
}
@@ -116,10 +106,9 @@ func generate(clx *cli.Context) error {
if err != nil {
return err
}
clusterKey := types.NamespacedName{
Name: name,
Namespace: cmds.Namespace(),
Namespace: Namespace(),
}
if err := ctrlClient.Get(ctx, clusterKey, &cluster); err != nil {
@@ -130,11 +119,9 @@ func generate(clx *cli.Context) error {
if err != nil {
return err
}
host := strings.Split(url.Host, ":")
if kubeconfigServerHost != "" {
host = []string{kubeconfigServerHost}
if err := altNames.Set(kubeconfigServerHost); err != nil {
return err
}
@@ -157,7 +144,6 @@ func generate(clx *cli.Context) error {
logrus.Infof("waiting for cluster to be available..")
var kubeconfig *clientcmdapi.Config
if err := retry.OnError(controller.Backoff, apierrors.IsNotFound, func() error {
kubeconfig, err = cfg.Extract(ctx, ctrlClient, &cluster, host[0])
return err
+26 -5
View File
@@ -1,10 +1,15 @@
package cmds
import (
"fmt"
"os"
"github.com/rancher/k3k/pkg/apis/k3k.io/v1alpha1"
"github.com/rancher/k3k/pkg/buildinfo"
"github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
)
const (
@@ -12,9 +17,12 @@ const (
)
var (
debug bool
Kubeconfig string
namespace string
Scheme = runtime.NewScheme()
debug bool
Kubeconfig string
namespace string
CommonFlags = []cli.Flag{
&cli.StringFlag{
Name: "kubeconfig",
@@ -31,6 +39,11 @@ var (
}
)
func init() {
_ = clientgoscheme.AddToScheme(Scheme)
_ = v1alpha1.AddToScheme(Scheme)
}
func NewApp() *cli.App {
app := cli.NewApp()
app.Name = "k3kcli"
@@ -48,10 +61,19 @@ func NewApp() *cli.App {
if debug {
logrus.SetLevel(logrus.DebugLevel)
}
return nil
}
app.Version = buildinfo.Version
cli.VersionPrinter = func(cCtx *cli.Context) {
fmt.Println("k3kcli Version: " + buildinfo.Version)
}
app.Commands = []*cli.Command{
NewClusterCommand(),
NewKubeconfigCommand(),
}
return app
}
@@ -59,6 +81,5 @@ func Namespace() string {
if namespace == "" {
return defaultNamespace
}
return namespace
}
-15
View File
@@ -1,29 +1,14 @@
package main
import (
"fmt"
"os"
"github.com/rancher/k3k/cli/cmds"
"github.com/rancher/k3k/cli/cmds/cluster"
"github.com/rancher/k3k/cli/cmds/kubeconfig"
"github.com/rancher/k3k/pkg/buildinfo"
"github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
)
func main() {
app := cmds.NewApp()
app.Version = buildinfo.Version
cli.VersionPrinter = func(cCtx *cli.Context) {
fmt.Println("k3kcli Version: " + buildinfo.Version)
}
app.Commands = []*cli.Command{
cluster.NewCommand(),
kubeconfig.NewCommand(),
}
if err := app.Run(os.Args); err != nil {
logrus.Fatal(err)
}
+98
View File
@@ -0,0 +1,98 @@
# NAME
k3kcli - CLI for K3K
# SYNOPSIS
k3kcli
```
[--debug]
```
**Usage**:
```
k3kcli [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...]
```
# GLOBAL OPTIONS
**--debug**: Turn on debug logs
# COMMANDS
## cluster
cluster command
### create
Create new cluster
>k3kcli cluster create [command options] NAME
**--agent-args**="": agents extra arguments
**--agents**="": number of agents (default: 0)
**--cluster-cidr**="": cluster CIDR
**--kubeconfig**="": kubeconfig path (default: "/home/jpgouin/.kube/config")
**--kubeconfig-server**="": override the kubeconfig server host
**--mode**="": k3k mode type (shared, virtual) (default: "shared")
**--namespace**="": namespace to create the k3k cluster in
**--persistence-type**="": persistence mode for the nodes (ephemeral, static, dynamic) (default: "dynamic")
**--server-args**="": servers extra arguments
**--servers**="": number of servers (default: 1)
**--service-cidr**="": service CIDR
**--storage-class-name**="": storage class name for dynamic persistence type
**--token**="": token of the cluster
**--version**="": k3s version
### delete
Delete an existing cluster
>k3kcli cluster delete [command options] NAME
**--kubeconfig**="": kubeconfig path (default: "/home/jpgouin/.kube/config")
**--namespace**="": namespace to create the k3k cluster in
## kubeconfig
Manage kubeconfig for clusters
### generate
Generate kubeconfig for clusters
**--altNames**="": altNames of the generated certificates for the kubeconfig
**--cn**="": Common name (CN) of the generated certificates for the kubeconfig (default: "system:admin")
**--config-name**="": the name of the generated kubeconfig file
**--expiration-days**="": Expiration date of the certificates used for the kubeconfig (default: 356)
**--kubeconfig**="": kubeconfig path (default: "/home/jpgouin/.kube/config")
**--kubeconfig-server**="": override the kubeconfig server host
**--name**="": cluster name
**--namespace**="": namespace to create the k3k cluster in
**--org**="": Organization name (ORG) of the generated certificates for the kubeconfig
+36
View File
@@ -0,0 +1,36 @@
package main
import (
"fmt"
"os"
"path"
"github.com/rancher/k3k/cli/cmds"
)
func main() {
// Instantiate the CLI application
app := cmds.NewApp()
// Generate the Markdown documentation
md, err := app.ToMarkdown()
if err != nil {
fmt.Println("Error generating documentation:", err)
os.Exit(1)
}
wd, err := os.Getwd()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
outputFile := path.Join(wd, "docs/cli/cli-docs.md")
err = os.WriteFile(outputFile, []byte(md), 0644)
if err != nil {
fmt.Println("Error generating documentation:", err)
os.Exit(1)
}
fmt.Println("Documentation generated at " + outputFile)
}
-6
View File
@@ -1,6 +0,0 @@
CRD_REF_DOCS_VER := v0.1.0
CRD_REF_DOCS := go run github.com/elastic/crd-ref-docs@$(CRD_REF_DOCS_VER)
.PHONY: generate
generate:
$(CRD_REF_DOCS) --config=config.yaml --renderer=markdown --source-path=../../pkg/apis/k3k.io/v1alpha1 --output-path=crd-docs.md