eksctl-io/eksctl

[Feature] Document Calling EKSCtl Cobra subcommands from Go

whatnick opened this issue · 2 comments

What feature/behavior/change do you want?

Clearly document imports and code required to call eksctl cobra command / sub-command from another go project as noted in #813.

Particularly:

  • func createClusterCmd(cmd *cmdutils.Cmd)
  • func deleteClusterCmd(cmd *cmdutils.Cmd)

Why do you want this feature?

Some projects would benefit from reusing eksctl in their CI to create and delete ephemeral clusters to test various AWS integrations, particularly CNI as shown here : microsoft/retina#667 , however linting rules do not allow Execing eksctl, being able to add the Cobra commands to a new rootCmd and Run / RunE those via the AWS Go SDK v2 will be useful in reusing the code here in those tests.

Hello whatnick 👋 Thank you for opening an issue in eksctl project. The team will review the issue and aim to respond within 1-5 business days. Meanwhile, please read about the Contribution and Code of Conduct guidelines here. You can find out more information about eksctl on our website

Filching parts of the code in the cmd section of eksctl allows you to embed it in other tooling that needs to create and tear down clusters without execing eksctl

go get github.com/weaveworks/eksctl/pkg/ctl/cmdutils
go get github.com/weaveworks/eksctl/pkg/ctl/create

Not all of it is necessary e.g. the logging etc. so can be more compact. Closing this and keeping it here as docs for anyone else looking to embed eksctl as a package in the future.

package aws

import (
	"bytes"
	"context"
	"fmt"
	"log"

	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/kris-nova/logger"
	"github.com/spf13/cobra"
	"github.com/weaveworks/eksctl/pkg/ctl/cmdutils"
	"github.com/weaveworks/eksctl/pkg/ctl/create"
)

type CreateCluster struct {
	AccountID          string
	Region             string
	ClusterName        string
	KubeConfigFilePath string
}

func (c *CreateCluster) Run() error {

	// Initialize AWS session
	_, err := config.LoadDefaultConfig(context.TODO(),
		config.WithRegion(c.Region),
	)
	if err != nil {
		return fmt.Errorf("unable to load SDK config, %v", err)
	}

	// Create the ekctl root cmd to execute
	rootCmd := &cobra.Command{
		Use:   "eksctl [command]",
		Short: "The official CLI for Amazon EKS",
		Run: func(c *cobra.Command, _ []string) {
			if err := c.Help(); err != nil {
				logger.Debug("ignoring cobra error %q", err.Error())
			}
		},
		SilenceUsage: true,
	}

	loggerLevel := rootCmd.PersistentFlags().IntP("verbose", "v", 3, "set log level, use 0 to silence, 4 for debugging and 5 for debugging with AWS debug logging")
	colorValue := rootCmd.PersistentFlags().StringP("color", "C", "true", "toggle colorized logs (valid options: true, false, fabulous)")
	dumpLogsValue := rootCmd.PersistentFlags().BoolP("dumpLogs", "d", false, "dump logs to disk on failure if set to true")

	logBuffer := new(bytes.Buffer)

	cobra.OnInitialize(func() {
		initLogger(*loggerLevel, *colorValue, logBuffer, *dumpLogsValue)
	})

	flagGrouping := cmdutils.NewGrouping()
	createCmd := create.Command(flagGrouping)
	rootCmd.AddCommand(createCmd)

	checkCommand(rootCmd)

	createArgs := []string{
		"create",
		"cluster",
		"--kubeconfig",
		c.KubeConfigFilePath,
		"-n",
		c.ClusterName,
		"--region",
		c.Region,
		"--managed",
	}

	rootCmd.SetArgs(createArgs)
	err = rootCmd.Execute()

	if err != nil {
		return fmt.Errorf("eksctl failed with %s", err)
	}

	log.Printf("Cluster created successfully!")
	return nil
}