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
53 changes: 23 additions & 30 deletions cmd/run_pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
"github.com/loft-sh/devspace/pkg/devspace/devpod"
"github.com/loft-sh/devspace/pkg/devspace/hook"
"github.com/loft-sh/devspace/pkg/devspace/kubectl"
fakekube "github.com/loft-sh/devspace/pkg/devspace/kubectl/testing"
"github.com/loft-sh/devspace/pkg/devspace/pipeline"
"github.com/loft-sh/devspace/pkg/devspace/pipeline/types"
"github.com/loft-sh/devspace/pkg/devspace/plugin"
Expand All @@ -32,7 +31,6 @@ import (
"gopkg.in/yaml.v3"
"io"
"io/ioutil"
"k8s.io/client-go/kubernetes/fake"
"os"
)

Expand Down Expand Up @@ -256,7 +254,7 @@ func (cmd *RunPipelineCmd) Run(cobraCmd *cobra.Command, args []string, f factory
cmd.Ctx = values.WithFlags(cmd.Ctx, cobraCmd.Flags())
}
options := cmd.BuildOptions(cmd.ToConfigOptions())
ctx, err := initialize(cmd.Ctx, f, false, options, cmd.Log)
ctx, err := initialize(cmd.Ctx, f, options, cmd.Log)
if err != nil {
return err
}
Expand All @@ -277,7 +275,7 @@ type CommandOptions struct {
UIPort int
}

func initialize(ctx context.Context, f factory.Factory, allowFailingKubeClient bool, options *CommandOptions, logger log.Logger) (devspacecontext.Context, error) {
func initialize(ctx context.Context, f factory.Factory, options *CommandOptions, logger log.Logger) (devspacecontext.Context, error) {
// start file logging
log.StartFileLogging()

Expand Down Expand Up @@ -305,18 +303,9 @@ func initialize(ctx context.Context, f factory.Factory, allowFailingKubeClient b
// create kubectl client
client, err := f.NewKubeClientFromContext(options.KubeContext, options.Namespace)
if err != nil {
if allowFailingKubeClient {
logger.Warnf("Unable to create new kubectl client: %v", err)
logger.Warn("Using fake client to render resources")
logger.WriteString(logrus.WarnLevel, "\n")

kube := fake.NewSimpleClientset()
client = &fakekube.Client{
Client: kube,
}
} else {
return nil, errors.Errorf("error creating Kubernetes client: %v. Please make sure you have a valid Kubernetes context that points to a working Kubernetes cluster. If in doubt, please check if the following command works locally: `kubectl get namespaces`", err)
}
logger.Warnf("Unable to create new kubectl client: %v", err)
logger.WriteString(logrus.WarnLevel, "\n")
client = nil
}

// load generated config
Expand All @@ -325,11 +314,13 @@ func initialize(ctx context.Context, f factory.Factory, allowFailingKubeClient b
return nil, errors.Errorf("error loading local cache: %v", err)
}

// If the current kube context or namespace is different than old,
// show warnings and reset kube client if necessary
client, err = kubectl.CheckKubeContext(client, localCache, options.NoWarn, options.SwitchContext, logger)
if err != nil {
return nil, err
if client != nil {
// If the current kube context or namespace is different than old,
// show warnings and reset kube client if necessary
client, err = kubectl.CheckKubeContext(client, localCache, options.NoWarn, options.SwitchContext, logger)
if err != nil {
return nil, err
}
}

// load config
Expand Down Expand Up @@ -370,15 +361,17 @@ func initialize(ctx context.Context, f factory.Factory, allowFailingKubeClient b

func updateLastKubeContext(ctx devspacecontext.Context) error {
// Update generated if we deploy the application
if ctx.Config() != nil && ctx.Config().LocalCache() != nil {
ctx.Config().LocalCache().SetLastContext(&localcache.LastContextConfig{
Context: ctx.KubeClient().CurrentContext(),
Namespace: ctx.KubeClient().Namespace(),
})

err := ctx.Config().LocalCache().Save()
if err != nil {
return errors.Wrap(err, "save generated")
if ctx.KubeClient() != nil {
if ctx.Config() != nil && ctx.Config().LocalCache() != nil {
ctx.Config().LocalCache().SetLastContext(&localcache.LastContextConfig{
Context: ctx.KubeClient().CurrentContext(),
Namespace: ctx.KubeClient().Namespace(),
})

err := ctx.Config().LocalCache().Save()
if err != nil {
return errors.Wrap(err, "save generated")
}
}
}

Expand Down
57 changes: 57 additions & 0 deletions e2e/tests/build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,63 @@ var _ = DevSpaceDescribe("build", func() {
framework.ExpectEqual(found, true, "image not found in cache")
})

ginkgo.It("should build dockerfile with docker even when KUBECONFIG is invalid", func() {
tempDir, err := framework.CopyToTempDir("tests/build/testdata/docker")
framework.ExpectNoError(err)
defer framework.CleanupTempDir(initialDir, tempDir)

_ = os.Setenv("KUBECONFIG", "i-am-invalid-config")
// create build command
buildCmd := &cmd.RunPipelineCmd{
GlobalFlags: &flags.GlobalFlags{
NoWarn: true,
},
SkipPush: true,
Pipeline: "build",
}
err = buildCmd.RunDefault(f)
framework.ExpectNoError(err)

// create devspace docker client to access docker APIs
devspaceDockerClient, err := docker.NewClient(context.TODO(), log)
framework.ExpectNoError(err)

dockerClient := devspaceDockerClient.DockerAPIClient()
imageList, err := dockerClient.ImageList(ctx, types.ImageListOptions{})
framework.ExpectNoError(err)

found := false
Outer:
for _, image := range imageList {
for _, tag := range image.RepoTags {
if tag == "my-docker-username/helloworld:latest" {
found = true
break Outer
}
}
}
framework.ExpectEqual(found, true, "image not found in cache")
_ = os.Unsetenv("KUBECONFIG")
})

ginkgo.It("should not build dockerfile with kaniko when KUBECONFIG is invalid", func() {
tempDir, err := framework.CopyToTempDir("tests/build/testdata/kaniko")
framework.ExpectNoError(err)
defer framework.CleanupTempDir(initialDir, tempDir)
_ = os.Setenv("KUBECONFIG", "i-am-invalid-config")
// create build command
buildCmd := &cmd.RunPipelineCmd{
GlobalFlags: &flags.GlobalFlags{
NoWarn: true,
},
SkipPush: true,
Pipeline: "build",
}
err = buildCmd.RunDefault(f)
framework.ExpectError(err)
_ = os.Unsetenv("KUBECONFIG")
})

ginkgo.It("should build dockerfile with buildkit", func() {
tempDir, err := framework.CopyToTempDir("tests/build/testdata/buildkit")
framework.ExpectNoError(err)
Expand Down
2 changes: 1 addition & 1 deletion pkg/devspace/dependency/registry/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ func (d *dependencyRegistry) MarkDependenciesExcluded(ctx devspacecontext.Contex

func (d *dependencyRegistry) excludeDependencies(ctx devspacecontext.Context, dependencyNames []string, forceLeader bool, retries int) (map[string]bool, error) {
retMap := map[string]bool{}
if len(dependencyNames) == 0 {
if len(dependencyNames) == 0 || ctx.KubeClient() == nil {
return retMap, nil
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/devspace/kubectl/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func NewClientByContext(context, namespace string, switchContext bool, kubeLoade
// try to load in cluster config
config, err := rest.InClusterConfig()
if err != nil {
return nil, "", "", false, errors.Errorf("kube config is invalid: please make sure you have an existing valid kube config. You might want to check one of the following things:\n\n* Make sure you can use 'kubectl get namespaces' locally\n* If you are using Loft, you might want to run 'devspace create space' or 'loft create space'\n")
return nil, "", "", false, errors.Errorf("kube config is invalid")
}

currentNamespace, err := inClusterNamespace()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,17 @@ type BuildImagesOptions struct {

func BuildImages(ctx devspacecontext.Context, pipeline types.Pipeline, args []string) error {
ctx.Log().Debugf("build_images %s", strings.Join(args, " "))
err := pipeline.Exclude(ctx)
if err != nil {
return err
if ctx.KubeClient() != nil {
err := pipeline.Exclude(ctx)
if err != nil {
return err
}
}

options := &BuildImagesOptions{
Options: pipeline.Options().BuildOptions,
}
args, err = flags.ParseArgs(options, args)
args, err := flags.ParseArgs(options, args)
if err != nil {
return errors.Wrap(err, "parse args")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,17 @@ type CreateDeploymentsOptions struct {
All bool `long:"all" description:"Deploy all deployments"`
}

const ErrMsg = "Please make sure you have an existing valid kube config. You might want to check one of the following things:\n\n* Make sure you can use 'kubectl get namespaces' locally\n* If you are using Loft, you might want to run 'devspace create space' or 'loft create space'\n"

func CreateDeployments(ctx devspacecontext.Context, pipeline types.Pipeline, args []string, stdout io.Writer) error {
ctx.Log().Debugf("create_deployments %s", strings.Join(args, " "))
err := pipeline.Exclude(ctx)
if err != nil {
return err
}

if ctx.KubeClient() == nil {
return errors.Errorf(ErrMsg)
}
options := &CreateDeploymentsOptions{
Options: pipeline.Options().DeployOptions,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ func EnsurePullSecrets(ctx devspacecontext.Context, pipeline types.Pipeline, arg
if err != nil {
return err
}

if ctx.KubeClient() == nil {
return errors.Errorf(ErrMsg)
}
options := &EnsurePullSecretsOptions{}
args, err = flags.ParseArgs(options, args)
if err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ type ExecContainerOptions struct {

func ExecContainer(ctx devspacecontext.Context, args []string) error {
hc := interp.HandlerCtx(ctx.Context())
if ctx.KubeClient() == nil {
return errors.Errorf(ErrMsg)
}
options := &ExecContainerOptions{
Namespace: ctx.KubeClient().Namespace(),
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ func PurgeDeployments(ctx devspacecontext.Context, pipeline types.Pipeline, args
if err != nil {
return err
}

if ctx.KubeClient() == nil {
return errors.Errorf(ErrMsg)
}
options := &PurgeDeploymentsOptions{
PurgeOptions: pipeline.Options().PurgeOptions,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ type SelectPodOptions struct {

func SelectPod(ctx devspacecontext.Context, args []string) error {
hc := interp.HandlerCtx(ctx.Context())
if ctx.KubeClient() == nil {
return errors.Errorf(ErrMsg)
}
options := &SelectPodOptions{
Namespace: ctx.KubeClient().Namespace(),
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ func StartDev(ctx devspacecontext.Context, pipeline types.Pipeline, args []strin
if err != nil {
return err
}

if ctx.KubeClient() == nil {
return errors.Errorf(ErrMsg)
}
options := &StartDevOptions{
Options: pipeline.Options().DevOptions,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ func StopDev(ctx devspacecontext.Context, pipeline types.Pipeline, args []string
if err != nil {
return err
}

if ctx.KubeClient() == nil {
return errors.Errorf(ErrMsg)
}
options := &StopDevOptions{
PurgeOptions: pipeline.Options().PurgeOptions,
}
Expand Down
12 changes: 7 additions & 5 deletions pkg/devspace/pipeline/pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,18 +88,20 @@ func (p *pipeline) Exclude(ctx devspacecontext.Context) error {
p.excluded = true

// create namespace if necessary
p.excludedErr = kubectl.EnsureNamespace(ctx.Context(), ctx.KubeClient(), ctx.KubeClient().Namespace(), ctx.Log())
if p.excludedErr != nil {
p.excludedErr = errors.Errorf("unable to create namespace: %v", p.excludedErr)
return p.excludedErr
if ctx.KubeClient() != nil {
p.excludedErr = kubectl.EnsureNamespace(ctx.Context(), ctx.KubeClient(), ctx.KubeClient().Namespace(), ctx.Log())
if p.excludedErr != nil {
p.excludedErr = errors.Errorf("unable to create namespace: %v", p.excludedErr)
return p.excludedErr
}
}

// exclude ourselves
var couldExclude bool
couldExclude, p.excludedErr = p.dependencyRegistry.MarkDependencyExcluded(ctx, p.name, true)
if p.excludedErr != nil {
return p.excludedErr
} else if !couldExclude {
} else if !couldExclude && ctx.KubeClient() != nil {
return fmt.Errorf("couldn't execute '%s', because there is another DevSpace instance active in the current namespace right now that uses the same project name (%s)", strings.Join(os.Args, " "), p.name)
}
ctx.Log().Debugf("Marked project excluded: %v", p.name)
Expand Down