Skip to content

Commit

Permalink
Merge pull request #37 from jaxxstorm/kubernetes
Browse files Browse the repository at this point in the history
  • Loading branch information
jaxxstorm authored Nov 1, 2022
2 parents 65681fe + 569e68d commit 063f9c1
Show file tree
Hide file tree
Showing 11 changed files with 296 additions and 8 deletions.
2 changes: 2 additions & 0 deletions cmd/cli/connect/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package connect
import (
"github.com/jaxxstorm/connecti/cmd/cli/connect/aws"
"github.com/jaxxstorm/connecti/cmd/cli/connect/azure"
"github.com/jaxxstorm/connecti/cmd/cli/connect/kubernetes"
"github.com/spf13/cobra"
)

Expand All @@ -15,6 +16,7 @@ func Command() *cobra.Command {

command.AddCommand(aws.Command())
command.AddCommand(azure.Command())
command.AddCommand(kubernetes.Command())

return command
}
115 changes: 115 additions & 0 deletions cmd/cli/connect/kubernetes/cli.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package kubernetes

import (
"context"
"fmt"

"github.com/jaxxstorm/connecti/pkg/kubernetes"
randomname "github.com/jaxxstorm/connecti/pkg/name"
tui "github.com/jaxxstorm/connecti/pkg/terminal"
"github.com/pulumi/pulumi/sdk/v3/go/auto/optup"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

var (
name string
tailnet string
apiKey string
routes []string
)

func Command() *cobra.Command {
command := &cobra.Command{
Use: "kubernetes",
Short: "Connect to Kubernetes infrastructure.",
Long: `Create a tailscale bastion in a Kubernetes cluster via a deployment.`,
RunE: tui.WrapCobraCommand(func(cmd *cobra.Command, args []string, view tui.View) error {
// Grab all the configuration variables
tailnet = viper.GetString("tailnet")
apiKey = viper.GetString("apiKey")
name = viper.GetString("name")
routes = viper.GetStringSlice("routes")

view.Ready()

// apparently you can't specify if a flag is required
// and set in configuration, so manual validation is the only way
// see: https://github.com/spf13/viper/issues/397
if tailnet == "" {
return fmt.Errorf("must specify a tailnet. See --help")
}

if apiKey == "" {
return fmt.Errorf("must specify a tailscale api key. See --help")
}

if name == "" {
name = randomname.Generate()
}

if len(routes) == 0 {
return fmt.Errorf("must specify at least one route. See --help")
}

ctx := context.Background()
program, err := kubernetes.Program(name, ctx, kubernetes.BastionArgs{
Name: name,
Routes: routes,
Tailnet: tailnet,
ApiKey: apiKey,
CreateNamespace: true, // FIXME: should we allow usage of an existing namespace?
})
if err != nil {
return err
}

view.SetPulumiProgramCancelFn(func() error {
return program.Cancel(ctx)
})

outputHandler := view.NewPulumiOutputHandler("update")
stdoutStreamer := optup.ProgressStreams(outputHandler)
_, err = program.Refresh(ctx)
if err != nil {
return fmt.Errorf("error refreshing stack: %v", err)
}
_, err = program.Up(ctx, stdoutStreamer)
if err != nil {
view.SendPulumiProgressOutput(outputHandler.CurrentProgress, "Failed to create resources. Cleaning up.", "")
// If the update errors, we should clean up the stack for the user.
_, dErr := program.Destroy(ctx)
if dErr != nil {
return fmt.Errorf("failed update: %v\n\n\tfailed clean up: %v", err, dErr)
}
rmErr := program.Workspace().RemoveStack(ctx, name)
if rmErr != nil {
return fmt.Errorf("failed update: %v\n\n\tfailed stack removal: %v", err, rmErr)
}

return fmt.Errorf("failed update: %v", err)
}

return nil

}),
}

command.Flags().StringVar(&name, "name", "", "Unique name to use for your bastion.")
command.Flags().StringVar(&tailnet, "tailnet", "", "The name of the tailnet to connect to. See: https://login.tailscale.com/admin/settings/general")
command.Flags().StringVar(&apiKey, "api-key", "", "The tailnet api key to use. See: https://login.tailscale.com/admin/settings/keys")
command.Flags().StringSliceVar(&routes, "routes", nil, "The routes to advertise. This is likely the cluster Pod CIDR and Service CIDR.")

viper.BindPFlag("name", command.Flags().Lookup("name"))
viper.BindPFlag("tailnet", command.Flags().Lookup("tailnet"))
viper.BindPFlag("apiKey", command.Flags().Lookup("api-key"))
viper.BindPFlag("routes", command.Flags().Lookup("routes"))

// Bind the env vars to the provider env vars
viper.BindEnv("tailnet", "TAILSCALE_TAILNET")
viper.BindEnv("apiKey", "TAILSCALE_API_KEY")

command.MarkFlagRequired("routes")

return command
}
2 changes: 2 additions & 0 deletions cmd/cli/disconnect/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package disconnect
import (
"github.com/jaxxstorm/connecti/cmd/cli/disconnect/aws"
"github.com/jaxxstorm/connecti/cmd/cli/disconnect/azure"
"github.com/jaxxstorm/connecti/cmd/cli/disconnect/kubernetes"
"github.com/spf13/cobra"
)

Expand All @@ -15,6 +16,7 @@ func Command() *cobra.Command {

command.AddCommand(aws.Command())
command.AddCommand(azure.Command())
command.AddCommand(kubernetes.Command())

return command
}
64 changes: 64 additions & 0 deletions cmd/cli/disconnect/kubernetes/cli.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package kubernetes

import (
"context"
"fmt"

"github.com/jaxxstorm/connecti/pkg/kubernetes"
tui "github.com/jaxxstorm/connecti/pkg/terminal"
"github.com/pulumi/pulumi/sdk/v3/go/auto/optdestroy"
"github.com/spf13/cobra"
)

var (
name string
)

func Command() *cobra.Command {
command := &cobra.Command{
Use: "kubernetes",
Short: "Disconnect from Kubernetes infrastructure",
Long: `Tear down a tailscale bastion in an Kubernetes cluster via a deployment`,
RunE: tui.WrapCobraCommand(func(cmd *cobra.Command, args []string, view tui.View) error {

view.Ready()
ctx := context.Background()
// FIXME: do we need to specify credentials here?
// I suspect not because I believe they're hardcoded into the provider
// but we should check
program, err := kubernetes.Program(name, ctx, kubernetes.BastionArgs{
Name: name,
})
if err != nil {
return err
}

view.SetPulumiProgramCancelFn(func() error {
return program.Cancel(ctx)
})

pulumiOutputHandler := view.NewPulumiOutputHandler("destroy")
stdoutStreamer := optdestroy.ProgressStreams(pulumiOutputHandler)
_, err = program.Refresh(ctx)
if err != nil {
return fmt.Errorf("error refreshing stack: %v", err)
}
_, err = program.Destroy(ctx, stdoutStreamer)
if err != nil {
return fmt.Errorf("failed destroy: %v", err)
}

err = program.Workspace().RemoveStack(ctx, name)
if err != nil {
return fmt.Errorf("failed to remove stack: %v", err)
}

return nil
}),
}

command.Flags().StringVar(&name, "name", "", "The name of the bastion to tear down")
command.MarkFlagRequired("name")

return command
}
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ require (
github.com/charmbracelet/bubbletea v0.22.1
github.com/cip8/autoname v1.0.1
github.com/gobeam/stringy v0.0.5
github.com/lbrlabs/pulumi-tailscale-bastion/sdk v0.0.10
github.com/lbrlabs/pulumi-tailscale-bastion/sdk v0.0.11
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de
github.com/pulumi/pulumi-aws/sdk/v5 v5.19.0
github.com/pulumi/pulumi-azure/sdk/v5 v5.23.0
github.com/pulumi/pulumi/sdk/v3 v3.44.2
github.com/pulumi/pulumi/sdk/v3 v3.44.3
github.com/spf13/cobra v1.5.0
github.com/spf13/viper v1.13.0
golang.org/x/text v0.3.7
Expand Down Expand Up @@ -77,6 +77,7 @@ require (
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pkg/term v1.1.0 // indirect
github.com/pulumi/pulumi-kubernetes/sdk/v3 v3.22.1 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/rogpeppe/go-internal v1.8.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
Expand Down
Loading

0 comments on commit 063f9c1

Please sign in to comment.