Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions cmd/enter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package cmd

import (
helmClient "github.com/covexo/devspace/pkg/devspace/clients/helm"
"github.com/covexo/devspace/pkg/devspace/clients/kubectl"
"github.com/covexo/devspace/pkg/devspace/config/configutil"
"github.com/covexo/devspace/pkg/util/log"
"github.com/spf13/cobra"
k8sv1 "k8s.io/api/core/v1"
"k8s.io/client-go/kubernetes"
kubectlExec "k8s.io/client-go/util/exec"
)

// EnterCmd is a struct that defines a command call for "enter"
type EnterCmd struct {
flags *EnterCmdFlags
helm *helmClient.HelmClientWrapper
kubectl *kubernetes.Clientset
pod *k8sv1.Pod
}

// EnterCmdFlags are the flags available for the enter-command
type EnterCmdFlags struct {
container string
}

func init() {
cmd := &EnterCmd{
flags: &EnterCmdFlags{},
}

cobraCmd := &cobra.Command{
Use: "enter",
Short: "Enter your DevSpace",
Long: `
#######################################################
################## devspace enter #####################
#######################################################
Execute a command or start a new terminal in your
devspace:

devspace enter
devspace enter bash
devspace enter -c myContainer
#######################################################`,
Run: cmd.Run,
}
rootCmd.AddCommand(cobraCmd)

cobraCmd.Flags().StringVarP(&cmd.flags.container, "container", "c", "", "Container name within pod where to execute command")
}

// Run executes the command logic
func (cmd *EnterCmd) Run(cobraCmd *cobra.Command, args []string) {
var err error
log.StartFileLogging()

cmd.kubectl, err = kubectl.NewClient()
if err != nil {
log.Fatalf("Unable to create new kubectl client: %v", err)
}

log.StartWait("Initializing helm client")
cmd.helm, err = helmClient.NewClient(cmd.kubectl, false)
log.StopWait()
if err != nil {
log.Fatalf("Error initializing helm client: %s", err.Error())
}

// Check if we find a running release pod
log.StartWait("Find a running devspace pod")
pod, err := getRunningDevSpacePod(cmd.helm, cmd.kubectl)
log.StopWait()
if err != nil {
log.Fatal("Cannot find a running devspace pod")
}

enterTerminal(cmd.kubectl, pod, cmd.flags.container, args)
}

func enterTerminal(client *kubernetes.Clientset, pod *k8sv1.Pod, containerNameOverride string, args []string) {
var command []string
config := configutil.GetConfig(false)

if len(args) == 0 && (config.DevSpace.Terminal.Command == nil || len(*config.DevSpace.Terminal.Command) == 0) {
command = []string{
"sh",
"-c",
"command -v bash >/dev/null 2>&1 && exec bash || exec sh",
}
} else {
if len(args) > 0 {
command = args
} else {
for _, cmd := range *config.DevSpace.Terminal.Command {
command = append(command, *cmd)
}
}
}

containerName := pod.Spec.Containers[0].Name
if containerNameOverride != "" {
containerName = containerNameOverride
} else if config.DevSpace.Terminal.ContainerName != nil {
containerName = *config.DevSpace.Terminal.ContainerName
}

_, _, _, terminalErr := kubectl.Exec(client, pod, containerName, command, true, nil)
if terminalErr != nil {
if _, ok := terminalErr.(kubectlExec.CodeExitError); ok == false {
log.Fatalf("Unable to start terminal session: %v", terminalErr)
}
}
}
15 changes: 12 additions & 3 deletions cmd/reset.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,15 @@ func (cmd *ResetCmd) Run(cobraCmd *cobra.Command, args []string) {
if cmd.kubectl == nil || cmd.helm == nil {
cmd.kubectl, err = kubectl.NewClient()
if err != nil {
log.Failf("Failed to initialize kubectl client: ", err.Error())
log.Failf("Failed to initialize kubectl client: %v", err)
}
}
cmd.determineResetExtent()

if cmd.flags.deleteRelease {
log.StartWait("Deleting devspace release")
err = cmd.deleteRelease()
log.StopWait()

if err != nil {
log.Failf("Error deleting release: %s", err.Error())
Expand All @@ -89,7 +91,9 @@ func (cmd *ResetCmd) Run(cobraCmd *cobra.Command, args []string) {
}

if cmd.flags.deleteRegistry {
log.StartWait("Deleting docker registry")
err = cmd.deleteRegistry()
log.StopWait()

if err != nil {
log.Failf("Error deleting docker registry: %s", err.Error())
Expand All @@ -103,7 +107,9 @@ func (cmd *ResetCmd) Run(cobraCmd *cobra.Command, args []string) {
}

if cmd.flags.deleteTiller {
log.StartWait("Deleting tiller")
err = cmd.deleteTiller()
log.StopWait()

if err != nil {
log.Failf("Error deleting tiller: %s", err.Error())
Expand Down Expand Up @@ -148,7 +154,7 @@ func (cmd *ResetCmd) Run(cobraCmd *cobra.Command, args []string) {
err = cmd.deleteDevspaceFolder()

if err != nil {
log.Failf("Error deleting .devspace folder: ", err.Error())
log.Failf("Error deleting .devspace folder: %v", err)

if cmd.shouldContinue() == false {
return
Expand All @@ -159,9 +165,12 @@ func (cmd *ResetCmd) Run(cobraCmd *cobra.Command, args []string) {
}

if cmd.flags.deleteClusterRoleBinding {
log.StartWait("Deleting cluster role bindings")
err = cmd.kubectl.RbacV1beta1().ClusterRoleBindings().Delete(clusterRoleBindingName, &metav1.DeleteOptions{})
log.StopWait()

if err != nil {
log.Failf("Failed to remove ClusterRoleBinding: ", err.Error())
log.Failf("Failed to remove ClusterRoleBinding: %v", err)
} else {
log.Done("Successfully deleted ClusterRoleBinding '" + clusterRoleBindingName + "'")
}
Expand Down
80 changes: 28 additions & 52 deletions cmd/up.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import (
k8sv1 "k8s.io/api/core/v1"
k8sv1beta1 "k8s.io/api/rbac/v1beta1"
"k8s.io/client-go/kubernetes"
kubectlExec "k8s.io/client-go/util/exec"
)

// UpCmd is a struct that defines a command call for "up"
Expand Down Expand Up @@ -70,7 +69,7 @@ var UpFlagsDefault = &UpCmdFlags{
tiller: true,
open: "cmd",
initRegistries: true,
build: true,
build: false,
sync: true,
deploy: false,
portforwarding: true,
Expand Down Expand Up @@ -106,13 +105,13 @@ Starts and connects your DevSpace:

cobraCmd.Flags().BoolVar(&cmd.flags.tiller, "tiller", cmd.flags.tiller, "Install/upgrade tiller")
cobraCmd.Flags().BoolVar(&cmd.flags.initRegistries, "init-registries", cmd.flags.initRegistries, "Initialize registries (and install internal one)")
cobraCmd.Flags().BoolVarP(&cmd.flags.build, "build", "b", cmd.flags.build, "Build image if Dockerfile has been modified")
cobraCmd.Flags().BoolVarP(&cmd.flags.build, "build", "b", cmd.flags.build, "Force image build")
cobraCmd.Flags().StringVarP(&cmd.flags.container, "container", "c", cmd.flags.container, "Container name where to open the shell")
cobraCmd.Flags().BoolVar(&cmd.flags.sync, "sync", cmd.flags.sync, "Enable code synchronization")
cobraCmd.Flags().BoolVar(&cmd.flags.verboseSync, "verbose-sync", cmd.flags.verboseSync, "When enabled the sync will log every file change")
cobraCmd.Flags().BoolVar(&cmd.flags.portforwarding, "portforwarding", cmd.flags.portforwarding, "Enable port forwarding")
cobraCmd.Flags().BoolVarP(&cmd.flags.deploy, "deploy", "d", cmd.flags.deploy, "Deploy chart")
cobraCmd.Flags().BoolVar(&cmd.flags.noSleep, "no-sleep", cmd.flags.noSleep, "Enable no-sleep")
cobraCmd.Flags().BoolVarP(&cmd.flags.deploy, "deploy", "d", cmd.flags.deploy, "Force chart deployment")
cobraCmd.Flags().BoolVar(&cmd.flags.noSleep, "no-sleep", cmd.flags.noSleep, "Enable no-sleep (Override the containers.default.command and containers.default.args values with empty strings)")
}

// Run executes the command logic
Expand Down Expand Up @@ -155,11 +154,9 @@ func (cmd *UpCmd) Run(cobraCmd *cobra.Command, args []string) {
if cmd.flags.initRegistries {
cmd.initRegistries()
}
mustRedeploy := false

if cmd.flags.build {
mustRedeploy = cmd.buildImages(cobraCmd.Flags().Changed("build"))
}
// Build image if necessary
mustRedeploy := cmd.buildImages()

// Check if we find a running release pod
pod, err := getRunningDevSpacePod(cmd.helm, cmd.kubectl)
Expand All @@ -183,7 +180,7 @@ func (cmd *UpCmd) Run(cobraCmd *cobra.Command, args []string) {
}()
}

cmd.enterTerminal(args)
enterTerminal(cmd.kubectl, cmd.pod, cmd.flags.container, args)
}

func (cmd *UpCmd) ensureNamespace() error {
Expand Down Expand Up @@ -345,7 +342,7 @@ func (cmd *UpCmd) initRegistries() {
}
}

func (cmd *UpCmd) shouldRebuild(imageConf *v1.ImageConfig, dockerfilePath string, buildFlagChanged bool) bool {
func (cmd *UpCmd) shouldRebuild(imageConf *v1.ImageConfig, dockerfilePath string) bool {
var dockerfileModTime time.Time

mustRebuild := true
Expand All @@ -361,7 +358,7 @@ func (cmd *UpCmd) shouldRebuild(imageConf *v1.ImageConfig, dockerfilePath string
dockerfileModTime = dockerfileInfo.ModTime()

// When user has not used -b or --build flags
if buildFlagChanged == false {
if cmd.flags.build == false {
if imageConf.Build.LatestTimestamp != nil {
latestBuildTime, _ := time.Parse(time.RFC3339Nano, *imageConf.Build.LatestTimestamp)

Expand All @@ -370,13 +367,13 @@ func (cmd *UpCmd) shouldRebuild(imageConf *v1.ImageConfig, dockerfilePath string
}
}
}
imageConf.Build.LatestTimestamp = configutil.String(dockerfileModTime.Format(time.RFC3339Nano))

imageConf.Build.LatestTimestamp = configutil.String(dockerfileModTime.Format(time.RFC3339Nano))
return mustRebuild
}

// returns true when one of the images had to be rebuild
func (cmd *UpCmd) buildImages(buildFlagChanged bool) bool {
func (cmd *UpCmd) buildImages() bool {
re := false
config := configutil.GetConfig(false)

Expand All @@ -391,10 +388,18 @@ func (cmd *UpCmd) buildImages(buildFlagChanged bool) bool {
if imageConf.Build.ContextPath != nil {
contextPath = *imageConf.Build.ContextPath
}
dockerfilePath = filepath.Join(cmd.workdir, strings.TrimPrefix(dockerfilePath, "."))
contextPath = filepath.Join(cmd.workdir, strings.TrimPrefix(contextPath, "."))

if cmd.shouldRebuild(imageConf, dockerfilePath, buildFlagChanged) {
dockerfilePath, err := filepath.Abs(dockerfilePath)
if err != nil {
log.Fatalf("Couldn't determine absolute path for %s", *imageConf.Build.DockerfilePath)
}

contextPath, err = filepath.Abs(contextPath)
if err != nil {
log.Fatalf("Couldn't determine absolute path for %s", *imageConf.Build.ContextPath)
}

if cmd.shouldRebuild(imageConf, dockerfilePath) {
re = true
imageTag, randErr := randutil.GenerateRandomString(7)

Expand Down Expand Up @@ -482,6 +487,12 @@ func (cmd *UpCmd) buildImages(buildFlagChanged bool) bool {
if imageConf.Build.Options.BuildArgs != nil {
buildOptions.BuildArgs = *imageConf.Build.Options.BuildArgs
}
if imageConf.Build.Options.Target != nil {
buildOptions.Target = *imageConf.Build.Options.Target
}
if imageConf.Build.Options.Network != nil {
buildOptions.NetworkMode = *imageConf.Build.Options.Network
}
}

err = imageBuilder.BuildImage(contextPath, dockerfilePath, buildOptions)
Expand Down Expand Up @@ -783,41 +794,6 @@ func (cmd *UpCmd) startPortForwarding() {
}
}

func (cmd *UpCmd) enterTerminal(args []string) {
var command []string
config := configutil.GetConfig(false)

if len(args) == 0 && (config.DevSpace.Terminal.Command == nil || len(*config.DevSpace.Terminal.Command) == 0) {
command = []string{
"sh",
"-c",
"command -v bash >/dev/null 2>&1 && exec bash || exec sh",
}
} else {
if len(args) > 0 {
command = args
} else {
for _, cmd := range *config.DevSpace.Terminal.Command {
command = append(command, *cmd)
}
}
}

containerName := cmd.pod.Spec.Containers[0].Name
if cmd.flags.container != "" {
containerName = cmd.flags.container
} else if config.DevSpace.Terminal.ContainerName != nil {
containerName = *config.DevSpace.Terminal.ContainerName
}

_, _, _, terminalErr := kubectl.Exec(cmd.kubectl, cmd.pod, containerName, command, true, nil)
if terminalErr != nil {
if _, ok := terminalErr.(kubectlExec.CodeExitError); ok == false {
log.Fatalf("Unable to start terminal session: %v", terminalErr)
}
}
}

func waitForPodReady(kubectl *kubernetes.Clientset, pod *k8sv1.Pod, maxWaitTime time.Duration, checkInterval time.Duration) error {
for maxWaitTime > 0 {
pod, err := kubectl.Core().Pods(pod.Namespace).Get(pod.Name, metav1.GetOptions{})
Expand Down
20 changes: 20 additions & 0 deletions docs/docs/cli/enter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
title: devspace enter
---

Execute a command or start a new terminal in your devspace.

```bash
Usage:
devspace enter [flags]

Flags:
-c, --container string Container name within pod where to execute command
-h, --help help for enter

Examples:
devspace enter
devspace enter bash
devspace enter echo 123
devspace enter -c myContainer
```
Loading