Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

helm configure #7

Merged
merged 15 commits into from
Jan 31, 2019
Prev Previous commit
Next Next commit
WIP: helm configure skeleton
  • Loading branch information
yorinasub17 committed Jan 29, 2019
commit 9e8c8404e9c79a61cd9cf8241243edd3bee6b0de
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -174,7 +174,7 @@ For example, to setup a basic install of helm in the Kubernetes namespace `tille
```bash
# Note that most of the arguments here are used to setup the Certificate Authority for TLS
kubergrunt helm deploy \
--namespace tiller-world \
--tiller-namespace tiller-world \
--service-account tiller \
--tls-common-name tiller \
--tls-org Gruntwork \
@@ -226,6 +226,9 @@ this will:
- `HELM_TLS_VERIFY`: This will be set to true to enable TLS verification.
- `HELM_TLS_ENABLE`: This will be set to true to enable TLS authentication.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is annoying, but helm doesn't have a concept of a config file. The default way for the user is:

helm --tiller-namespace NAMESPACE --tls --tls-verify

everytime they want to use helm. If they want multiple helm configs, this is even worse:

helm --home HELM_HOME_DIR --tiller-namespace NAMESPACE --tls --tls-verify
# or if they want to share home dir but use different certs
helm --tiller-namespace NAMESPACE --tls --tls-verify --tls-ca-cert ca.cert.pem --tls-cert helm.cert.pem --tls-key helm.key.pem

So the proposal here is to instead provide an environment file they can source that sets these as environment variables. Then this becomes:

source ~/.helm/env
helm


You can also optionally set the current kubectl context to set the default namespace to be compatible with this Tiller
install.

Afterwards, you can source the environment file to setup your shell to access the proper helm client.

For example, if you want to setup helm to target a server install in the namespace `dev` with the default helm home
@@ -234,7 +237,7 @@ directory:
```bash
# This is for linux
# Setup helm
kubergrunt helm configure --home-dir $HOME/.helm --namespace dev
kubergrunt helm configure --home-dir $HOME/.helm --tiller-namespace dev
# Source the environment file
source $HOME/.helm/env
# Verify connection. This should display info about both the client and server.
99 changes: 86 additions & 13 deletions cmd/helm.go
Original file line number Diff line number Diff line change
@@ -11,19 +11,26 @@ import (
"github.com/urfave/cli"

"github.com/gruntwork-io/kubergrunt/helm"
"github.com/gruntwork-io/kubergrunt/logging"
"github.com/gruntwork-io/kubergrunt/tls"
)

var (
// Shared configurations
tillerNamespaceFlag = cli.StringFlag{
Name: "namespace",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I wonder if tiller-namespace and namespace would be better naming here? I expect to use this namespace for a single item, the tiller server, while many resources will reside in the resource namespace.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Usage: "Kubernetes namespace that Tiller will reside in.",
}
resourceNamespaceFlag = cli.StringFlag{
Name: "resource-namespace",
Usage: "Kubernetes namespace where the resources deployed by Tiller reside. If unspecified, defaults to the Tiller namespace.",
}

// Configurations for how helm is installed
serviceAccountFlag = cli.StringFlag{
Name: "service-account",
Usage: "The name of the ServiceAccount that Tiller should use.",
}
namespaceFlag = cli.StringFlag{
Name: "namespace",
Usage: "Kubernetes namespace to install Tiller in.",
}

// Configurations for how to authenticate with the Kubernetes cluster.
// NOTE: this is the same as eksKubectlContextNameFlag and eksKubeconfigFlag, except the descriptions are updated to
@@ -109,9 +116,16 @@ var (
Name: "undeploy-releases",
Usage: "Undeploy all releases managed by the target Helm server before undeploying the server.",
}
// This is also used in configure
helmHomeFlag = cli.StringFlag{
Name: "home",
Usage: "Home directory that is configured for accessing the helm server being removed.",
Usage: "Home directory that is configured for accessing deployed Tiller server.",
}

// Configurations for configuring the helm client
setKubectlNamespaceFlag = cli.BoolFlag{
Name: "set-kubectl-namespace",
Usage: "Set the kubectl context default namespace to match the namespace that Tiller deploys resources into.",
}
)

@@ -134,7 +148,7 @@ func SetupHelmCommand() cli.Command {
Action: deployHelmServer,
Flags: []cli.Flag{
serviceAccountFlag,
namespaceFlag,
tillerNamespaceFlag,
tlsCommonNameFlag,
tlsOrgFlag,
tlsOrgUnitFlag,
@@ -160,7 +174,26 @@ Note: By default, this will not undeploy the Helm server if there are any deploy
forceUndeployFlag,
undeployReleasesFlag,
helmHomeFlag,
namespaceFlag,
tillerNamespaceFlag,
helmKubectlContextNameFlag,
helmKubeconfigFlag,
},
},
cli.Command{
Name: "configure",
Usage: "Setup local helm client to be able to access Tiller.",
Description: `Setup local helm client to be able to access the deployed Tiller located at the provided namespace. This assumes that an administrator has granted you access to the Tiller install already. This will:

- Download the client TLS certificate key pair that you have access to.
- Install the TLS certificate key pair in the helm home directory. The helm home directory can be modified with the --helm-home option.
- Install an environment file compatible with your platform that can be sourced to setup variables to configure default parameters for the helm client to access the Tiller install.
- Optionally set the kubectl context default namespace to be the one that Tiller manages.`,
Action: configureHelmClient,
Flags: []cli.Flag{
helmHomeFlag,
tillerNamespaceFlag,
resourceNamespaceFlag,
setKubectlNamespaceFlag,
helmKubectlContextNameFlag,
helmKubeconfigFlag,
},
@@ -171,7 +204,7 @@ Note: By default, this will not undeploy the Helm server if there are any deploy
Description: "Grant access to a deployed Helm server to a client by issuing new TLS certificate keypairs that is accessible by the provided RBAC role.",
Action: grantHelmAccess,
Flags: []cli.Flag{
namespaceFlag,
tillerNamespaceFlag,
grantedRbacRoleFlag,
helmKubectlContextNameFlag,
helmKubeconfigFlag,
@@ -183,7 +216,7 @@ Note: By default, this will not undeploy the Helm server if there are any deploy
Description: "Revoke access to a deployed Helm server to a client by issuing new TLS certificate keypairs that is accessible by the provided RBAC role.",
Action: revokeHelmAccess,
Flags: []cli.Flag{
namespaceFlag,
tillerNamespaceFlag,
grantedRbacRoleFlag,
helmKubectlContextNameFlag,
helmKubeconfigFlag,
@@ -193,6 +226,7 @@ Note: By default, this will not undeploy the Helm server if there are any deploy
}
}

// deployHelmServer is the action function for helm deploy command.
func deployHelmServer(cliContext *cli.Context) error {
// Check if the required commands are installed
if err := shell.CommandInstalledE("helm"); err != nil {
@@ -207,7 +241,7 @@ func deployHelmServer(cliContext *cli.Context) error {
if err != nil {
return err
}
namespace, err := entrypoint.StringFlagRequiredE(cliContext, namespaceFlag.Name)
tillerNamespace, err := entrypoint.StringFlagRequiredE(cliContext, tillerNamespaceFlag.Name)
if err != nil {
return err
}
@@ -241,12 +275,13 @@ func deployHelmServer(cliContext *cli.Context) error {

return helm.Deploy(
kubectlOptions,
namespace,
tillerNamespace,
serviceAccount,
tlsOptions,
)
}

// undeployHelmServer is the action command for the helm undeploy command.
func undeployHelmServer(cliContext *cli.Context) error {
// Check if the required commands are installed
if err := shell.CommandInstalledE("helm"); err != nil {
@@ -258,7 +293,7 @@ func undeployHelmServer(cliContext *cli.Context) error {
if err != nil {
return err
}
namespace, err := entrypoint.StringFlagRequiredE(cliContext, namespaceFlag.Name)
tillerNamespace, err := entrypoint.StringFlagRequiredE(cliContext, tillerNamespaceFlag.Name)
if err != nil {
return err
}
@@ -267,21 +302,59 @@ func undeployHelmServer(cliContext *cli.Context) error {
return err
}

// Get optional info
force := cliContext.Bool(forceUndeployFlag.Name)
undeployReleases := cliContext.Bool(undeployReleasesFlag.Name)

return helm.Undeploy(
kubectlOptions,
namespace,
tillerNamespace,
helmHome,
force,
undeployReleases,
)
}

// configureHelmClient is the action function for the helm configure command.
func configureHelmClient(cliContext *cli.Context) error {
logger := logging.GetProjectLogger()

// Check if the required commands are installed
if err := shell.CommandInstalledE("helm"); err != nil {
return err
}

// Get required info
helmHome, err := entrypoint.StringFlagRequiredE(cliContext, helmHomeFlag.Name)
if err != nil {
return err
}
tillerNamespace, err := entrypoint.StringFlagRequiredE(cliContext, tillerNamespaceFlag.Name)
if err != nil {
return err
}
kubectlOptions, err := parseKubectlOptions(cliContext)
if err != nil {
return err
}

// Get optional info
setKubectlNamespace := cliContext.Bool(setKubectlNamespaceFlag.Name)
resourceNamespace := cliContext.String(resourceNamespaceFlag.Name)
if resourceNamespace == "" {
logger.Warnf("Did not get a specific resource namespace. Defaulting to the provided Tiller namespace.")
resourceNamespace = tillerNamespace
}

return helm.ConfigureClient(kubectlOptions, helmHome, tillerNamespace, resourceNamespace, setKubectlNamespace)
}

// grantHelmAccess is the action function for the helm grant command.
func grantHelmAccess(cliContext *cli.Context) error {
return nil
}

// revokeHelmAccess is the action function for the helm revoke command.
func revokeHelmAccess(cliContext *cli.Context) error {
return nil
}
45 changes: 45 additions & 0 deletions helm/configure.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package helm

import (
"github.com/gruntwork-io/kubergrunt/kubectl"
"github.com/gruntwork-io/kubergrunt/logging"
)

// ConfigureClient will configure the local helm client to be able to communicate with the Tiller server installed in
// the provided Tiller namespace. Note that this supports the notion where Tiller is deployed in a different namespace
// from where resources should go. This is to address the risk where access to the tiller-secret will grant admin access
// by using the tiller server TLS certs.
func ConfigureClient(
kubectlOptions *kubectl.KubectlOptions,
helmHome string,
tillerNamespace string,
resourceNamespace string,
setKubectlNamespace bool,
) error {
logger := logging.GetProjectLogger()
logger.Infof("Setting up local helm client to access Tiller server deployed in namespace %s.", tillerNamespace)

logger.Info("Checking if authorized to access specified Tiller server.")
// TODO: Check for
// - Access to TLS certs. If unavailable, mention they need to be granted access.
// - Access to Tiller pod. If unavailable, mention they need to be granted access, pod should be deployed, or change
// namespace.
logger.Info("Confirmed authorized to access specified Tiller server.")

logger.Info("Downloading TLS certificates to access specified Tiller server.")
// TODO
logger.Info("Successfully downloaded TLS certificates.")

logger.Info("Generating environment file to setup helm client.")
// TODO
logger.Info("Successfully generated environment file.")

if setKubectlNamespace {
logger.Info("Requested to set default kubectl namespace.")
// TODO
logger.Infof("Updated context %s to use namespace %s as default.", kubectlOptions.ContextName, resourceNamespace)
}

logger.Infof("Successfully set up local helm client to access Tiller server deployed in namespace %s. Be sure to source the environment file (%s/env) before using the helm client.", tillerNamespace, helmHome)
return nil
}