Skip to content

Commit

Permalink
feat: add k3s cmd
Browse files Browse the repository at this point in the history
Signed-off-by: DrummyFloyd <[email protected]>
  • Loading branch information
DrummyFloyd committed Mar 11, 2024
1 parent 9563f05 commit 5c7f74c
Show file tree
Hide file tree
Showing 7 changed files with 314 additions and 2 deletions.
2 changes: 2 additions & 0 deletions cmd/beta.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"fmt"

"github.com/kubefirst/kubefirst/cmd/google"
"github.com/kubefirst/kubefirst/cmd/k3s"
"github.com/kubefirst/kubefirst/cmd/vultr"
"github.com/kubefirst/kubefirst/internal/progress"
"github.com/spf13/cobra"
Expand All @@ -33,6 +34,7 @@ var betaCmd = &cobra.Command{
func init() {
cobra.OnInitialize()
betaCmd.AddCommand(
k3s.NewCommand(),
google.NewCommand(),
vultr.NewCommand(),
)
Expand Down
134 changes: 134 additions & 0 deletions cmd/k3s/command.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
Copyright (C) 2021-2023, Kubefirst
This program is licensed under MIT.
See the LICENSE file for more details.
*/
package k3s

import (
"fmt"

"github.com/kubefirst/kubefirst/internal/common"
"github.com/spf13/cobra"
)

var (
// Create
// TODO: add ssh key flag to connect on k3s targets
alertsEmailFlag string
ciFlag bool
cloudRegionFlag string
nodeTypeFlag string
nodeCountFlag string
clusterNameFlag string
clusterTypeFlag string
k3sServersPrivateIpsFlag []string
k3sServersPublicIpsFlag []string
k3sSshUserflag string
k3sSshPrivateKeyflag string
K3sServersArgsFlags []string
dnsProviderFlag string
domainNameFlag string
githubOrgFlag string
gitlabGroupFlag string
gitProviderFlag string
gitProtocolFlag string
gitopsTemplateURLFlag string
gitopsTemplateBranchFlag string
useTelemetryFlag bool
forceDestroyFlag bool

// RootCredentials
copyArgoCDPasswordToClipboardFlag bool
copyKbotPasswordToClipboardFlag bool
copyVaultPasswordToClipboardFlag bool

// Supported providers
supportedDNSProviders = []string{"cloudflare"}
supportedGitProviders = []string{"github", "gitlab"}

// Supported git providers
supportedGitProtocolOverride = []string{"https", "ssh"}
)

func NewCommand() *cobra.Command {
k3sCmd := &cobra.Command{
Use: "k3s",
Short: "kubefirst K3s installation",
Long: "kubefirst k3s on premises installation",
}

// on error, doesnt show helper/usage
k3sCmd.SilenceUsage = true

// wire up new commands
k3sCmd.AddCommand(Create(), Destroy(), RootCredentials())

return k3sCmd
}

func Create() *cobra.Command {
createCmd := &cobra.Command{
Use: "create",
Short: "create the kubefirst platform running on premise",
TraverseChildren: true,
RunE: createK3s,
// PreRun: common.CheckDocker,
}

// todo review defaults and update descriptions
createCmd.Flags().StringVar(&alertsEmailFlag, "alerts-email", "", "email address for let's encrypt certificate notifications (required)")
createCmd.MarkFlagRequired("alerts-email")
createCmd.Flags().BoolVar(&ciFlag, "ci", false, "if running kubefirst in ci, set this flag to disable interactive features")
createCmd.Flags().StringVar(&cloudRegionFlag, "cloud-region", "on-premise", "NOT USED, PRESENT FOR COMPATIBILITY ISSUE")
createCmd.Flags().StringVar(&nodeTypeFlag, "node-type", "on-premise", "NOT USED, PRESENT FOR COMPATIBILITY ISSUE")
createCmd.Flags().StringVar(&nodeCountFlag, "node-count", "3", "NOT USED, PRESENT FOR COMPATIBILITY ISSUE")
createCmd.Flags().StringVar(&clusterNameFlag, "cluster-name", "kubefirst", "the name of the cluster to create")
createCmd.Flags().StringVar(&clusterTypeFlag, "cluster-type", "mgmt", "the type of cluster to create (i.e. mgmt|workload)")
createCmd.Flags().StringSliceVar(&k3sServersPrivateIpsFlag, "servers-private-ips", []string{}, "the list of k3s (servers) private ip x.x.x.x,y.y.y.y comma separated (required)")
createCmd.MarkFlagRequired("servers-private-ips")
createCmd.Flags().StringSliceVar(&k3sServersPublicIpsFlag, "servers-public-ips", []string{}, "the list of k3s (servers) public ip x.x.x.x,y.y.y.y comma separated (required)")
createCmd.Flags().StringSliceVar(&K3sServersArgsFlags, "servers-args", []string{"--disable traefik", "--write-kubeconfig-mode 644"}, "list of k3s extras args to add to the k3s server installation,comma separated in between quote, if --servers-publis-ips <VALUES> --tls-san <VALUES> is added to default --servers-args")
createCmd.Flags().StringVar(&k3sSshUserflag, "ssh-user", "root", "the user used to log into servers with ssh connection")
createCmd.Flags().StringVar(&k3sSshPrivateKeyflag, "ssh-privatekey", "", "the private key used to log into servers with ssh connection")
createCmd.MarkFlagRequired("ssh-privatekey")
createCmd.Flags().StringVar(&dnsProviderFlag, "dns-provider", "cloudflare", fmt.Sprintf("the dns provider - one of: %s", supportedDNSProviders))
createCmd.Flags().StringVar(&domainNameFlag, "domain-name", "", "the cloudProvider DNS Name to use for DNS records (i.e. your-domain.com|subdomain.your-domain.com) (required)")
createCmd.Flags().StringVar(&gitProviderFlag, "git-provider", "github", fmt.Sprintf("the git provider - one of: %s", supportedGitProviders))
createCmd.Flags().StringVar(&gitProtocolFlag, "git-protocol", "ssh", fmt.Sprintf("the git protocol - one of: %s", supportedGitProtocolOverride))
createCmd.Flags().StringVar(&githubOrgFlag, "github-org", "", "the GitHub organization for the new gitops and metaphor repositories - required if using github")
createCmd.Flags().StringVar(&gitlabGroupFlag, "gitlab-group", "", "the GitLab group for the new gitops and metaphor projects - required if using gitlab")
createCmd.Flags().StringVar(&gitopsTemplateBranchFlag, "gitops-template-branch", "", "the branch to clone for the gitops-template repository")
createCmd.Flags().StringVar(&gitopsTemplateURLFlag, "gitops-template-url", "https://github.com/kubefirst/gitops-template.git", "the fully qualified url to the gitops-template repository to clone")
createCmd.Flags().BoolVar(&useTelemetryFlag, "use-telemetry", true, "whether to emit telemetry")
createCmd.Flags().BoolVar(&forceDestroyFlag, "force-destroy", false, "allows force destruction on objects (helpful for test environments, defaults to false)")
return createCmd
}

func Destroy() *cobra.Command {
destroyCmd := &cobra.Command{
Use: "destroy",
Short: "destroy the kubefirst platform",
Long: "destroy the kubefirst platform running in k3s cluster",
RunE: common.Destroy,
// PreRun: common.CheckDocker,
}

return destroyCmd
}

func RootCredentials() *cobra.Command {
authCmd := &cobra.Command{
Use: "root-credentials",
Short: "retrieve root authentication information for platform components",
Long: "retrieve root authentication information for platform components",
RunE: common.GetRootCredentials,
}

authCmd.Flags().BoolVar(&copyArgoCDPasswordToClipboardFlag, "argocd", false, "copy the argocd password to the clipboard (optional)")
authCmd.Flags().BoolVar(&copyKbotPasswordToClipboardFlag, "kbot", false, "copy the kbot password to the clipboard (optional)")
authCmd.Flags().BoolVar(&copyVaultPasswordToClipboardFlag, "vault", false, "copy the vault password to the clipboard (optional)")

return authCmd
}
117 changes: 117 additions & 0 deletions cmd/k3s/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
Copyright (C) 2021-2023, Kubefirst
This program is licensed under MIT.
See the LICENSE file for more details.
*/
package k3s

import (
"fmt"

"github.com/rs/zerolog/log"

"github.com/kubefirst/kubefirst/internal/cluster"
"github.com/kubefirst/kubefirst/internal/gitShim"
"github.com/kubefirst/kubefirst/internal/launch"
"github.com/kubefirst/kubefirst/internal/progress"
"github.com/kubefirst/kubefirst/internal/provision"
"github.com/kubefirst/kubefirst/internal/utilities"
"github.com/kubefirst/runtime/pkg"
internalssh "github.com/kubefirst/runtime/pkg/ssh"
"github.com/spf13/cobra"
"github.com/spf13/viper"
_ "k8s.io/client-go/plugin/pkg/client/auth"
)

func createK3s(cmd *cobra.Command, args []string) error {
cliFlags, err := utilities.GetFlags(cmd, "k3s")
if err != nil {
progress.Error(err.Error())
return nil
}

progress.DisplayLogHints(20)

err = ValidateProvidedFlags(cliFlags.GitProvider)
if err != nil {
progress.Error(err.Error())
return nil
}

// If cluster setup is complete, return
clusterSetupComplete := viper.GetBool("kubefirst-checks.cluster-install-complete")
if clusterSetupComplete {
err = fmt.Errorf("this cluster install process has already completed successfully")
progress.Error(err.Error())
return nil
}

utilities.CreateK1ClusterDirectory(clusterNameFlag)

gitAuth, err := gitShim.ValidateGitCredentials(cliFlags.GitProvider, cliFlags.GithubOrg, cliFlags.GitlabGroup)
if err != nil {
progress.Error(err.Error())
return nil
}

executionControl := viper.GetBool(fmt.Sprintf("kubefirst-checks.%s-credentials", cliFlags.GitProvider))
if !executionControl {
newRepositoryNames := []string{"gitops", "metaphor"}
newTeamNames := []string{"admins", "developers"}

initGitParameters := gitShim.GitInitParameters{
GitProvider: gitProviderFlag,
GitToken: gitAuth.Token,
GitOwner: gitAuth.Owner,
Repositories: newRepositoryNames,
Teams: newTeamNames,
}
err = gitShim.InitializeGitProvider(&initGitParameters)
if err != nil {
progress.Error(err.Error())
return nil
}
}
viper.Set(fmt.Sprintf("kubefirst-checks.%s-credentials", cliFlags.GitProvider), true)
viper.WriteConfig()

k3dClusterCreationComplete := viper.GetBool("launch.deployed")
if !k3dClusterCreationComplete {
launch.Up(nil, true, cliFlags.UseTelemetry)
}

err = pkg.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresUrl()), "kubefirst api")
if err != nil {
progress.Error("unable to start kubefirst api")
}

provision.CreateMgmtCluster(gitAuth, cliFlags)

return nil
}

func ValidateProvidedFlags(gitProvider string) error {
progress.AddStep("Validate provided flags")

switch gitProvider {
case "github":
key, err := internalssh.GetHostKey("github.com")
if err != nil {
return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan github.com >> ~/.ssh/known_hosts` to remedy")
} else {
log.Info().Msgf("%s %s\n", "github.com", key.Type())
}
case "gitlab":
key, err := internalssh.GetHostKey("gitlab.com")
if err != nil {
return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan gitlab.com >> ~/.ssh/known_hosts` to remedy")
} else {
log.Info().Msgf("%s %s\n", "gitlab.com", key.Type())
}
}

progress.CompleteStep("Validate provided flags")

return nil
}
3 changes: 3 additions & 0 deletions internal/progress/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ func DisplaySuccessMessage(cluster types.Cluster) successMsg {

case "vultr":
cloudCliKubeconfig = fmt.Sprintf("vultr-cli kubernetes config %s", cluster.ClusterName)

case "k3s":
cloudCliKubeconfig = fmt.Sprint(("use the kubeconfig file outputed from terraform to acces to the cluster"))
break

}
Expand Down
5 changes: 5 additions & 0 deletions internal/types/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,9 @@ type CliFlags struct {
NodeType string
NodeCount string
InstallCatalogApps string
K3sSshUser string
K3sSshPrivateKey string
K3sServersPrivateIps []string
K3sServersPublicIps []string
K3sServersArgs []string
}
45 changes: 45 additions & 0 deletions internal/utilities/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,44 @@ func GetFlags(cmd *cobra.Command, cloudProvider string) (types.CliFlags, error)
cliFlags.GoogleProject = googleProject
}

// TODO: reafactor this part
if cloudProvider == "k3s" {
k3sServersPrivateIps, err := cmd.Flags().GetStringSlice("servers-private-ips")
if err != nil {
progress.Error(err.Error())
return cliFlags, err
}
cliFlags.K3sServersPrivateIps = k3sServersPrivateIps

k3sServersPublicIps, err := cmd.Flags().GetStringSlice("servers-public-ips")
if err != nil {
progress.Error(err.Error())
return cliFlags, err
}
cliFlags.K3sServersPublicIps = k3sServersPublicIps

k3sSshUserFlag, err := cmd.Flags().GetString("ssh-user")
if err != nil {
progress.Error(err.Error())
return cliFlags, err
}
cliFlags.K3sSshUser = k3sSshUserFlag

k3sSshPrivateKeyFlag, err := cmd.Flags().GetString("ssh-privatekey")
if err != nil {
progress.Error(err.Error())
return cliFlags, err
}
cliFlags.K3sSshPrivateKey = k3sSshPrivateKeyFlag

K3sServersArgsFlags, err := cmd.Flags().GetStringSlice("servers-args")
if err != nil {
progress.Error(err.Error())
return cliFlags, err
}
cliFlags.K3sServersArgs = K3sServersArgsFlags
}

cliFlags.AlertsEmail = alertsEmailFlag
cliFlags.CloudRegion = cloudRegionFlag
cliFlags.ClusterName = clusterNameFlag
Expand All @@ -162,6 +200,13 @@ func GetFlags(cmd *cobra.Command, cloudProvider string) (types.CliFlags, error)
viper.Set("flags.git-protocol", cliFlags.GitProtocol)
viper.Set("flags.cloud-region", cliFlags.CloudRegion)
viper.Set("kubefirst.cloud-provider", cloudProvider)
if cloudProvider == "k3s" {
viper.Set("flags.servers-private-ips", cliFlags.K3sServersPrivateIps)
viper.Set("flags.servers-public-ips", cliFlags.K3sServersPublicIps)
viper.Set("flags.ssh-user", cliFlags.K3sSshUser)
viper.Set("flags.ssh-privatekey", cliFlags.K3sSshPrivateKey)
viper.Set("flags.servers-args", cliFlags.K3sServersArgs)
}
viper.WriteConfig()

return cliFlags, nil
Expand Down
10 changes: 8 additions & 2 deletions internal/utilities/utilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func CreateClusterRecordFromRaw(
case "civo":
cl.CivoAuth.Token = os.Getenv("CIVO_TOKEN")
case "aws":
//ToDo: where to get credentials?
// ToDo: where to get credentials?
cl.AWSAuth.AccessKeyID = viper.GetString("kubefirst.state-store-creds.access-key-id")
cl.AWSAuth.SecretAccessKey = viper.GetString("kubefirst.state-store-creds.secret-access-key-id")
cl.AWSAuth.SessionToken = viper.GetString("kubefirst.state-store-creds.token")
Expand Down Expand Up @@ -192,7 +192,7 @@ func CreateClusterDefinitionRecordFromRaw(gitAuth apiTypes.GitAuth, cliFlags typ
case "civo":
cl.CivoAuth.Token = os.Getenv("CIVO_TOKEN")
case "aws":
//ToDo: where to get credentials?
// ToDo: where to get credentials?
cl.AWSAuth.AccessKeyID = viper.GetString("kubefirst.state-store-creds.access-key-id")
cl.AWSAuth.SecretAccessKey = viper.GetString("kubefirst.state-store-creds.secret-access-key-id")
cl.AWSAuth.SessionToken = viper.GetString("kubefirst.state-store-creds.token")
Expand All @@ -203,6 +203,12 @@ func CreateClusterDefinitionRecordFromRaw(gitAuth apiTypes.GitAuth, cliFlags typ
cl.DigitaloceanAuth.SpacesSecret = os.Getenv("DO_SPACES_SECRET")
case "vultr":
cl.VultrAuth.Token = os.Getenv("VULTR_API_KEY")
case "k3s":
cl.K3sAuth.K3sServersPrivateIps = viper.GetStringSlice("flags.servers-private-ips")
cl.K3sAuth.K3sServersPublicIps = viper.GetStringSlice("flags.servers-public-ips")
cl.K3sAuth.K3sSshUser = viper.GetString("flags.ssh-user")
cl.K3sAuth.K3sSshPrivateKey = viper.GetString("flags.ssh-privatekey")
cl.K3sAuth.K3sServersArgs = viper.GetStringSlice("flags.servers-args")
case "google":
jsonFilePath := os.Getenv("GOOGLE_APPLICATION_CREDENTIALS")

Expand Down

0 comments on commit 5c7f74c

Please sign in to comment.