Skip to content

Commit 9747ce3

Browse files
committed
add: refactor custom build & add disabled config options
1 parent dcb644b commit 9747ce3

File tree

14 files changed

+132
-53
lines changed

14 files changed

+132
-53
lines changed

examples/custom-builder/custom/build

Lines changed: 0 additions & 4 deletions
This file was deleted.

examples/custom-builder/custom/build.cmd

Lines changed: 0 additions & 4 deletions
This file was deleted.

examples/custom-builder/devspace.yaml

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,10 @@ images:
99
image: ${IMAGE}
1010
build:
1111
custom:
12-
command: ./custom/build
13-
# command: docker
14-
# args:
15-
# - build
16-
# - .
17-
# - --tag
18-
# appendArgs:
19-
# - --file
20-
# - ./custom/Dockerfile
12+
skipImageArg: true
13+
command: |-
14+
# Also works on windows as this is executed in a golang shell
15+
docker build -t ${runtime.images.default.image}:${runtime.images.default.tag} . -f custom/Dockerfile
2116
onChange:
2217
- main.go
2318
deployments:

examples/custom-builder/kube/deployment.yaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ metadata:
44
name: devspace
55
spec:
66
replicas: 1
7+
selector:
8+
matchLabels:
9+
app.kubernetes.io/component: devspace-default
10+
app.kubernetes.io/name: devspace-app
711
template:
812
metadata:
913
labels:
@@ -12,4 +16,5 @@ spec:
1216
spec:
1317
containers:
1418
- name: default
15-
image: devspace
19+
image: myusername/devspace
20+
imagePullPolicy: Never

pkg/devspace/build/builder/custom/custom.go

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ package custom
22

33
import (
44
"fmt"
5+
"github.com/loft-sh/devspace/pkg/devspace/config"
6+
"github.com/loft-sh/devspace/pkg/devspace/config/loader/variable/runtime"
7+
"github.com/loft-sh/devspace/pkg/devspace/dependency/types"
8+
"github.com/loft-sh/devspace/pkg/util/shell"
59
"io"
610
"path/filepath"
711
"strings"
@@ -28,14 +32,20 @@ type Builder struct {
2832

2933
imageConfigName string
3034
imageTags []string
35+
36+
config config.Config
37+
dependencies []types.Dependency
3138
}
3239

3340
// NewBuilder creates a new custom builder
34-
func NewBuilder(imageConfigName string, imageConf *latest.ImageConfig, imageTags []string) *Builder {
41+
func NewBuilder(imageConfigName string, imageConf *latest.ImageConfig, imageTags []string, config config.Config, dependencies []types.Dependency) *Builder {
3542
return &Builder{
3643
imageConfigName: imageConfigName,
3744
imageConf: imageConf,
3845
imageTags: imageTags,
46+
47+
config: config,
48+
dependencies: dependencies,
3949
}
4050
}
4151

@@ -74,7 +84,7 @@ func (b *Builder) ShouldRebuild(cache *generated.CacheConfig, forceRebuild bool,
7484
imageCache := cache.GetImageCache(b.imageConfigName)
7585

7686
// only rebuild Docker image when Dockerfile or context has changed since latest build
77-
mustRebuild := imageCache.Tag == "" || imageCache.ImageConfigHash != imageConfigHash || imageCache.CustomFilesHash != customFilesHash
87+
mustRebuild := forceRebuild || b.imageConf.RebuildStrategy == latest.RebuildStrategyAlways || imageCache.Tag == "" || imageCache.ImageConfigHash != imageConfigHash || imageCache.CustomFilesHash != customFilesHash
7888

7989
imageCache.ImageConfigHash = imageConfigHash
8090
imageCache.CustomFilesHash = customFilesHash
@@ -87,8 +97,23 @@ func (b *Builder) Build(devspacePID string, log logpkg.Logger) error {
8797
// Build arguments
8898
args := []string{}
8999

90-
// add args
91-
args = append(args, b.imageConf.Build.Custom.Args...)
100+
// resolve command
101+
if len(b.imageTags) > 0 {
102+
key := fmt.Sprintf("images.%s", b.imageConfigName)
103+
b.config.SetRuntimeVariable(key, b.imageConf.Image+":"+b.imageTags[0])
104+
b.config.SetRuntimeVariable(key+".image", b.imageConf.Image)
105+
b.config.SetRuntimeVariable(key+".tag", b.imageTags[0])
106+
}
107+
108+
// loop over args
109+
for i := range b.imageConf.Build.Custom.Args {
110+
resolvedArg, err := runtime.NewRuntimeResolver(false).FillRuntimeVariablesAsString(b.imageConf.Build.Custom.Args[i], b.config, b.dependencies)
111+
if err != nil {
112+
return err
113+
}
114+
115+
args = append(args, resolvedArg)
116+
}
92117

93118
// add image arg
94119
if !b.imageConf.Build.Custom.SkipImageArg {
@@ -106,7 +131,14 @@ func (b *Builder) Build(devspacePID string, log logpkg.Logger) error {
106131
}
107132

108133
// append the rest
109-
args = append(args, b.imageConf.Build.Custom.AppendArgs...)
134+
for i := range b.imageConf.Build.Custom.AppendArgs {
135+
resolvedArg, err := runtime.NewRuntimeResolver(false).FillRuntimeVariablesAsString(b.imageConf.Build.Custom.AppendArgs[i], b.config, b.dependencies)
136+
if err != nil {
137+
return err
138+
}
139+
140+
args = append(args, resolvedArg)
141+
}
110142

111143
// get the command
112144
commandPath := b.imageConf.Build.Custom.Command
@@ -122,11 +154,11 @@ func (b *Builder) Build(devspacePID string, log logpkg.Logger) error {
122154
return fmt.Errorf("no command specified for custom builder")
123155
}
124156

125-
// make sure the path has the correct slashes
126-
commandPath = filepath.FromSlash(commandPath)
127-
128-
// Create the command
129-
cmd := command.NewStreamCommand(commandPath, args)
157+
// resolve command and args
158+
commandPath, err := runtime.NewRuntimeResolver(false).FillRuntimeVariablesAsString(commandPath, b.config, b.dependencies)
159+
if err != nil {
160+
return err
161+
}
130162

131163
// Determine output writer
132164
var writer io.Writer
@@ -138,9 +170,16 @@ func (b *Builder) Build(devspacePID string, log logpkg.Logger) error {
138170

139171
log.Infof("Build %s:%s with custom command '%s %s'", b.imageConf.Image, b.imageTags[0], commandPath, strings.Join(args, " "))
140172

141-
err := cmd.Run(writer, writer, nil)
142-
if err != nil {
143-
return errors.Errorf("Error building image: %v", err)
173+
if len(args) == 0 {
174+
err = shell.ExecuteShellCommand(commandPath, args, filepath.Dir(b.config.Path()), writer, writer, nil)
175+
if err != nil {
176+
return errors.Errorf("error building image: %v", err)
177+
}
178+
} else {
179+
err = command.NewStreamCommand(commandPath, args).Run(writer, writer, nil)
180+
if err != nil {
181+
return errors.Errorf("error building image: %v", err)
182+
}
144183
}
145184

146185
log.Done("Done processing image '" + b.imageConf.Image + "'")

pkg/devspace/build/create_builder.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func (c *controller) createBuilder(imageConfigName string, imageConf *latest.Ima
2424
var builder builder.Interface
2525

2626
if imageConf.Build != nil && imageConf.Build.Custom != nil {
27-
builder = custom.NewBuilder(imageConfigName, imageConf, imageTags)
27+
builder = custom.NewBuilder(imageConfigName, imageConf, imageTags, c.config, c.dependencies)
2828
} else if imageConf.Build != nil && imageConf.Build.BuildKit != nil {
2929
log.StartWait("Creating BuildKit builder")
3030
defer log.StopWait()

pkg/devspace/config/loader/parser.go

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package loader
22

33
import (
44
"github.com/loft-sh/devspace/pkg/devspace/config/loader/variable"
5+
"github.com/loft-sh/devspace/pkg/devspace/config/loader/variable/runtime"
56
"github.com/loft-sh/devspace/pkg/devspace/config/versions"
67
"github.com/loft-sh/devspace/pkg/devspace/config/versions/latest"
78
"github.com/loft-sh/devspace/pkg/util/log"
@@ -96,16 +97,7 @@ func (p *profilesParser) Parse(originalRawConfig map[interface{}]interface{}, ra
9697

9798
func fillVariablesAndParse(resolver variable.Resolver, preparedConfig map[interface{}]interface{}, log log.Logger) (*latest.Config, error) {
9899
// fill in variables and expressions (leave out
99-
preparedConfigInterface, err := resolver.FillVariablesExclude(preparedConfig, []string{
100-
"/deployments/*/helm/values/**",
101-
"/hooks/*/command",
102-
"/hooks/*/args/*",
103-
"/hooks/*/container/imageSelector",
104-
"/dev/ports/*/imageSelector",
105-
"/dev/sync/*/imageSelector",
106-
"/dev/logs/*/selectors/*/imageSelector",
107-
"/dev/terminal/imageSelector",
108-
})
100+
preparedConfigInterface, err := resolver.FillVariablesExclude(preparedConfig, runtime.Locations)
109101
if err != nil {
110102
return nil, err
111103
}

pkg/devspace/config/loader/variable/resolver.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package variable
33
import (
44
"fmt"
55
"github.com/loft-sh/devspace/pkg/devspace/config/loader/variable/expression"
6+
"github.com/loft-sh/devspace/pkg/devspace/config/loader/variable/runtime"
67
"path/filepath"
78
"regexp"
89
"strings"
@@ -66,7 +67,7 @@ func (r *resolver) fillVariables(haystack interface{}, exclude []*regexp.Regexp)
6667
return nil, err
6768
}
6869
}
69-
70+
7071
return t, nil
7172
}
7273

@@ -120,6 +121,13 @@ func (r *resolver) FindVariables(haystack interface{}) (map[string]bool, error)
120121
}
121122
}
122123

124+
// filter out runtime environment variables
125+
for k := range varsUsed {
126+
if strings.HasPrefix(k, "runtime.") {
127+
delete(varsUsed, k)
128+
}
129+
}
130+
123131
return varsUsed, nil
124132
}
125133

@@ -396,7 +404,7 @@ func (r *resolver) fillVariable(name string, definition *latest.Variable) (inter
396404

397405
// is runtime variable
398406
if strings.HasPrefix(name, "runtime.") {
399-
return nil, fmt.Errorf("cannot resolve %s in this config area as this config region is loaded on startup. Please check the DevSpace docs in which config regions you can use runtime variables", name)
407+
return nil, fmt.Errorf("cannot resolve %s in this config area as this config region is loaded on startup. You can only use runtime variables in the following locations: \n %s", name, strings.Join(runtime.Locations, "\n "))
400408
}
401409

402410
// fill variable without definition

pkg/devspace/config/loader/variable/runtime/runtime_variable.go

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,21 @@ import (
77
"strings"
88
)
99

10+
var Locations = []string{
11+
"/images/*/build/custom/command",
12+
"/images/*/build/custom/commands/*/command",
13+
"/images/*/build/custom/args/*",
14+
"/images/*/build/custom/appendArgs/*",
15+
"/deployments/*/helm/values/**",
16+
"/hooks/*/command",
17+
"/hooks/*/args/*",
18+
"/hooks/*/container/imageSelector",
19+
"/dev/ports/*/imageSelector",
20+
"/dev/sync/*/imageSelector",
21+
"/dev/logs/*/selectors/*/imageSelector",
22+
"/dev/terminal/imageSelector",
23+
}
24+
1025
// NewRuntimeVariable creates a new variable that is loaded during runtime
1126
func NewRuntimeVariable(name string, config config.Config, dependencies []types.Dependency, builtImages map[string]string) *runtimeVariable {
1227
return &runtimeVariable{
@@ -57,6 +72,12 @@ func (e *runtimeVariable) Load() (bool, interface{}, error) {
5772
return false, nil, fmt.Errorf("couldn't find runtime variable %s", e.name)
5873
}
5974

75+
// generic retrieve runtime variable
76+
out, ok := runtimeVariables[runtimeVar]
77+
if ok {
78+
return false, out, nil
79+
}
80+
6081
// get image info from generated config
6182
if strings.HasPrefix(runtimeVar, "images.") {
6283
runtimeVar = strings.TrimPrefix(runtimeVar, "images.")
@@ -126,11 +147,5 @@ func (e *runtimeVariable) Load() (bool, interface{}, error) {
126147
return false, nil, fmt.Errorf("couldn't find imageName %s resolving variable %s", imageName, e.name)
127148
}
128149

129-
// generic retrieve runtime variable
130-
out, ok := runtimeVariables[runtimeVar]
131-
if !ok {
132-
return false, nil, fmt.Errorf("couldn't find runtime variable %s", e.name)
133-
}
134-
135-
return false, out, nil
150+
return false, nil, fmt.Errorf("couldn't find runtime variable %s", e.name)
136151
}

pkg/devspace/config/versions/latest/schema.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,7 @@ type BuildOptions struct {
448448
type DeploymentConfig struct {
449449
Name string `yaml:"name" json:"name"`
450450
Namespace string `yaml:"namespace,omitempty" json:"namespace,omitempty"`
451+
Disabled bool `yaml:"disabled,omitempty" json:"disabled,omitempty"`
451452
Helm *HelmConfig `yaml:"helm,omitempty" json:"helm,omitempty"`
452453
Kubectl *KubectlConfig `yaml:"kubectl,omitempty" json:"kubectl,omitempty"`
453454
}
@@ -956,6 +957,7 @@ type PodPatch struct {
956957
type DependencyConfig struct {
957958
Name string `yaml:"name" json:"name"`
958959
Source *SourceConfig `yaml:"source" json:"source"`
960+
Disabled bool `yaml:"disabled,omitempty" json:"disabled,omitempty"`
959961
Profile string `yaml:"profile,omitempty" json:"profile,omitempty"`
960962
Profiles []string `yaml:"profiles,omitempty" json:"profiles,omitempty"`
961963
ProfileParents []string `yaml:"profileParents,omitempty" json:"profileParents,omitempty"`
@@ -1012,6 +1014,9 @@ type HookConfig struct {
10121014
// Name is the name of the hook
10131015
Name string `yaml:"name,omitempty" json:"name,omitempty"`
10141016

1017+
// If true, the hook is disabled and not executed
1018+
Disabled bool `yaml:"disabled,omitempty" json:"disabled,omitempty"`
1019+
10151020
// Events are the events when the hook should be executed
10161021
Events []string `yaml:"events" json:"events"`
10171022

@@ -1212,6 +1217,9 @@ type PatchConfig struct {
12121217

12131218
// PullSecretConfig defines a pull secret that should be created by DevSpace
12141219
type PullSecretConfig struct {
1220+
// If true, the pull secret will be not created
1221+
Disabled bool `yaml:"disabled,omitempty" json:"disabled,omitempty"`
1222+
12151223
// The registry to create the image pull secret for.
12161224
// e.g. gcr.io
12171225
Registry string `yaml:"registry" json:"registry"`

0 commit comments

Comments
 (0)