From 31f3497fcabb563995d1b1ee6d1a16c81df4992c Mon Sep 17 00:00:00 2001 From: huf1 Date: Mon, 26 Sep 2022 09:22:10 +0200 Subject: [PATCH] feat: copsctl goes cops-hq use cops-hq for: - cli - command execution - logging --- README.md | 2 +- cmd/copsctl/azure_devops.go | 93 +-- cmd/copsctl/cli.go | 10 + cmd/copsctl/cluster_info.go | 30 +- cmd/copsctl/connection.go | 51 +- cmd/copsctl/main.go | 14 +- cmd/copsctl/namespace.go | 302 +++------- cmd/copsctl/root.go | 64 -- go.mod | 56 +- go.sum | 547 +++++++++++------- internal/adapters/azure_devops/endpoints.go | 36 +- internal/adapters/azure_devops/http.go | 43 +- internal/adapters/kubernetes/commands.go | 66 +-- .../adapters/kubernetes/service_account.go | 7 +- .../kubernetes/service_account_secret.go | 7 +- internal/azure_devops/orchestrator.go | 35 +- internal/cluster_info/orchestrator.go | 36 +- internal/common/commands/commands.go | 84 --- internal/common/commands/execute.go | 95 --- .../common/file_processing/file_processing.go | 10 +- internal/common/logging/logging.go | 95 --- internal/connection/helpers.go | 15 +- internal/connection/orchestrator.go | 58 +- internal/namespace/namespace.go | 46 +- internal/namespace/serviceaccounts.go | 28 +- internal/namespace/users.go | 30 +- 26 files changed, 737 insertions(+), 1123 deletions(-) create mode 100644 cmd/copsctl/cli.go delete mode 100644 cmd/copsctl/root.go delete mode 100644 internal/common/commands/commands.go delete mode 100644 internal/common/commands/execute.go delete mode 100644 internal/common/logging/logging.go diff --git a/README.md b/README.md index a7a2fd4..e08567f 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/cmd/copsctl/azure_devops.go b/cmd/copsctl/azure_devops.go index 956bed0..00bec6c 100644 --- a/cmd/copsctl/azure_devops.go +++ b/cmd/copsctl/azure_devops.go @@ -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() + }) } diff --git a/cmd/copsctl/cli.go b/cmd/copsctl/cli.go new file mode 100644 index 0000000..3aceb7b --- /dev/null +++ b/cmd/copsctl/cli.go @@ -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) +} diff --git a/cmd/copsctl/cluster_info.go b/cmd/copsctl/cluster_info.go index 971d455..caea008 100644 --- a/cmd/copsctl/cluster_info.go +++ b/cmd/copsctl/cluster_info.go @@ -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 } diff --git a/cmd/copsctl/connection.go b/cmd/copsctl/connection.go index 7a93dc9..4ef8d0f 100644 --- a/cmd/copsctl/connection.go +++ b/cmd/copsctl/connection.go @@ -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 } diff --git a/cmd/copsctl/main.go b/cmd/copsctl/main.go index 13bb605..32d0924 100644 --- a/cmd/copsctl/main.go +++ b/cmd/copsctl/main.go @@ -1,16 +1,20 @@ 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() { @@ -18,7 +22,7 @@ func errorhandler() { // 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) } } diff --git a/cmd/copsctl/namespace.go b/cmd/copsctl/namespace.go index e560b7d..d928005 100644 --- a/cmd/copsctl/namespace.go +++ b/cmd/copsctl/namespace.go @@ -2,257 +2,139 @@ package main import ( "github.com/conplementAG/copsctl/internal/cmd/flags" - "os" - "github.com/conplementAG/copsctl/internal/namespace" - "github.com/spf13/cobra" - "github.com/spf13/viper" + "github.com/conplementag/cops-hq/pkg/cli" + "github.com/conplementag/cops-hq/pkg/hq" ) -func createNamespaceCommand() *cobra.Command { - var command = &cobra.Command{ - Use: "namespace", - Short: "Command group for administration of k8s namespaces", - Long: "Use this command to administer k8s namespaces.", - Run: func(cmd *cobra.Command, args []string) { - // since "namespace" is not really a command, but rather a group of commands, we - // show the help for the command group instead - if len(args) == 0 { - cmd.Help() - os.Exit(0) - } - }, - } +func createNamespaceCommand(hq hq.HQ) { + namespaceCmdGroup := hq.GetCli().AddBaseCommand("namespace", "Command group for administration of k8s namespaces", + "Use this command to administer k8s namespaces.", nil) - command.AddCommand(createNamespaceListCommand()) - command.AddCommand(createNamespaceCreateCommand()) - command.AddCommand(createNamespaceDeleteCommand()) - command.AddCommand(createNamespaceUsersCommand()) - command.AddCommand(createNamespaceServiceAccountsCommand()) + namespaceOrchestrator := namespace.New(hq) - return command + createNamespaceListCommand(namespaceOrchestrator, namespaceCmdGroup) + createNamespaceCreateCommand(namespaceOrchestrator, namespaceCmdGroup) + createNamespaceDeleteCommand(namespaceOrchestrator, namespaceCmdGroup) + createNamespaceUsersCommand(namespaceOrchestrator, namespaceCmdGroup) + createNamespaceServiceAccountsCommand(namespaceOrchestrator, namespaceCmdGroup) } -func createNamespaceListCommand() *cobra.Command { - var command = &cobra.Command{ - Use: "list", - Short: "Lists all the CoreOps namespaces", - Long: "Use this list all the CoreOps namespaces inside this cluster.", - Run: func(cmd *cobra.Command, args []string) { - namespace.List() - }, - } - - return command +func createNamespaceListCommand(o *namespace.Orchestrator, cmd cli.Command) { + cmd.AddCommand("list", "Lists all the CoreOps namespaces", "Use this list all the CoreOps namespaces inside this cluster.", func() { + o.List() + }) } -func createNamespaceCreateCommand() *cobra.Command { - var command = &cobra.Command{ - Use: "create", - Short: "Create a new namespace", - Long: "Use this command to create a new k8s namespace. This command is idempotent, " + - "which means you can use it multiple times to ensure that the namespace is there, " + - "as well as all other users.", - PreRun: func(cmd *cobra.Command, args []string) { - viper.BindPFlag(flags.Users, cmd.Flags().Lookup(flags.Users)) - viper.BindPFlag(flags.ServiceAccounts, cmd.Flags().Lookup(flags.ServiceAccounts)) - viper.BindPFlag(flags.Name, cmd.Flags().Lookup(flags.Name)) - }, - Run: func(cmd *cobra.Command, args []string) { - namespace.Create() - }, - } - - command.PersistentFlags().StringP(flags.Name, "n", "", "Name of the namespace") - command.MarkPersistentFlagRequired(flags.Name) - - addUsersPersistentFlag(command) - command.MarkPersistentFlagRequired(flags.Users) - - addServiceAccountsPersistentFlag(command) - - return command +func createNamespaceCreateCommand(o *namespace.Orchestrator, cmd cli.Command) { + namespaceCreateCmd := cmd.AddCommand("create", "Create a new namespace", + "Use this command to create a new k8s namespace. This command is idempotent, "+ + "which means you can use it multiple times to ensure that the namespace is there, "+ + "as well as all other users.", func() { + o.Create() + }) + + addUsersParam(namespaceCreateCmd) + addServiceAccountsParam(namespaceCreateCmd) + addNameParam(namespaceCreateCmd) } -func createNamespaceDeleteCommand() *cobra.Command { - var command = &cobra.Command{ - Use: "delete", - Short: "Delete an existing namespace", - Long: "Use this command to delete existing cops namespace.", - PreRun: func(cmd *cobra.Command, args []string) { - viper.BindPFlag(flags.Name, cmd.Flags().Lookup(flags.Name)) - }, - Run: func(cmd *cobra.Command, args []string) { - namespace.Delete() - }, - } +func createNamespaceDeleteCommand(o *namespace.Orchestrator, cmd cli.Command) { + namespaceDeleteCmd := cmd.AddCommand("delete", "Delete an existing namespace", + "Use this command to delete existing cops namespace.", func() { + o.Delete() + }) - command.PersistentFlags().StringP(flags.Name, "n", "", "Name of the namespace") - command.MarkPersistentFlagRequired(flags.Name) - - return command + addNameParam(namespaceDeleteCmd) } -func createNamespaceUsersCommand() *cobra.Command { - var command = &cobra.Command{ - Use: "users", - Short: "Manage users of a namespace", - Long: "Use this command to manage the users in an existing k8s namespace.", - Run: func(cmd *cobra.Command, args []string) { - if len(args) == 0 { - cmd.Help() - os.Exit(0) - } - }, - } - - command.PersistentFlags().StringP(flags.Name, "n", "", "Name of the namespace") - command.MarkPersistentFlagRequired(flags.Name) +func createNamespaceUsersCommand(o *namespace.Orchestrator, cmd cli.Command) { + namespaceUserCmd := cmd.AddCommand("users", "Manage users of a namespace", + "Use this command to manage the users in an existing k8s namespace.", + nil) - command.AddCommand(createNamespaceUsersAddCommand()) - command.AddCommand(createNamespaceUsersRemoveCommand()) - command.AddCommand(createNamespaceUsersListCommand()) + addNameParam(namespaceUserCmd) - return command + createNamespaceUsersAddCommand(o, namespaceUserCmd) + createNamespaceUsersRemoveCommand(o, namespaceUserCmd) + createNamespaceUsersListCommand(o, namespaceUserCmd) } -func createNamespaceUsersAddCommand() *cobra.Command { - var command = &cobra.Command{ - Use: "add", - Short: "Adds users to the namespace", - Long: "Use this command to add users to an existing k8s namespace.", - PreRun: func(cmd *cobra.Command, args []string) { - viper.BindPFlag(flags.Users, cmd.Flags().Lookup(flags.Users)) - viper.BindPFlag(flags.Name, cmd.Flags().Lookup(flags.Name)) - }, - Run: func(cmd *cobra.Command, args []string) { - namespace.AddUsers() - }, - } +func createNamespaceUsersAddCommand(o *namespace.Orchestrator, cmd cli.Command) { + namespaceUsersAddCmd := cmd.AddCommand("add", "Adds users to the namespace", + "Use this command to add users to an existing k8s namespace.", func() { + o.AddUsers() + }) - addUsersPersistentFlag(command) - command.MarkPersistentFlagRequired(flags.Users) - return command + addUsersParam(namespaceUsersAddCmd) } -func createNamespaceUsersRemoveCommand() *cobra.Command { - var command = &cobra.Command{ - Use: "remove", - Short: "Removes users from a namespace", - Long: "Use this command to remove users from an existing k8s namespace.", - PreRun: func(cmd *cobra.Command, args []string) { - viper.BindPFlag(flags.Users, cmd.Flags().Lookup(flags.Users)) - viper.BindPFlag(flags.Name, cmd.Flags().Lookup(flags.Name)) - }, - Run: func(cmd *cobra.Command, args []string) { - namespace.RemoveUsers() - }, - } +func createNamespaceUsersRemoveCommand(o *namespace.Orchestrator, cmd cli.Command) { + namespaceUsersRemoveCmd := cmd.AddCommand("remove", "Removes users from a namespace", + "Use this command to remove users from an existing k8s namespace.", func() { + o.RemoveUsers() + }) - addUsersPersistentFlag(command) - command.MarkPersistentFlagRequired(flags.Users) - return command + addUsersParam(namespaceUsersRemoveCmd) } -func createNamespaceUsersListCommand() *cobra.Command { - var command = &cobra.Command{ - Use: "list", - Short: "List users of a namespace", - Long: "Use this command to list users of an existing k8s namespace.", - PreRun: func(cmd *cobra.Command, args []string) { - viper.BindPFlag(flags.Name, cmd.Flags().Lookup(flags.Name)) - }, - Run: func(cmd *cobra.Command, args []string) { - namespace.ListUsers() - }, - } - return command +func createNamespaceUsersListCommand(o *namespace.Orchestrator, cmd cli.Command) { + cmd.AddCommand("list", "List users of a namespace", + "Use this command to list users of an existing k8s namespace.", func() { + o.ListUsers() + }) } -func createNamespaceServiceAccountsCommand() *cobra.Command { - var command = &cobra.Command{ - Use: "service-accounts", - Short: "Manage service accounts of a namespace", - Long: "Use this command to manage the service accounts in an existing k8s namespace.", - Run: func(cmd *cobra.Command, args []string) { - if len(args) == 0 { - cmd.Help() - os.Exit(0) - } - }, - } - - command.PersistentFlags().StringP(flags.Name, "n", "", "Name of the namespace") - command.MarkPersistentFlagRequired(flags.Name) +func createNamespaceServiceAccountsCommand(o *namespace.Orchestrator, cmd cli.Command) { + namespaceServiceAccountsCmd := cmd.AddCommand("service-accounts", + "Manage service accounts of a namespace", + "Use this command to manage the service accounts in an existing k8s namespace.", + nil) - command.AddCommand(createNamespaceServiceAccountsAddCommand()) - command.AddCommand(createNamespaceServiceAccountsRemoveCommand()) - command.AddCommand(createNamespaceServiceAccountsListCommand()) + addNameParam(namespaceServiceAccountsCmd) - return command + createNamespaceServiceAccountsAddCommand(o, namespaceServiceAccountsCmd) + createNamespaceServiceAccountsRemoveCommand(o, namespaceServiceAccountsCmd) + createNamespaceServiceAccountsListCommand(o, namespaceServiceAccountsCmd) } -func createNamespaceServiceAccountsAddCommand() *cobra.Command { - var command = &cobra.Command{ - Use: "add", - Short: "Adds service accounts to the namespace", - Long: "Use this command to add service accounts to an existing k8s namespace.", - PreRun: func(cmd *cobra.Command, args []string) { - viper.BindPFlag(flags.ServiceAccounts, cmd.Flags().Lookup(flags.ServiceAccounts)) - viper.BindPFlag(flags.Name, cmd.Flags().Lookup(flags.Name)) - }, - Run: func(cmd *cobra.Command, args []string) { - namespace.AddServiceAccounts() - }, - } +func createNamespaceServiceAccountsAddCommand(o *namespace.Orchestrator, cmd cli.Command) { + namespaceServiceAccountAddCmd := cmd.AddCommand("add", "Adds service accounts to the namespace", + "Use this command to add service accounts to an existing k8s namespace.", func() { + o.AddServiceAccounts() + }) - addServiceAccountsPersistentFlag(command) - command.MarkPersistentFlagRequired(flags.ServiceAccounts) - return command + addServiceAccountsParam(namespaceServiceAccountAddCmd) } -func createNamespaceServiceAccountsRemoveCommand() *cobra.Command { - var command = &cobra.Command{ - Use: "remove", - Short: "Removes users from a namespace", - Long: "Use this command to remove service-accounts from an existing k8s namespace.", - PreRun: func(cmd *cobra.Command, args []string) { - viper.BindPFlag(flags.ServiceAccounts, cmd.Flags().Lookup(flags.ServiceAccounts)) - viper.BindPFlag(flags.Name, cmd.Flags().Lookup(flags.Name)) - }, - Run: func(cmd *cobra.Command, args []string) { - namespace.RemoveServiceAccounts() - }, - } +func createNamespaceServiceAccountsRemoveCommand(o *namespace.Orchestrator, cmd cli.Command) { + namespaceServiceAccountRemoveCmd := cmd.AddCommand("remove", "Removes users from a namespace", + "Use this command to remove service-accounts from an existing k8s namespace.", func() { + o.RemoveServiceAccounts() + }) - addServiceAccountsPersistentFlag(command) - command.MarkPersistentFlagRequired(flags.ServiceAccounts) - return command + addServiceAccountsParam(namespaceServiceAccountRemoveCmd) } -func createNamespaceServiceAccountsListCommand() *cobra.Command { - var command = &cobra.Command{ - Use: "list", - Short: "List service-accounts of a namespace", - Long: "Use this command to list service-accounts of an existing k8s namespace.", - PreRun: func(cmd *cobra.Command, args []string) { - viper.BindPFlag(flags.Name, cmd.Flags().Lookup(flags.Name)) - }, - Run: func(cmd *cobra.Command, args []string) { - namespace.ListServiceAccounts() - }, - } - return command +func createNamespaceServiceAccountsListCommand(o *namespace.Orchestrator, cmd cli.Command) { + cmd.AddCommand("list", "List service-accounts of a namespace", + "Use this command to list service-accounts of an existing k8s namespace.", func() { + o.ListServiceAccounts() + }) } -func addUsersPersistentFlag(command *cobra.Command) { - command.PersistentFlags().StringP(flags.Users, "u", "", "The email-addresses of the admin "+ +func addUsersParam(cmd cli.Command) { + cmd.AddPersistentParameterString(flags.Users, "", true, "u", "The email-addresses of the admin "+ "users of the namespace. Must be identical to Azure AD (case-sensitive). "+ "You can specify multiple users separated by commas.") } -func addServiceAccountsPersistentFlag(command *cobra.Command) { - command.PersistentFlags().StringP(flags.ServiceAccounts, "s", "", "Optionally, you can specify service accounts "+ - "which will be granted idential access level like the users. Each service accounts has to be in "+ +func addServiceAccountsParam(cmd cli.Command) { + cmd.AddPersistentParameterString(flags.ServiceAccounts, "", false, "s", "Optionally, you can specify service accounts "+ + "which will be granted identical access level like the users. Each service accounts has to be in "+ "the format accountname.namespace, and multiple accounts can be specified separated by commas.") } + +func addNameParam(cmd cli.Command) { + cmd.AddPersistentParameterString(flags.Name, "", true, "n", "Name of the namespace") +} diff --git a/cmd/copsctl/root.go b/cmd/copsctl/root.go deleted file mode 100644 index 14172b5..0000000 --- a/cmd/copsctl/root.go +++ /dev/null @@ -1,64 +0,0 @@ -package main - -import ( - "github.com/conplementAG/copsctl/internal/cmd/flags" - "os" - "strings" - - "github.com/conplementAG/copsctl/internal/common/logging" - "github.com/spf13/cobra" - "github.com/spf13/viper" -) - -// rootCmd represents the base command when called without any subcommands -var rootCmd = &cobra.Command{ - Use: "copsctl", - Short: "copsctl - the Conplement AG Kubernetes developer tooling", - Long: ` - - _ _ - ___ ___ _ __ ___ ___| |_| | - / __/ _ \| '_ \/ __|/ __| __| | - | (_| (_) | |_) \__ \ (__| |_| | - \___\___/| .__/|___/\___|\__|_| - |_| by Conplement AG - - Version 0.8.4 - `, - - Version: "0.8.4", -} - -// Execute adds all child commands to the root command and sets flags appropriately. -// This is called by main.main(). It only needs to happen once to the rootCmd. -func Execute() { - if err := rootCmd.Execute(); err != nil { - panic(err) - } -} - -func init() { - cobra.OnInitialize(initConfig) - - // Here you will define your flags and configuration settings. - // Cobra supports persistent flags, which, if defined here, - // will be global for your application. - rootCmd.AddCommand(createNamespaceCommand()) - rootCmd.AddCommand(createClusterInfoCommand()) - rootCmd.AddCommand(createConnectCommand()) - rootCmd.AddCommand(createAzureDevopsCommand()) - - rootCmd.PersistentFlags().BoolP(flags.Verbose, "v", false, "If set logging will be verbose") - viper.BindPFlag(flags.Verbose, rootCmd.PersistentFlags().Lookup(flags.Verbose)) -} - -func initConfig() { - viper.AutomaticEnv() // read in environment variables that match - - logging.Initialize() - - logging.Debug("=============================================") - logging.Debug("=============== copsctl ===============") - logging.Debug("=============================================") - logging.Debug("Command " + strings.Join(os.Args, " ")) -} diff --git a/go.mod b/go.mod index c6562c5..7346b69 100644 --- a/go.mod +++ b/go.mod @@ -4,40 +4,44 @@ go 1.18 require ( github.com/ahmetb/go-linq v3.0.0+incompatible - github.com/briandowns/spinner v1.12.0 - github.com/imroc/req v0.3.0 - github.com/mattn/go-colorable v0.1.8 + github.com/conplementag/cops-hq v1.0.0 + github.com/imroc/req v0.3.2 github.com/mitchellh/go-homedir v1.1.0 - github.com/rs/xid v1.2.1 - github.com/sirupsen/logrus v1.7.0 - github.com/spf13/cobra v1.1.1 - github.com/spf13/viper v1.7.1 - github.com/x-cray/logrus-prefixed-formatter v0.5.2 - gopkg.in/natefinch/lumberjack.v2 v2.0.0 + github.com/rs/xid v1.4.0 + github.com/sirupsen/logrus v1.9.0 + github.com/spf13/viper v1.13.0 gopkg.in/yaml.v2 v2.4.0 ) require ( - github.com/fatih/color v1.10.0 // indirect - github.com/fsnotify/fsnotify v1.4.9 // indirect + github.com/Masterminds/semver v1.5.0 // indirect + github.com/briandowns/spinner v1.19.0 // indirect + github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect + github.com/fatih/color v1.13.0 // indirect + github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/inconshreveable/mousetrap v1.0.0 // indirect - github.com/magiconair/properties v1.8.4 // indirect - github.com/mattn/go-isatty v0.0.12 // indirect + github.com/inconshreveable/mousetrap v1.0.1 // indirect + github.com/magiconair/properties v1.8.6 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.16 // indirect github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect - github.com/mitchellh/mapstructure v1.4.1 // indirect - github.com/onsi/ginkgo v1.12.2 // indirect - github.com/onsi/gomega v1.10.1 // indirect - github.com/pelletier/go-toml v1.8.1 // indirect - github.com/spf13/afero v1.5.1 // indirect - github.com/spf13/cast v1.3.1 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/nxadm/tail v1.4.8 // indirect + github.com/pelletier/go-toml v1.9.5 // indirect + github.com/pelletier/go-toml/v2 v2.0.5 // indirect + github.com/snowzach/rotatefilehook v0.0.0-20220211133110-53752135082d // indirect + github.com/spf13/afero v1.9.2 // indirect + github.com/spf13/cast v1.5.0 // indirect + github.com/spf13/cobra v1.5.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/subosito/gotenv v1.2.0 // indirect - golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 // indirect - golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f // indirect - golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e // indirect + github.com/subosito/gotenv v1.4.1 // indirect + github.com/x-cray/logrus-prefixed-formatter v0.5.2 // indirect + golang.org/x/crypto v0.0.0-20220924013350-4ba4fb4dd9e7 // indirect + golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8 // indirect + golang.org/x/term v0.0.0-20220919170432-7a66f970e087 // indirect golang.org/x/text v0.3.7 // indirect - golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect - gopkg.in/ini.v1 v1.62.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 3b337c6..6204f6e 100644 --- a/go.sum +++ b/go.sum @@ -3,254 +3,250 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/ahmetb/go-linq v3.0.0+incompatible h1:qQkjjOXKrKOTy83X8OpRmnKflXKQIL/mC/gMVVDMhOA= github.com/ahmetb/go-linq v3.0.0+incompatible/go.mod h1:PFffvbdbtw+QTB0WKRP0cNht7vnCfnGlEpak/DVg5cY= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/briandowns/spinner v1.12.0 h1:72O0PzqGJb6G3KgrcIOtL/JAGGZ5ptOMCn9cUHmqsmw= -github.com/briandowns/spinner v1.12.0/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/briandowns/spinner v1.19.0 h1:s8aq38H+Qju89yhp89b4iIiMzMm8YN3p6vGpwyh/a8E= +github.com/briandowns/spinner v1.19.0/go.mod h1:mQak9GHqbspjC/5iUx3qMlIho8xBS/ppAL/hX5SmPJU= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be h1:J5BL2kskAlV9ckgEsNQXscjIaLiOYiZ75d4e94E6dcQ= +github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be/go.mod h1:mk5IQ+Y0ZeO87b858TlA645sVcEcbiX6YqP98kt+7+w= +github.com/conplementag/cops-hq v1.0.0 h1:GkZFkIePFvUODuprt8jpD+ChmOh8MBzwnxBE70jgIWM= +github.com/conplementag/cops-hq v1.0.0/go.mod h1:7LuC9TYk/sm9Uk6/aJug4kb2Nhwx0BGuras7vEQBUuo= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg= -github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/imroc/req v0.3.0 h1:3EioagmlSG+z+KySToa+Ylo3pTFZs+jh3Brl7ngU12U= -github.com/imroc/req v0.3.0/go.mod h1:F+NZ+2EFSo6EFXdeIbpfE9hcC233id70kf0byW97Caw= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imroc/req v0.3.2 h1:M/JkeU6RPmX+WYvT2vaaOL0K+q8ufL5LxwvJc4xeB4o= +github.com/imroc/req v0.3.2/go.mod h1:F+NZ+2EFSo6EFXdeIbpfE9hcC233id70kf0byW97Caw= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= +github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.4 h1:8KGKTcQQGm0Kv7vEbKFErAoAOFyyacLStRtQSeYtvkY= -github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= +github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.12.2 h1:Ke9m3h2Hu0wsZ45yewCqhYr3Z+emcNTuLY2nMWCkrSI= -github.com/onsi/ginkgo v1.12.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM= -github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= +github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rs/xid v1.2.1 h1:mhH9Nq+C1fY2l1XIpgxIiUOfNpRBYH1kKcr+qfKgjRc= -github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.5.1 h1:VHu76Lk0LSP1x254maIu2bplkWpfBWI+B+6fdoZprcg= -github.com/spf13/afero v1.5.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4= -github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY= +github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/snowzach/rotatefilehook v0.0.0-20220211133110-53752135082d h1:4660u5vJtsyrn3QwJNfESwCws+TM1CMhRn123xjVyQ8= +github.com/snowzach/rotatefilehook v0.0.0-20220211133110-53752135082d/go.mod h1:ZLVe3VfhAuMYLYWliGEydMBoRnfib8EFSqkBYu1ck9E= +github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw= +github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= +github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= +github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU= +github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk= -github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.13.0 h1:BWSJ/M+f+3nmdz9bxB+bWX28kkALN2ok11D0rSo8EJU= +github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= +github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJzfthRT6usrui8uGmg= github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 h1:7KByu05hhLed2MO29w7p1XfZvZ13m8mub3shuVftRs0= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220924013350-4ba4fb4dd9e7 h1:WJywXQVIb56P2kAvXeMGTIgQ1ZHQxR60+F9dLsodECc= +golang.org/x/crypto v0.0.0-20220924013350-4ba4fb4dd9e7/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -260,17 +256,22 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -279,24 +280,48 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2 h1:NWy5+hlRbC7HK+PmcXVUmW1IMyFce7to56IUvhUFm7Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -305,54 +330,131 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e h1:CsOuNlbOuf0mzxJIefr6Q4uAUetRUwZE4qt7VfzP+xo= -golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8 h1:h+EGohizhe9XlX18rfpa8k8RAc5XyaeamM+0VHRd4lc= +golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20220919170432-7a66f970e087 h1:tPwmk4vmvVCMdr98VgL4JH+qZxPL8fqlUOHnyOM8N3w= +golang.org/x/term v0.0.0-20220919170432-7a66f970e087/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f h1:uF6paiQQebLeSXkrTqHqz0MXhXXS1KgF41eUdBNvxK0= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -362,39 +464,82 @@ google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/internal/adapters/azure_devops/endpoints.go b/internal/adapters/azure_devops/endpoints.go index 3d94005..17d8e18 100644 --- a/internal/adapters/azure_devops/endpoints.go +++ b/internal/adapters/azure_devops/endpoints.go @@ -1,37 +1,21 @@ package azure_devops -import "log" +import ( + "github.com/sirupsen/logrus" +) -func CreateServiceEndpoint(username string, accesstoken string, name string, organization string, project string, masterPlaneFqdn string, token string, certificate string) { - existingEndpointId := getEndpointId(username, accesstoken, name, organization, project) +func CreateServiceEndpoint(username string, accessToken string, name string, organization string, project string, masterPlaneFqdn string, token string, certificate string) { + existingEndpointId := getEndpointId(username, accessToken, name, organization, project) if existingEndpointId != "" { - log.Println("Endpoint with name " + name + " in " + organization + ", project " + project + " already exists. Connection will be updated") - updateEndpoint(username, accesstoken, existingEndpointId, name, organization, project, masterPlaneFqdn, token, certificate) + logrus.Println("Endpoint with name " + name + " in " + organization + ", project " + project + " already exists. Connection will be updated") + updateEndpoint(username, accessToken, existingEndpointId, name, organization, project, masterPlaneFqdn, token, certificate) } else { - createEndpoint(username, accesstoken, name, organization, project, masterPlaneFqdn, token, certificate) + createEndpoint(username, accessToken, name, organization, project, masterPlaneFqdn, token, certificate) } } -func RemoveServiceEndpoint(username string, accesstoken string, name string, organization string, project string) { - endpoints := searchForEndpoint(username, accesstoken, name, organization, project) - if len(endpoints.Value) > 1 { - panic("Endpoint delete cannot be performed since multiple endpoints with the name have been found.") - } - - if len(endpoints.Value) == 0 { - // nothing to delete, all good - return - } - - endpointId := endpoints.Value[0].ID - - deleteEndpoint(username, accesstoken, endpointId, organization, project) - - log.Println("Azure DevOps endpoint " + name + " deleted, organization " + organization + ", project " + project) -} - -func getEndpointId(username string, accesstoken string, name string, organization string, project string) string { - response := searchForEndpoint(username, accesstoken, name, organization, project) +func getEndpointId(username string, accessToken string, name string, organization string, project string) string { + response := searchForEndpoint(username, accessToken, name, organization, project) endpointId := "" if len(response.Value) > 0 { endpointId = response.Value[0].ID diff --git a/internal/adapters/azure_devops/http.go b/internal/adapters/azure_devops/http.go index 66bc2ac..80a4c5f 100644 --- a/internal/adapters/azure_devops/http.go +++ b/internal/adapters/azure_devops/http.go @@ -4,16 +4,15 @@ import ( "encoding/base64" "fmt" "github.com/conplementAG/copsctl/internal/cmd/flags" - "log" - "github.com/imroc/req" + "github.com/sirupsen/logrus" "github.com/spf13/viper" ) func prepareHeaders(username string, accessToken string) req.Header { if viper.GetBool(flags.Verbose) { - log.Println("Using username: " + username) - log.Println("Using token: " + accessToken) + logrus.Println("Using username: " + username) + logrus.Println("Using token: " + accessToken) } headers := make(map[string]string) @@ -34,8 +33,8 @@ func buildBaseUrl(organization string, project string) string { return "https://dev.azure.com/" + organization + "/" + project + "/_apis/serviceendpoint/endpoints" } -func searchForEndpoint(username string, accesstoken string, name string, organization string, project string) endpointsByNameQueryResponse { - headers := prepareHeaders(username, accesstoken) +func searchForEndpoint(username string, accessToken string, name string, organization string, project string) endpointsByNameQueryResponse { + headers := prepareHeaders(username, accessToken) param := req.QueryParam{ "api-version": "5.0-preview.2", @@ -48,7 +47,7 @@ func searchForEndpoint(username string, accesstoken string, name string, organiz r, err := req.Get(reqUrl, headers, param) if viper.GetBool(flags.Verbose) { - log.Printf("%+v", r) + logrus.Printf("%+v", r) } if err != nil { @@ -72,32 +71,6 @@ func searchForEndpoint(username string, accesstoken string, name string, organiz return response } -func deleteEndpoint(username string, accessToken string, endpointId string, organization string, project string) { - header := prepareHeaders(username, accessToken) - - param := req.QueryParam{ - "api-version": "5.0-preview.2", - } - - reqUrl := buildBaseUrl(organization, project) + "/" + endpointId - - r, err := req.Delete(reqUrl, header, param) - - if viper.GetBool(flags.Verbose) { - log.Printf("%+v", r) - } - - if err != nil { - panic(err) - } - - statusCode := r.Response().StatusCode - - if statusCode != 204 { - panic(fmt.Sprintf("[Endpoint Delete] HTTP request failed with status code %d", statusCode)) - } -} - func createEndpoint(username string, accessToken string, name string, organization string, project string, kubernetesMasterUrl string, token string, certificate string) { headers := prepareHeaders(username, accessToken) @@ -124,7 +97,7 @@ func createEndpoint(username string, accessToken string, name string, organizati r, err := req.Post(reqUrl, headers, param, body) if viper.GetBool(flags.Verbose) { - log.Printf("%+v", r) + logrus.Printf("%+v", r) } if err != nil { @@ -165,7 +138,7 @@ func updateEndpoint(username string, accessToken string, endpointId string, name r, err := req.Put(reqUrl, headers, param, body) if viper.GetBool(flags.Verbose) { - log.Printf("%+v", r) + logrus.Printf("%+v", r) } if err != nil { diff --git a/internal/adapters/kubernetes/commands.go b/internal/adapters/kubernetes/commands.go index ed8dd00..b26fea8 100644 --- a/internal/adapters/kubernetes/commands.go +++ b/internal/adapters/kubernetes/commands.go @@ -2,23 +2,17 @@ package kubernetes import ( "encoding/json" + "github.com/conplementag/cops-hq/pkg/commands" + "github.com/sirupsen/logrus" "strings" "github.com/ahmetb/go-linq" - "github.com/conplementAG/copsctl/internal/common/commands" "github.com/conplementAG/copsctl/internal/common/file_processing" - "github.com/conplementAG/copsctl/internal/common/logging" ) -func UseContext(contextName string) error { - command := "kubectl config use-context " + contextName - _, err := commands.ExecuteCommand(commands.Create(command)) - return err -} - -func GetCurrentConfig() (*ConfigResponse, error) { +func GetCurrentConfig(executor commands.Executor) (*ConfigResponse, error) { command := "kubectl config view -o json" - out, err := commands.ExecuteCommand(commands.Create(command)) + out, err := executor.Execute(command) if err != nil { return nil, err @@ -29,21 +23,21 @@ func GetCurrentConfig() (*ConfigResponse, error) { return config, nil } -func PrintAllCopsNamespaces() error { +func PrintAllCopsNamespaces(executor commands.Executor) error { command := "kubectl get copsnamespaces" - out, err := commands.ExecuteCommand(commands.Create(command)) + out, err := executor.Execute(command) if err != nil { return err } - logging.Info("\nNamespaces:\n" + out) + logrus.Info("\nNamespaces:\n" + out) return nil } -func GetCopsNamespace(namespace string) (*CopsNamespaceResponse, error) { +func GetCopsNamespace(executor commands.Executor, namespace string) (*CopsNamespaceResponse, error) { command := "kubectl get CopsNamespace " + namespace + " -o json" - out, err := commands.ExecuteCommand(commands.Create(command)) + out, err := executor.Execute(command) if err != nil { return nil, err @@ -54,37 +48,37 @@ func GetCopsNamespace(namespace string) (*CopsNamespaceResponse, error) { return response, nil } -func Apply(filepath string) (string, error) { +func Apply(executor commands.Executor, filepath string) (string, error) { command := "kubectl apply -f " + filepath - return commands.ExecuteCommandLongRunning(commands.Create(command)) + return executor.ExecuteWithProgressInfo(command) } -func Delete(filepath string) (string, error) { +func Delete(executor commands.Executor, filepath string) (string, error) { command := "kubectl delete --wait -f " + filepath - return commands.ExecuteCommandLongRunning(commands.Create(command)) + return executor.ExecuteWithProgressInfo(command) } -func ApplyString(content string) (string, error) { +func ApplyString(executor commands.Executor, content string) (string, error) { temporaryDirectory, temporaryFile := file_processing.WriteStringToTemporaryFile(content, "resource.yaml") defer file_processing.DeletePath(temporaryDirectory) - return Apply(temporaryFile) + return Apply(executor, temporaryFile) } -func DeleteString(content string) (string, error) { +func DeleteString(executor commands.Executor, content string) (string, error) { temporaryDirectory, temporaryFile := file_processing.WriteStringToTemporaryFile(content, "resource.yaml") defer file_processing.DeletePath(temporaryDirectory) - return Delete(temporaryFile) + return Delete(executor, temporaryFile) } -func CanIGetPods(namespace string) bool { - data, err := commands.ExecuteCommandLongRunning(commands.Create("kubectl auth can-i get pods -n " + namespace)) +func CanIGetPods(executor commands.Executor, namespace string) bool { + data, err := executor.ExecuteWithProgressInfo("kubectl auth can-i get pods -n " + namespace) return err == nil && strings.TrimSuffix(data, "\n") == "yes" } -func GetCurrentMasterPlaneFqdn() (string, error) { - currentConfig, err := GetCurrentConfig() +func GetCurrentMasterPlaneFqdn(executor commands.Executor) (string, error) { + currentConfig, err := GetCurrentConfig(executor) if err != nil { return "", err @@ -100,21 +94,3 @@ func GetCurrentMasterPlaneFqdn() (string, error) { return currentClusterResponse.Cluster.Server, nil } - -func CreateServiceAccount(namespace string, accountName string) error { - command := "kubectl create serviceaccount " + accountName + " --namespace " + namespace - _, err := commands.ExecuteCommand(commands.Create(command)) - return err -} - -func RemoveServiceAccount(namespace string, accountName string) error { - command := "kubectl delete serviceaccount " + accountName + " --namespace " + namespace - _, err := commands.ExecuteCommand(commands.Create(command)) - return err -} - -func DeleteDeployment(deploymentName string, namespace string) error { - command := "kubectl delete deployment " + deploymentName + " -n " + namespace - _, err := commands.ExecuteCommand(commands.Create(command)) - return err -} diff --git a/internal/adapters/kubernetes/service_account.go b/internal/adapters/kubernetes/service_account.go index d667667..c64b5f8 100644 --- a/internal/adapters/kubernetes/service_account.go +++ b/internal/adapters/kubernetes/service_account.go @@ -1,12 +1,13 @@ package kubernetes import ( - "github.com/conplementAG/copsctl/internal/common/commands" + "fmt" + "github.com/conplementag/cops-hq/pkg/commands" "gopkg.in/yaml.v2" ) -func GetServiceAccount(namespace string, name string) ServiceAccount { - out, err := commands.ExecuteCommand(commands.Createf("kubectl get serviceaccount %s -n %s -o yaml --ignore-not-found", name, namespace)) +func GetServiceAccount(executor commands.Executor, namespace string, name string) ServiceAccount { + out, err := executor.Execute(fmt.Sprintf("kubectl get serviceaccount %s -n %s -o yaml --ignore-not-found", name, namespace)) if err != nil { panic("we should never get an err when using ignore-not-found " + err.Error()) diff --git a/internal/adapters/kubernetes/service_account_secret.go b/internal/adapters/kubernetes/service_account_secret.go index dab7020..2643c1c 100644 --- a/internal/adapters/kubernetes/service_account_secret.go +++ b/internal/adapters/kubernetes/service_account_secret.go @@ -1,12 +1,13 @@ package kubernetes import ( - "github.com/conplementAG/copsctl/internal/common/commands" + "fmt" + "github.com/conplementag/cops-hq/pkg/commands" "gopkg.in/yaml.v2" ) -func GetServiceAccountSecret(namespace string, name string) ServiceAccountSecret { - out, err := commands.ExecuteCommand(commands.Createf("kubectl get secret %s -n %s -o yaml --ignore-not-found", name, namespace)) +func GetServiceAccountSecret(executor commands.Executor, namespace string, name string) ServiceAccountSecret { + out, err := executor.Execute(fmt.Sprintf("kubectl get secret %s -n %s -o yaml --ignore-not-found", name, namespace)) if err != nil { panic("we should never get an err when using ignore-not-found " + err.Error()) diff --git a/internal/azure_devops/orchestrator.go b/internal/azure_devops/orchestrator.go index 0827d60..edf63f5 100644 --- a/internal/azure_devops/orchestrator.go +++ b/internal/azure_devops/orchestrator.go @@ -3,6 +3,9 @@ package azure_devops import ( "embed" "github.com/conplementAG/copsctl/internal/cmd/flags" + "github.com/conplementag/cops-hq/pkg/commands" + "github.com/conplementag/cops-hq/pkg/hq" + "github.com/sirupsen/logrus" "strings" "time" @@ -11,12 +14,12 @@ import ( "github.com/conplementAG/copsctl/internal/adapters/azure_devops" "github.com/conplementAG/copsctl/internal/adapters/kubernetes" "github.com/conplementAG/copsctl/internal/common/file_processing" - "github.com/conplementAG/copsctl/internal/common/logging" "github.com/spf13/viper" ) // see https://pkg.go.dev/embed +// //go:embed global/* var globalYamls embed.FS @@ -24,6 +27,8 @@ var globalYamls embed.FS var scopedYamls embed.FS type AzureDevopsOrchestrator struct { + hq hq.HQ + executor commands.Executor Organization string Project string Namespace string @@ -32,10 +37,10 @@ type AzureDevopsOrchestrator struct { roleName string endpointName string username string - accesstoken string + accessToken string } -func NewOrchestrator() *AzureDevopsOrchestrator { +func New(hq hq.HQ) *AzureDevopsOrchestrator { environmentTag := viper.GetString(flags.EnvironmentTag) organization := viper.GetString(flags.Organization) project := viper.GetString(flags.Project) @@ -50,6 +55,8 @@ func NewOrchestrator() *AzureDevopsOrchestrator { } return &AzureDevopsOrchestrator{ + hq: hq, + executor: hq.GetExecutor(), Organization: trim(organization), Project: trim(project), Namespace: trim(namespace), @@ -59,7 +66,7 @@ func NewOrchestrator() *AzureDevopsOrchestrator { roleName: strings.ToLower(urlDecode(organization)) + "-" + strings.ToLower(urlDecode(project)) + "-" + trim(namespace) + "-azuredevops-role", endpointName: trim(environmentTag) + "-" + trim(namespace), username: trim(username), - accesstoken: trim(accessToken), + accessToken: trim(accessToken), } } @@ -73,19 +80,19 @@ func trim(source string) string { } func (orchestrator *AzureDevopsOrchestrator) ConfigureEndpoint() { - logging.Info("Connecting the current k8s cluster with an Azure DevOps account...") + logrus.Info("Connecting the current k8s cluster with an Azure DevOps account...") if orchestrator.globalScope { - logging.Info("RBAC will be without limitation, since no 'namespace' was specified, and the RBAC resources will be in kube-system") + logrus.Info("RBAC will be without limitation, since no 'namespace' was specified, and the RBAC resources will be in kube-system") } else { - logging.Info("RBAC will be scoped to namespace " + orchestrator.Namespace) + logrus.Info("RBAC will be scoped to namespace " + orchestrator.Namespace) } - logging.Info("Creating the RBAC resources") + logrus.Info("Creating the RBAC resources") outputPath := orchestrator.prepareRbacFiles() - _, err := kubernetes.Apply(outputPath) + _, err := kubernetes.Apply(orchestrator.executor, outputPath) if err != nil { panic("Apply failed: " + err.Error()) @@ -93,21 +100,21 @@ func (orchestrator *AzureDevopsOrchestrator) ConfigureEndpoint() { file_processing.DeletePath(outputPath) - logging.Info("Setting up the Azure DevOps connection...") + logrus.Info("Setting up the Azure DevOps connection...") // sleep a bit to make sure the secret is created time.Sleep(3 * time.Second) // first, get the token, the certificate of the created service account and the master plane FQDN - serviceAccount := kubernetes.GetServiceAccount(orchestrator.Namespace, orchestrator.serviceAccountName) + serviceAccount := kubernetes.GetServiceAccount(orchestrator.executor, orchestrator.Namespace, orchestrator.serviceAccountName) if len(serviceAccount.Secrets) != 1 { panic("Expected the service account to contain exactly one secret (where the token and cert are located)") } - serviceAccountSecret := kubernetes.GetServiceAccountSecret(orchestrator.Namespace, serviceAccount.Secrets[0].Name) + serviceAccountSecret := kubernetes.GetServiceAccountSecret(orchestrator.executor, orchestrator.Namespace, serviceAccount.Secrets[0].Name) - masterPlaneFqdn, err := kubernetes.GetCurrentMasterPlaneFqdn() + masterPlaneFqdn, err := kubernetes.GetCurrentMasterPlaneFqdn(orchestrator.executor) if err != nil { panic("Could not get the master plane fqdn " + err.Error()) @@ -116,7 +123,7 @@ func (orchestrator *AzureDevopsOrchestrator) ConfigureEndpoint() { // now we can create the endpoint (aka. service connection / service endpoint) azure_devops.CreateServiceEndpoint( orchestrator.username, - orchestrator.accesstoken, + orchestrator.accessToken, orchestrator.endpointName, orchestrator.Organization, orchestrator.Project, diff --git a/internal/cluster_info/orchestrator.go b/internal/cluster_info/orchestrator.go index 11b5362..e635931 100644 --- a/internal/cluster_info/orchestrator.go +++ b/internal/cluster_info/orchestrator.go @@ -4,29 +4,41 @@ import ( "encoding/json" "fmt" "github.com/conplementAG/copsctl/internal/cmd/flags" - "github.com/conplementAG/copsctl/internal/common/commands" - "github.com/conplementAG/copsctl/internal/common/logging" + "github.com/conplementag/cops-hq/pkg/commands" + "github.com/conplementag/cops-hq/pkg/hq" + "github.com/sirupsen/logrus" "github.com/spf13/viper" "strings" ) -func ShowClusterInfo() { +type Orchestrator struct { + hq hq.HQ + executor commands.Executor +} + +func New(hq hq.HQ) *Orchestrator { + return &Orchestrator{ + hq: hq, + executor: hq.GetExecutor(), + } +} + +func (o *Orchestrator) ShowClusterInfo() { printConfigSilenceEverythingElse := viper.GetBool(flags.PrintToStdoutSilenceEverythingElse) if !printConfigSilenceEverythingElse { - logging.Info("Reading the cluster info ...") - logging.Info("NOTE: you can use the " + flags.PrintToStdoutSilenceEverythingElse + " flag to silence these outputs (useful for automation)") + logrus.Info("Reading the cluster info ...") + logrus.Info("NOTE: you can use the " + flags.PrintToStdoutSilenceEverythingElse + " flag to silence these outputs (useful for automation)") - logging.Info("===========================================================") - logging.Info("==================== Cluster Info: =======================") - logging.Info("===========================================================") + logrus.Info("===========================================================") + logrus.Info("==================== Cluster Info: =======================") + logrus.Info("===========================================================") } - command := "kubectl get configmap -n coreops-public -o jsonpath=\"{.data['info\\.json']}\" coreops-cluster-info" - result, err := commands.ExecuteCommand(commands.Create(command)) + result, err := o.executor.Execute("kubectl get configmap -n coreops-public -o jsonpath=\"{.data['info\\.json']}\" coreops-cluster-info") if err != nil { - logging.Errorf(err.Error()) + logrus.Errorf(err.Error()) panic(err) } @@ -45,7 +57,7 @@ func ShowClusterInfo() { indented, err := json.MarshalIndent(mapResult, "", " ") if err != nil { - logging.Errorf(err.Error()) + logrus.Errorf(err.Error()) panic(err) } diff --git a/internal/common/commands/commands.go b/internal/common/commands/commands.go deleted file mode 100644 index b250233..0000000 --- a/internal/common/commands/commands.go +++ /dev/null @@ -1,84 +0,0 @@ -package commands - -import ( - "fmt" - "os/exec" - "strings" -) - -const SPACE_WITHIN_QUOTE = "{SPACE_WITHIN_QUOTE}" -const DOUBLE_QUOTE = "{DOUBLE_QUOTE}" - -// Create creates a command from a single string -// This allows you to pass parameters which include spaces as commands. -// You just need to add "double-quotes" around the parameter and it will be treated as one parameter and not be splitted by whitespace. -func Create(plainCommand string) *exec.Cmd { - /* - Example - plainCommand : az role assignment create --role "Network Contributer" --assignee ABC --scope abc - escapedCommand : az role assignment create --role "Network{SPACE_WITHIN_QUOTE}Contributer" --assignee ABC --scope abc - commandParts : ["az", "role", "assignment", "create", "--role", "Network Contributer", "--assignee", "ABC", "--scope", "abc"] - */ - escapedCommand := markQuotedSpaces(plainCommand) - commandParts := handleSpacesInQuotes(strings.Fields(escapedCommand)) - - var cmd *exec.Cmd - - if len(commandParts) > 1 { - cmd = exec.Command(commandParts[0], commandParts[1:]...) - } else { - cmd = exec.Command(commandParts[0]) - } - - return cmd -} - -// Createf creates a command from a formatted input string -func Createf(format string, args ...interface{}) *exec.Cmd { - actualCommand := fmt.Sprintf(format, args...) - return Create(actualCommand) -} - -func markQuotedSpaces(plainCommand string) string { - escapeMode := false - var escapedCommand strings.Builder - enteredEscapeModeInThisIteration := false - - for _, char := range plainCommand { - - // Enter Escape Mode when " occurrs - if !escapeMode && string(char) == "\"" { - escapeMode = true - enteredEscapeModeInThisIteration = true - } - - // Handle spaces when in Escape Mode - if escapeMode && string(char) == " " { - escapedCommand.WriteString(SPACE_WITHIN_QUOTE) - } else if escapeMode && string(char) == "\"" { - escapedCommand.WriteString(DOUBLE_QUOTE) - } else { - escapedCommand.WriteRune(char) - } - - // Exit Escape Mode when " occurrs - if !enteredEscapeModeInThisIteration && escapeMode && string(char) == "\"" { - escapeMode = false - } - - enteredEscapeModeInThisIteration = false - } - return escapedCommand.String() -} - -func handleSpacesInQuotes(parts []string) []string { - handledParts := make([]string, len(parts)) - - for pos, part := range parts { - newPartWithSpaces := strings.Replace(part, SPACE_WITHIN_QUOTE, " ", -1) - newPartWithoutQuotes := strings.Replace(newPartWithSpaces, DOUBLE_QUOTE, "", -1) - handledParts[pos] = newPartWithoutQuotes - } - - return handledParts -} diff --git a/internal/common/commands/execute.go b/internal/common/commands/execute.go deleted file mode 100644 index 546843f..0000000 --- a/internal/common/commands/execute.go +++ /dev/null @@ -1,95 +0,0 @@ -package commands - -import ( - "bytes" - "io" - "os" - "os/exec" - "strings" - "sync" - "time" - - "github.com/briandowns/spinner" - "github.com/conplementAG/copsctl/internal/common/logging" -) - -// ExecuteCommandLongRunning runs the given command and starts -// a async spinner to tell the user to be patient -func ExecuteCommandLongRunning(command *exec.Cmd) (string, error) { - spinner := spinner.New(spinner.CharSets[9], 100*time.Millisecond) - spinner.Prefix = "Please wait " - spinner.Color("green", "bold") - spinner.Start() - - result, err := ExecuteCommand(command) - - spinner.Stop() - - return result, err -} - -func ExecuteCommand(command *exec.Cmd) (string, error) { - return execute(command, true) -} - -func ExecuteCommandWithSecretContents(command *exec.Cmd) (string, error) { - return execute(command, false) -} - -func execute(command *exec.Cmd, loggingEnabled bool) (string, error) { - command.Stdin = os.Stdin - - commandStdoutPipe, _ := command.StdoutPipe() - commandstderrPipe, _ := command.StderrPipe() - - var stdoutBuffer, stderrBuffer bytes.Buffer - stdoutMultiwriter := io.MultiWriter(newDebugLogWriter(loggingEnabled), &stdoutBuffer) - stderrMultiwriter := io.MultiWriter(newDebugLogWriter(loggingEnabled), &stderrBuffer) - - if loggingEnabled { - logging.Debugf("Executing: %s %s", command.Path, strings.Join(command.Args[1:], " ")) - } - - err := command.Start() - - if err != nil { - logging.Fatalf("cmd.Start() failed with '%s'\n", err) - } - - var multiWritingSteps sync.WaitGroup - multiWritingSteps.Add(2) - - go func() { - io.Copy(stdoutMultiwriter, commandStdoutPipe) - multiWritingSteps.Done() - }() - - go func() { - io.Copy(stderrMultiwriter, commandstderrPipe) - multiWritingSteps.Done() - }() - - commandReturnValue := command.Wait() - multiWritingSteps.Wait() - - outStr := string(stdoutBuffer.Bytes()) - return outStr, commandReturnValue -} - -type debugLogWriter struct { - enabled bool -} - -func newDebugLogWriter(enabled bool) *debugLogWriter { - return &debugLogWriter{ - enabled: enabled, - } -} - -func (w *debugLogWriter) Write(p []byte) (int, error) { - if w.enabled { - logging.Debug(string(p)) - } - - return len(p), nil -} diff --git a/internal/common/file_processing/file_processing.go b/internal/common/file_processing/file_processing.go index cd1533c..bb945f3 100644 --- a/internal/common/file_processing/file_processing.go +++ b/internal/common/file_processing/file_processing.go @@ -2,7 +2,7 @@ package file_processing import ( "embed" - "io/ioutil" + "io" "os" "path/filepath" "strings" @@ -11,11 +11,11 @@ import ( ) // WriteStringToTemporaryFile writes the file contents into a file on a temporary disk location -func WriteStringToTemporaryFile(fileContents string, filePath string) (outputfolder string, outputfile string) { +func WriteStringToTemporaryFile(fileContents string, filePath string) (outputFolder string, outputFile string) { outputFolderPath := createUniqueDirectory() generatedFilePath := filepath.Join(outputFolderPath, filePath) - err := ioutil.WriteFile(generatedFilePath, []byte(fileContents), 0644) + err := os.WriteFile(generatedFilePath, []byte(fileContents), 0644) panicOnError(err) return outputFolderPath, generatedFilePath @@ -40,14 +40,14 @@ func InterpolateStaticFiles(inputPathFs embed.FS, inputPathRootFolderName string for _, file := range directory { f, err := inputPathFs.Open(inputPathRootFolderName + "/" + file.Name()) panicOnError(err) - filesContent, err := ioutil.ReadAll(f) + filesContent, err := io.ReadAll(f) panicOnError(err) fileContentString := string(filesContent) for key, value := range variables { fileContentString = strings.Replace(fileContentString, key, value, -1) } - err = ioutil.WriteFile(filepath.Join(uniqueOutputFolder, file.Name()), []byte(fileContentString), 0644) + err = os.WriteFile(filepath.Join(uniqueOutputFolder, file.Name()), []byte(fileContentString), 0644) panicOnError(err) } diff --git a/internal/common/logging/logging.go b/internal/common/logging/logging.go deleted file mode 100644 index 85e7f40..0000000 --- a/internal/common/logging/logging.go +++ /dev/null @@ -1,95 +0,0 @@ -package logging - -import ( - "github.com/conplementAG/copsctl/internal/cmd/flags" - "os" - "time" - - "github.com/sirupsen/logrus" - "github.com/spf13/viper" - "gopkg.in/natefinch/lumberjack.v2" - - "github.com/mattn/go-colorable" - prefixed "github.com/x-cray/logrus-prefixed-formatter" -) - -var ( - file *os.File - consoleLogger *logrus.Logger - fileLogger *logrus.Logger -) - -func Initialize() { - consoleLogger = logrus.New() - fileLogger = logrus.New() - - fileLogger.SetLevel(logrus.DebugLevel) - consoleLogger.SetLevel(logrus.InfoLevel) - - if viper.GetBool(flags.Verbose) { - consoleLogger.SetLevel(logrus.DebugLevel) - } - - consoleLogger.SetFormatter(&prefixed.TextFormatter{ - ForceColors: true, - ForceFormatting: true, - FullTimestamp: true, - TimestampFormat: time.RFC822, - }) - - fileLogger.SetFormatter(&prefixed.TextFormatter{ - DisableColors: true, - ForceFormatting: true, - FullTimestamp: true, - TimestampFormat: time.RFC822, - }) - - fileLog := &lumberjack.Logger{ - Filename: "copsctl.log", - MaxSize: 10, - MaxBackups: 10, - LocalTime: true, - } - - consoleLogger.SetOutput(colorable.NewColorableStdout()) - fileLogger.SetOutput(fileLog) -} - -func Dispose() { - file.Close() -} - -func Info(text string) { - consoleLogger.Info(text) - fileLogger.Info(text) -} - -func Infof(text string, v ...interface{}) { - consoleLogger.Infof(text, v...) - fileLogger.Infof(text, v...) -} - -func Debug(text string) { - consoleLogger.Debug(text) - fileLogger.Debug(text) -} - -func Debugf(text string, v ...interface{}) { - consoleLogger.Debugf(text, v...) - fileLogger.Debugf(text, v...) -} - -func Fatalf(text string, v ...interface{}) { - consoleLogger.Fatalf(text, v...) - fileLogger.Fatalf(text, v...) -} - -func Error(text string) { - consoleLogger.Error(text) - fileLogger.Error(text) -} - -func Errorf(text string, v ...interface{}) { - consoleLogger.Errorf(text, v...) - fileLogger.Errorf(text, v...) -} diff --git a/internal/connection/helpers.go b/internal/connection/helpers.go index 87b6511..6e1be51 100644 --- a/internal/connection/helpers.go +++ b/internal/connection/helpers.go @@ -1,8 +1,7 @@ package connection import ( - "fmt" - "github.com/conplementAG/copsctl/internal/common/logging" + "github.com/sirupsen/logrus" "gopkg.in/yaml.v2" ) @@ -10,23 +9,13 @@ func marshalToYaml(input interface{}) string { output, err := yaml.Marshal(&input) if err != nil { - logging.Error("Error occurred while generating YAML for the interface. " + err.Error()) + logrus.Error("Error occurred while generating YAML for the interface. " + err.Error()) panic(err) } return string(output) } -func confirmOperation(message string) { - logging.Info(message) - var input string - fmt.Scanln(&input) - - if input != "yes" { - panic("operation aborted") - } -} - func panicOnError(err error) { if err != nil { panic(err) diff --git a/internal/connection/orchestrator.go b/internal/connection/orchestrator.go index 35505f8..e5d5e97 100644 --- a/internal/connection/orchestrator.go +++ b/internal/connection/orchestrator.go @@ -3,18 +3,30 @@ package connection import ( "fmt" "github.com/conplementAG/copsctl/internal/cmd/flags" - "github.com/conplementAG/copsctl/internal/common/commands" - "github.com/conplementAG/copsctl/internal/common/logging" + "github.com/conplementag/cops-hq/pkg/commands" + "github.com/conplementag/cops-hq/pkg/hq" "github.com/mitchellh/go-homedir" + "github.com/sirupsen/logrus" "github.com/spf13/viper" "gopkg.in/yaml.v2" "io" - "io/ioutil" "os" "path/filepath" ) -func Connect() { +type Orchestrator struct { + hq hq.HQ + executor commands.Executor +} + +func New(hq hq.HQ) *Orchestrator { + return &Orchestrator{ + hq: hq, + executor: hq.GetExecutor(), + } +} + +func (o *Orchestrator) Connect() { environmentTag := viper.GetString(flags.EnvironmentTag) connectionString := viper.GetString(flags.ConnectionString) isTechnicalAccount := viper.GetBool(flags.TechnicalAccount) @@ -24,13 +36,13 @@ func Connect() { validateConnectionString(connectionString, environmentTag, isTechnicalAccount) - blob := downloadBlob(connectionString) + blob := downloadBlob(o, connectionString) validateDownloadedBlob(blob, isTechnicalAccount) configs := parseConfigs(blob) if !printConfigSilenceEverythingElse { - logging.Info("Using configuration last modified at " + configs.ModifiedAt) + logrus.Info("Using configuration last modified at " + configs.ModifiedAt) } configYaml := marshalToYaml(configs.PrimaryKubeConfig) @@ -41,32 +53,38 @@ func Connect() { if printToStdout || printConfigSilenceEverythingElse { if !printConfigSilenceEverythingElse { - logging.Info("===========================================================") - logging.Info("You can either replace your config file in $HOME/.kube/config manually, or merge the files.") - logging.Info("Check for reference: https://stackoverflow.com/questions/46184125/how-to-merge-kubectl-config-file-with-kube-config") - logging.Info("===========================================================") - logging.Info("==================== Kube Config: ========================") - logging.Info("===========================================================") + logrus.Info("===========================================================") + logrus.Info("You can either replace your config file in $HOME/.kube/config manually, or merge the files.") + logrus.Info("Check for reference: https://stackoverflow.com/questions/46184125/how-to-merge-kubectl-config-file-with-kube-config") + logrus.Info("===========================================================") + logrus.Info("==================== Kube Config: ========================") + logrus.Info("===========================================================") } fmt.Println(configYaml) } else { + proceed := true if !viper.GetBool(flags.AutoApprove) { - confirmOperation("Proceeding will overwrite your local $HOME/.kube/config file. Your old config will be backed up, but the impact of " + + if !o.executor.AskUserToConfirm("Proceeding will overwrite your local $HOME/.kube/config file. Your old config will be backed up, but the impact of " + "this is that you will lose existing connections to other clusters. You can manually restore your connections by renaming the config " + "backup (in .kube directory) back to 'config' file name. Type 'yes' to proceed. You can also consider using the " + - flags.PrintToStdout + "flag to see instructions on merging the kube config files") + flags.PrintToStdout + "flag to see instructions on merging the kube config files") { + proceed = false + } } - saveKubeConfigToFile(configYaml) + if proceed { + saveKubeConfigToFile(configYaml) - logging.Info("Connection setup completed.") + logrus.Info("Connection setup completed.") + } else { + logrus.Warn("Connection setup aborted.") + } } } -func downloadBlob(connectionString string) string { - blob, err := commands.ExecuteCommandWithSecretContents( - commands.Create("curl -s --retry 3 " + connectionString)) +func downloadBlob(o *Orchestrator, connectionString string) string { + blob, err := o.executor.ExecuteSilent("curl -s --retry 3 " + connectionString) if err != nil { panic(err) @@ -101,7 +119,7 @@ func saveKubeConfigToFile(configYaml string) { copyFile(configFilePath, filepath.Join(home, ".kube", "copsctl_backup_config")) } - err = ioutil.WriteFile(configFilePath, []byte(configYaml), 0600) + err = os.WriteFile(configFilePath, []byte(configYaml), 0600) panicOnError(err) } diff --git a/internal/namespace/namespace.go b/internal/namespace/namespace.go index 625ba6e..a2a209f 100644 --- a/internal/namespace/namespace.go +++ b/internal/namespace/namespace.go @@ -2,61 +2,75 @@ package namespace import ( "github.com/conplementAG/copsctl/internal/cmd/flags" + "github.com/conplementag/cops-hq/pkg/commands" + "github.com/conplementag/cops-hq/pkg/hq" + "github.com/sirupsen/logrus" "time" "github.com/conplementAG/copsctl/internal/adapters/kubernetes" - "github.com/conplementAG/copsctl/internal/common/logging" "github.com/spf13/viper" ) -func List() { - kubernetes.PrintAllCopsNamespaces() +type Orchestrator struct { + hq hq.HQ + executor commands.Executor } -func Create() { +func New(hq hq.HQ) *Orchestrator { + return &Orchestrator{ + hq: hq, + executor: hq.GetExecutor(), + } +} + +func (o *Orchestrator) List() { + kubernetes.PrintAllCopsNamespaces(o.executor) +} + +func (o *Orchestrator) Create() { namespaceName := viper.GetString(flags.Name) users := parseUsernames(viper.GetString("users")) serviceAccounts := parseServiceAccounts(viper.GetString("service-accounts")) - copsnamespace := renderTemplate(namespaceName, users, serviceAccounts) + copsNamespace := renderTemplate(namespaceName, users, serviceAccounts) - _, err := kubernetes.ApplyString(copsnamespace) + _, err := kubernetes.ApplyString(o.executor, copsNamespace) if err != nil { panic("Apply failed: " + err.Error()) } - ensureNamespaceAccess(namespaceName) + ensureNamespaceAccess(o.executor, namespaceName) - logging.Infof("Cops namespace %s successfully created / updated.", namespaceName) + logrus.Infof("Cops namespace %s successfully created / updated.", namespaceName) } -func Delete() { +func (o *Orchestrator) Delete() { namespaceName := viper.GetString(flags.Name) - namespace, err := kubernetes.GetCopsNamespace(namespaceName) + namespace, err := kubernetes.GetCopsNamespace(o.executor, namespaceName) if err != nil { - logging.Infof("Cops namespace %s does not exist", namespaceName) + logrus.Infof("Cops namespace %s does not exist", namespaceName) return } - copsnamespace := renderTemplate(namespaceName, namespace.Spec.NamespaceAdminUsers, namespace.Spec.NamespaceAdminServiceAccounts) + copsNamespace := renderTemplate(namespaceName, namespace.Spec.NamespaceAdminUsers, namespace.Spec.NamespaceAdminServiceAccounts) - _, error := kubernetes.DeleteString(copsnamespace) + _, error := kubernetes.DeleteString(o.executor, copsNamespace) if error != nil { panic("Deleting copsnamespace failed: " + err.Error()) } - logging.Infof("Cops namespace %s successfully deleted", namespaceName) + logrus.Infof("Cops namespace %s successfully deleted", namespaceName) } -func ensureNamespaceAccess(namespace string) { +func ensureNamespaceAccess(executor commands.Executor, namespace string) { status := false for i := 0; i < 20; i++ { - status = kubernetes.CanIGetPods(namespace) + status = kubernetes.CanIGetPods(executor, namespace) if status == true { break } diff --git a/internal/namespace/serviceaccounts.go b/internal/namespace/serviceaccounts.go index a75afd4..213210a 100644 --- a/internal/namespace/serviceaccounts.go +++ b/internal/namespace/serviceaccounts.go @@ -2,10 +2,10 @@ package namespace import ( "github.com/conplementAG/copsctl/internal/cmd/flags" + "github.com/sirupsen/logrus" "strings" "github.com/conplementAG/copsctl/internal/adapters/kubernetes" - "github.com/conplementAG/copsctl/internal/common/logging" "github.com/spf13/viper" ) @@ -37,12 +37,12 @@ func parseServiceAccounts(rawAccounts string) []kubernetes.CopsServiceAccount { return parsedAccounts } -func AddServiceAccounts() { +func (o *Orchestrator) AddServiceAccounts() { namespaceName := viper.GetString(flags.Name) accounts := viper.GetString("service-accounts") newAccounts := parseServiceAccounts(accounts) - namespace, err := kubernetes.GetCopsNamespace(namespaceName) + namespace, err := kubernetes.GetCopsNamespace(o.executor, namespaceName) if err != nil { panic("Could not get the cops namespace " + err.Error()) @@ -69,23 +69,23 @@ func AddServiceAccounts() { } } - copsnamespace := renderTemplate(namespaceName, existingUsers, relevantAccounts) + copsNamespace := renderTemplate(namespaceName, existingUsers, relevantAccounts) - _, err = kubernetes.ApplyString(copsnamespace) + _, err = kubernetes.ApplyString(o.executor, copsNamespace) if err != nil { panic("Apply failed: " + err.Error()) } - logging.Infof("%d service account(s) have been successfully added to %s namespace", addedAccountsCount, namespaceName) + logrus.Infof("%d service account(s) have been successfully added to %s namespace", addedAccountsCount, namespaceName) } -func RemoveServiceAccounts() { +func (o *Orchestrator) RemoveServiceAccounts() { namespaceName := viper.GetString(flags.Name) accounts := viper.GetString("service-accounts") accountsToRemove := parseServiceAccounts(accounts) - namespace, err := kubernetes.GetCopsNamespace(namespaceName) + namespace, err := kubernetes.GetCopsNamespace(o.executor, namespaceName) if err != nil { panic("Could not get the cops namespace " + err.Error()) @@ -115,18 +115,18 @@ func RemoveServiceAccounts() { copsnamespace := renderTemplate(namespaceName, existingUsers, resultingAccounts) - _, err = kubernetes.ApplyString(copsnamespace) + _, err = kubernetes.ApplyString(o.executor, copsnamespace) if err != nil { panic("Apply failed: " + err.Error()) } - logging.Infof("%d service account(s) have been removed from the %s namespace", removedAccountsCount, namespaceName) + logrus.Infof("%d service account(s) have been removed from the %s namespace", removedAccountsCount, namespaceName) } -func ListServiceAccounts() { +func (o *Orchestrator) ListServiceAccounts() { namespaceName := viper.GetString(flags.Name) - namespace, err := kubernetes.GetCopsNamespace(namespaceName) + namespace, err := kubernetes.GetCopsNamespace(o.executor, namespaceName) if err != nil { panic("Could not get the cops namespace " + err.Error()) @@ -134,9 +134,9 @@ func ListServiceAccounts() { serviceAccounts := namespace.Spec.NamespaceAdminServiceAccounts - logging.Info("Current service accounts in the namespace " + namespaceName + ":") + logrus.Info("Current service accounts in the namespace " + namespaceName + ":") for _, sa := range serviceAccounts { - logging.Info(" - " + sa.ServiceAccount + "." + sa.Namespace) + logrus.Info(" - " + sa.ServiceAccount + "." + sa.Namespace) } } diff --git a/internal/namespace/users.go b/internal/namespace/users.go index 1cce2f2..8401418 100644 --- a/internal/namespace/users.go +++ b/internal/namespace/users.go @@ -2,10 +2,10 @@ package namespace import ( "github.com/conplementAG/copsctl/internal/cmd/flags" + "github.com/sirupsen/logrus" "strings" "github.com/conplementAG/copsctl/internal/adapters/kubernetes" - "github.com/conplementAG/copsctl/internal/common/logging" "github.com/spf13/viper" ) @@ -20,12 +20,12 @@ func parseUsernames(userNames string) []string { return parsedUsers } -func AddUsers() { +func (o *Orchestrator) AddUsers() { namespaceName := viper.GetString(flags.Name) users := viper.GetString("users") newUsers := parseUsernames(users) - namespace, err := kubernetes.GetCopsNamespace(namespaceName) + namespace, err := kubernetes.GetCopsNamespace(o.executor, namespaceName) if err != nil { panic("Could not get the cops namespace " + err.Error()) @@ -52,23 +52,23 @@ func AddUsers() { } } - copsnamespace := renderTemplate(namespaceName, relevantUsers, existingServiceAccounts) + copsNamespace := renderTemplate(namespaceName, relevantUsers, existingServiceAccounts) - _, err = kubernetes.ApplyString(copsnamespace) + _, err = kubernetes.ApplyString(o.executor, copsNamespace) if err != nil { panic("Apply failed: " + err.Error()) } - logging.Infof("%d user(s) have been successfully added to %s namespace", addedUserCount, namespaceName) + logrus.Infof("%d user(s) have been successfully added to %s namespace", addedUserCount, namespaceName) } -func RemoveUsers() { +func (o *Orchestrator) RemoveUsers() { namespaceName := viper.GetString(flags.Name) users := viper.GetString("users") usersToRemove := parseUsernames(users) - namespace, err := kubernetes.GetCopsNamespace(namespaceName) + namespace, err := kubernetes.GetCopsNamespace(o.executor, namespaceName) if err != nil { panic("Could not get the cops namespace " + err.Error()) @@ -96,20 +96,20 @@ func RemoveUsers() { } } - copsnamespace := renderTemplate(namespaceName, relevantUsers, existingServiceAccounts) + copsNamespace := renderTemplate(namespaceName, relevantUsers, existingServiceAccounts) - _, err = kubernetes.ApplyString(copsnamespace) + _, err = kubernetes.ApplyString(o.executor, copsNamespace) if err != nil { panic("Apply failed: " + err.Error()) } - logging.Infof("%d user(s) have been successfully removed from %s namespace", removedUserCount, namespaceName) + logrus.Infof("%d user(s) have been successfully removed from %s namespace", removedUserCount, namespaceName) } -func ListUsers() { +func (o *Orchestrator) ListUsers() { namespaceName := viper.GetString(flags.Name) - namespace, err := kubernetes.GetCopsNamespace(namespaceName) + namespace, err := kubernetes.GetCopsNamespace(o.executor, namespaceName) if err != nil { panic("Could not get the cops namespace " + err.Error()) @@ -117,9 +117,9 @@ func ListUsers() { users := namespace.Spec.NamespaceAdminUsers - logging.Info("Current users in namespace " + namespaceName + ":") + logrus.Info("Current users in namespace " + namespaceName + ":") for _, user := range users { - logging.Info(" - " + user) + logrus.Info(" - " + user) } }