Skip to content

Commit

Permalink
Merge pull request #48 from conplementAG/feature/copsctl-goes-cops-hq
Browse files Browse the repository at this point in the history
feat: copsctl goes cops-hq
  • Loading branch information
huf1 authored Sep 26, 2022
2 parents 5636955 + 31f3497 commit 93fc7ac
Show file tree
Hide file tree
Showing 26 changed files with 737 additions and 1,123 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ copsctl - the Conplement AG Kubernetes developer tooling
[![Build Status](https://cpgithub.visualstudio.com/GitHubPipelines/_apis/build/status/conplementAG.copsctl?branchName=master)](https://cpgithub.visualstudio.com/GitHubPipelines/_build/latest?definitionId=9&branchName=master)

## Requirements
- [kubectl > 1.21](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
- [kubectl >= 1.23.9](https://kubernetes.io/docs/tasks/tools/install-kubectl/)

## Installation

Expand Down
93 changes: 31 additions & 62 deletions cmd/copsctl/azure_devops.go
Original file line number Diff line number Diff line change
@@ -1,71 +1,40 @@
package main

import (
"github.com/conplementAG/copsctl/internal/cmd/flags"
"os"

"github.com/conplementAG/copsctl/internal/azure_devops"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/conplementAG/copsctl/internal/cmd/flags"
"github.com/conplementag/cops-hq/pkg/cli"
"github.com/conplementag/cops-hq/pkg/hq"
)

func createAzureDevopsCommand() *cobra.Command {
var command = &cobra.Command{
Use: "azure-devops",
Short: "[DEPRECATED] Command group for administration of Azure DevOps accounts",
Long: `
[DEPRECATED] Instead of setting up the Azure DevOps service connection, consider using copsctl connect just before deploying via Helm.
This way you will not have a dependency on Azure DevOps and a prerequisite to setup the service connection before deploying.
`,
PersistentPreRun: func(cmd *cobra.Command, args []string) {
// bind these during pre-run to avoid viper overwriting itself when same PFlag used with multiple commands
viper.BindPFlag(flags.EnvironmentTag, cmd.Flags().Lookup(flags.EnvironmentTag))
viper.BindPFlag(flags.Organization, cmd.Flags().Lookup(flags.Organization))
viper.BindPFlag(flags.Project, cmd.Flags().Lookup(flags.Project))
viper.BindPFlag(flags.Namespace, cmd.Flags().Lookup(flags.Namespace))
viper.BindPFlag(flags.Username, cmd.Flags().Lookup(flags.Username))
viper.BindPFlag(flags.AccessToken, cmd.Flags().Lookup(flags.AccessToken))
},
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
cmd.Help()
os.Exit(0)
}
},
}

command.PersistentFlags().StringP(flags.EnvironmentTag, "e", "", "Tag to use to make all environment names unique, e.g. your env identifier")
command.MarkPersistentFlagRequired(flags.EnvironmentTag)

command.PersistentFlags().StringP(flags.Organization, "o", "", "Name of the Azure DevOps organization")
command.MarkPersistentFlagRequired(flags.Organization)

command.PersistentFlags().StringP(flags.Project, "p", "", "The name of Azure DevOps project")
command.MarkPersistentFlagRequired(flags.Project)

command.PersistentFlags().StringP(flags.AccessToken, "t", "", "Your access token to access Azure DevOps (see. Azure DevOps->Profile->Security)")
command.MarkPersistentFlagRequired(flags.AccessToken)

command.PersistentFlags().StringP(flags.Username, "u", "", "Your username to access Azure DevOps (see. Azure DevOps->Profile->Security)")
command.MarkPersistentFlagRequired(flags.Username)

command.PersistentFlags().StringP(flags.Namespace, "n", "", "Namespace to which the endpoint can be scoped (RBAC rights)")

command.AddCommand(createAzureDevopsCreateEndpointCommand())

return command
func createAzureDevopsCommand(hq hq.HQ) {
azureDevOpsCmdGroup := hq.GetCli().AddBaseCommand("azure-devops",
"[DEPRECATED] Command group for administration of Azure DevOps accounts",
"[DEPRECATED] Instead of setting up the Azure DevOps service connection, consider using copsctl connect just before deploying via Helm. "+
"This way you will not have a dependency on Azure DevOps and a prerequisite to setup the service connection before deploying.",
nil)

azureDevOpsCmdGroup.AddPersistentParameterString(flags.EnvironmentTag, "", true, "e",
"Tag to use to make all environment names unique, e.g. your env identifier")
azureDevOpsCmdGroup.AddPersistentParameterString(flags.Organization, "", true, "o",
"Name of the Azure DevOps organization")
azureDevOpsCmdGroup.AddPersistentParameterString(flags.Project, "", true, "p",
"The name of Azure DevOps project")
azureDevOpsCmdGroup.AddPersistentParameterString(flags.AccessToken, "", true, "t",
"Your access token to access Azure DevOps (see. Azure DevOps->Profile->Security)")
azureDevOpsCmdGroup.AddPersistentParameterString(flags.Username, "", true, "u",
"Your username to access Azure DevOps (see. Azure DevOps->Profile->Security)")
azureDevOpsCmdGroup.AddPersistentParameterString(flags.Namespace, "", false, "n",
"Namespace to which the endpoint can be scoped (RBAC rights)")

createAzureDevopsCreateEndpointCommand(hq, azureDevOpsCmdGroup)
}

func createAzureDevopsCreateEndpointCommand() *cobra.Command {
return &cobra.Command{
Use: "create-endpoint",
Short: "[DEPRECATED] Connect the Azure DevOps account to the current Kubernetes cluster.",
Long: `
[DEPRECATED] Use this command to provision a service account which will be used to create a service endpoint in the Azure DevOps project.
This command is idempotent. Check azure-devops command info for deprecation explanation.
`,
Run: func(cmd *cobra.Command, args []string) {
azure_devops.NewOrchestrator().ConfigureEndpoint()
},
}
func createAzureDevopsCreateEndpointCommand(hq hq.HQ, cmd cli.Command) {

cmd.AddCommand("create-endpoint", "[DEPRECATED] Connect the Azure DevOps account to the current Kubernetes cluster.",
"[DEPRECATED] Use this command to provision a service account which will be used to create a service endpoint in the Azure DevOps project. "+
"This command is idempotent. Check azure-devops command info for deprecation explanation.", func() {
azure_devops.New(hq).ConfigureEndpoint()
})
}
10 changes: 10 additions & 0 deletions cmd/copsctl/cli.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package main

import "github.com/conplementag/cops-hq/pkg/hq"

func createCommands(hq hq.HQ) {
createNamespaceCommand(hq)
createClusterInfoCommand(hq)
createConnectCommand(hq)
createAzureDevopsCommand(hq)
}
30 changes: 9 additions & 21 deletions cmd/copsctl/cluster_info.go
Original file line number Diff line number Diff line change
@@ -1,31 +1,19 @@
package main

import (
"fmt"
"github.com/conplementAG/copsctl/internal/cluster_info"
"github.com/conplementAG/copsctl/internal/cmd/flags"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/conplementag/cops-hq/pkg/hq"
)

func createClusterInfoCommand() *cobra.Command {
var command = &cobra.Command{
Use: "cluster-info",
Short: "Command for showing the CoreOps cluster information",
Long: `
Use this command to get the cluster info which might be useful for your. For example, if the static outbound IPs are enabled for the cluster,
then you can use this command to get these IPs. Make sure you are connected to the cluster first.
` + "Use the " + flags.PrintToStdoutSilenceEverythingElse + " flag for automation.",
PreRun: func(cmd *cobra.Command, args []string) {
viper.BindPFlag(flags.PrintToStdoutSilenceEverythingElse,
cmd.Flags().Lookup(flags.PrintToStdoutSilenceEverythingElse))
},
Run: func(cmd *cobra.Command, args []string) {
cluster_info.ShowClusterInfo()
},
}
func createClusterInfoCommand(hq hq.HQ) {
clusterInfoCmdGroup := hq.GetCli().AddBaseCommand("cluster-info", "Command for showing the CoreOps cluster information",
fmt.Sprintf("Use this command to get the cluster info which might be useful for your. For example, if the static outbound IPs are enabled for the cluster, then you can use this command to get these IPs. Make sure you are connected to the cluster first. "+
"Use the %s flag for automation.", flags.PrintToStdoutSilenceEverythingElse), func() {
cluster_info.New(hq).ShowClusterInfo()
})

command.PersistentFlags().BoolP(flags.PrintToStdoutSilenceEverythingElse, "q", false,
clusterInfoCmdGroup.AddPersistentParameterBool(flags.PrintToStdoutSilenceEverythingElse, false, false, "q",
"Similar to print-to-stdout, but silences all other logging outputs. Useful for automation.")

return command
}
51 changes: 13 additions & 38 deletions cmd/copsctl/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,53 +3,28 @@ package main
import (
"github.com/conplementAG/copsctl/internal/cmd/flags"
"github.com/conplementAG/copsctl/internal/connection"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/conplementag/cops-hq/pkg/hq"
)

func createConnectCommand() *cobra.Command {
var command = &cobra.Command{
Use: "connect",
Short: "Command for managing the connection to k8s clusters",
Long: `
Use this command to manage the connection to a k8s cluster.
`,
PreRun: func(cmd *cobra.Command, args []string) {
viper.BindPFlag(flags.EnvironmentTag, cmd.Flags().Lookup(flags.EnvironmentTag))
viper.BindPFlag(flags.ConnectionString, cmd.Flags().Lookup(flags.ConnectionString))
viper.BindPFlag(flags.TechnicalAccount, cmd.Flags().Lookup(flags.TechnicalAccount))
viper.BindPFlag(flags.Secondary, cmd.Flags().Lookup(flags.Secondary))
func createConnectCommand(hq hq.HQ) {
connectCmdGroup := hq.GetCli().AddBaseCommand("connect", "Command for managing the connection to k8s clusters",
"Use this command to manage the connection to a k8s cluster.", func() {
connection.New(hq).Connect()
})

viper.BindPFlag(flags.AutoApprove, cmd.Flags().Lookup(flags.AutoApprove))
viper.BindPFlag(flags.PrintToStdout, cmd.Flags().Lookup(flags.PrintToStdout))
viper.BindPFlag(flags.PrintToStdoutSilenceEverythingElse,
cmd.Flags().Lookup(flags.PrintToStdoutSilenceEverythingElse))
},
Run: func(cmd *cobra.Command, args []string) {
connection.Connect()
},
}

command.PersistentFlags().StringP(flags.EnvironmentTag, "e", "",
connectCmdGroup.AddPersistentParameterString(flags.EnvironmentTag, "", true, "e",
"The environment tag of the environment you want to connect to")
command.MarkPersistentFlagRequired(flags.EnvironmentTag)

command.PersistentFlags().StringP(flags.ConnectionString, "c", "",
connectCmdGroup.AddPersistentParameterString(flags.ConnectionString, "", true, "c",
"The connection string for the environment.")
command.MarkPersistentFlagRequired(flags.ConnectionString)

command.PersistentFlags().BoolP(flags.TechnicalAccount, "t", false,
connectCmdGroup.AddPersistentParameterBool(flags.TechnicalAccount, false, false, "t",
"Use to switch to non-interactive technical account mode. "+
"Make sure that the connection string you provide is valid for a technical account!")
command.PersistentFlags().BoolP(flags.Secondary, "s", false,
connectCmdGroup.AddPersistentParameterBool(flags.Secondary, false, false, "s",
"Connect to the secondary instead of the primary cluster.")

command.PersistentFlags().BoolP(flags.AutoApprove, "a", false,
connectCmdGroup.AddPersistentParameterBool(flags.AutoApprove, false, false, "a",
"Auto approve any confirmation prompts.")
command.PersistentFlags().BoolP(flags.PrintToStdout, "p", false,
connectCmdGroup.AddPersistentParameterBool(flags.PrintToStdout, false, false, "p",
"Print the config to stdout instead of overwriting $HOME/.kube/config. Useful for developers")
command.PersistentFlags().BoolP(flags.PrintToStdoutSilenceEverythingElse, "q", false,
connectCmdGroup.AddPersistentParameterBool(flags.PrintToStdoutSilenceEverythingElse, false, false, "q",
"Similar to print-to-stdout, but silences all other logging outputs. Useful for automation.")

return command
}
14 changes: 9 additions & 5 deletions cmd/copsctl/main.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
package main

import (
"github.com/conplementag/cops-hq/pkg/error_handling"
"github.com/conplementag/cops-hq/pkg/hq"
"github.com/sirupsen/logrus"
"os"

"github.com/conplementAG/copsctl/internal/common/logging"
)

func main() {
defer logging.Dispose()
defer errorhandler()
hq := hq.NewQuiet("copsctl", "0.9.0", "copsctl.log")
createCommands(hq)

error_handling.PanicOnAnyError = true

Execute()
hq.Run()
}

func errorhandler() {
// as this is a CLI tool, and not a library with an API, panic is used for most errors that occur,
// since they are unrecoverable and need some user intervention (or they are genuine panic programming
// errors)
if r := recover(); r != nil {
logging.Errorf("copsctl --- error occured: %+v\n", r)
logrus.Errorf("copsctl --- error occured: %+v\n", r)
os.Exit(1)
}
}
Loading

0 comments on commit 93fc7ac

Please sign in to comment.