Skip to content

Commit 7b4da99

Browse files
committed
Add new Auto sync option and tie into jib impl
1 parent 11d005d commit 7b4da99

File tree

7 files changed

+177
-8
lines changed

7 files changed

+177
-8
lines changed

pkg/skaffold/build/jib/sync.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,21 @@ type JSONSyncEntry struct {
5353
Dest string `json:"dest"`
5454
}
5555

56-
func InitSync(ctx context.Context, workspace string, a *latest.JibArtifact) error {
56+
var InitSync = initSync
57+
58+
func initSync(ctx context.Context, workspace string, a *latest.JibArtifact) error {
5759
syncMap, err := getSyncMapFunc(ctx, workspace, a)
5860
if err != nil {
59-
return err
61+
return errors.Wrapf(err, "failed to initialize sync state for %s", workspace)
6062
}
6163
syncLists[getProjectKey(workspace, a)] = *syncMap
6264
return nil
6365
}
6466

67+
var GetSyncDiff = getSyncDiff
68+
6569
// returns toCopy, toDelete, error
66-
func GetSyncDiff(ctx context.Context, workspace string, a *latest.JibArtifact, e filemon.Events) (map[string][]string, map[string][]string, error) {
70+
func getSyncDiff(ctx context.Context, workspace string, a *latest.JibArtifact, e filemon.Events) (map[string][]string, map[string][]string, error) {
6771
// no deletions allowed
6872
if len(e.Deleted) != 0 {
6973
// change into logging

pkg/skaffold/runner/dev.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ func (r *SkaffoldRunner) Dev(ctx context.Context, out io.Writer, artifacts []*la
145145
return build.DependenciesForArtifact(ctx, artifact, r.runCtx.InsecureRegistries)
146146
},
147147
func(e filemon.Events) {
148-
s, err := sync.NewItem(artifact, e, r.builds, r.runCtx.InsecureRegistries)
148+
s, err := sync.NewItem(ctx, artifact, e, r.builds, r.runCtx.InsecureRegistries)
149149
switch {
150150
case err != nil:
151151
logrus.Warnf("error adding dirty artifact to changeset: %s", err.Error())
@@ -187,6 +187,11 @@ func (r *SkaffoldRunner) Dev(ctx context.Context, out io.Writer, artifacts []*la
187187

188188
logrus.Infoln("List generated in", time.Since(start))
189189

190+
// Init Sync State
191+
if err := sync.Init(ctx, artifacts); err != nil {
192+
return errors.Wrap(err, "exiting dev mode because initializing sync state failed")
193+
}
194+
190195
// First build
191196
if _, err := r.BuildAndTest(ctx, out, artifacts); err != nil {
192197
return errors.Wrap(err, "exiting dev mode because first build failed")

pkg/skaffold/schema/defaults/defaults.go

+9-2
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,15 @@ func setDefaultWorkspace(a *latest.Artifact) {
217217
}
218218

219219
func setDefaultSync(a *latest.Artifact) {
220-
if a.Sync != nil && len(a.Sync.Manual) == 0 && len(a.Sync.Infer) == 0 {
221-
a.Sync.Infer = []string{"**/*"}
220+
if a.Sync != nil {
221+
if len(a.Sync.Manual) == 0 && len(a.Sync.Infer) == 0 && a.Sync.Auto == nil {
222+
switch {
223+
case a.JibArtifact != nil:
224+
a.Sync.Auto = &latest.Auto{}
225+
default:
226+
a.Sync.Infer = []string{"**/*"}
227+
}
228+
}
222229
}
223230
}
224231

pkg/skaffold/schema/defaults/defaults_test.go

+10
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,13 @@ func TestSetDefaults(t *testing.T) {
5858
},
5959
Sync: &latest.Sync{},
6060
},
61+
{
62+
ImageName: "fifth",
63+
ArtifactType: latest.ArtifactType{
64+
JibArtifact: &latest.JibArtifact{},
65+
},
66+
Sync: &latest.Sync{},
67+
},
6168
},
6269
},
6370
},
@@ -83,6 +90,9 @@ func TestSetDefaults(t *testing.T) {
8390
testutil.CheckDeepEqual(t, []string{"."}, cfg.Build.Artifacts[3].BuildpackArtifact.Dependencies.Paths)
8491
testutil.CheckDeepEqual(t, []string(nil), cfg.Build.Artifacts[3].BuildpackArtifact.Dependencies.Ignore)
8592
testutil.CheckDeepEqual(t, []string{"**/*"}, cfg.Build.Artifacts[3].Sync.Infer)
93+
94+
testutil.CheckDeepEqual(t, "fifth", cfg.Build.Artifacts[4].ImageName)
95+
testutil.CheckDeepEqual(t, &latest.Auto{}, cfg.Build.Artifacts[4].Sync.Auto)
8696
}
8797

8898
func TestSetDefaultsOnCluster(t *testing.T) {

pkg/skaffold/schema/latest/config.go

+7
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,10 @@ type Sync struct {
593593
// The container destination is inferred by the builder.
594594
// Currently only available for docker artifacts.
595595
Infer []string `yaml:"infer,omitempty" yamltags:"oneOf=sync"`
596+
597+
// Auto delegates discovery of sync rules to the build system.
598+
// Currently not available on any builders.
599+
Auto *Auto `yaml:"auto,omitempty" yamltags:"oneOf=sync"`
596600
}
597601

598602
// SyncRule specifies which local files to sync to remote folders.
@@ -612,6 +616,9 @@ type SyncRule struct {
612616
Strip string `yaml:"strip,omitempty"`
613617
}
614618

619+
// Auto cannot be customized.
620+
type Auto struct{}
621+
615622
// Profile is used to override any `build`, `test` or `deploy` configuration.
616623
type Profile struct {
617624
// Name is a unique profile name.

pkg/skaffold/sync/sync.go

+45-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333

3434
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/build"
3535
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/buildpacks"
36+
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/jib"
3637
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/docker"
3738
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/filemon"
3839
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes"
@@ -47,7 +48,7 @@ var (
4748
SyncMap = syncMapForArtifact
4849
)
4950

50-
func NewItem(a *latest.Artifact, e filemon.Events, builds []build.Artifact, insecureRegistries map[string]bool) (*Item, error) {
51+
func NewItem(ctx context.Context, a *latest.Artifact, e filemon.Events, builds []build.Artifact, insecureRegistries map[string]bool) (*Item, error) {
5152
if !e.HasChanged() || a.Sync == nil {
5253
return nil, nil
5354
}
@@ -83,6 +84,9 @@ func NewItem(a *latest.Artifact, e filemon.Events, builds []build.Artifact, inse
8384
case len(a.Sync.Infer) > 0:
8485
return inferredSyncItem(a, tag, e, insecureRegistries)
8586

87+
case a.Sync.Auto != nil:
88+
return autoSyncItem(ctx, a, e, builds)
89+
8690
default:
8791
return nil, nil
8892
}
@@ -169,6 +173,30 @@ func syncMapForArtifact(a *latest.Artifact, insecureRegistries map[string]bool)
169173
}
170174
}
171175

176+
func autoSyncItem(ctx context.Context, a *latest.Artifact, e filemon.Events, builds []build.Artifact) (*Item, error) {
177+
tag := latestTag(a.ImageName, builds)
178+
if tag == "" {
179+
return nil, fmt.Errorf("could not find latest tag for image %s in builds: %v", a.ImageName, builds)
180+
}
181+
182+
switch {
183+
case a.JibArtifact != nil:
184+
toCopy, toDelete, err := jib.GetSyncDiff(ctx, a.Workspace, a.JibArtifact, e)
185+
if err != nil {
186+
return nil, err
187+
}
188+
if toCopy == nil && toDelete == nil {
189+
// do a rebuild
190+
return nil, nil
191+
}
192+
return &Item{Image: tag, Copy: toCopy, Delete: toDelete}, nil
193+
194+
default:
195+
// TODO: this error does appear a little late in the build, perhaps it could surface at first run, rather than first sync?
196+
return nil, fmt.Errorf("Sync: Auto is not supported by the build of %s", a.ImageName)
197+
}
198+
}
199+
172200
func latestTag(image string, builds []build.Artifact) string {
173201
for _, build := range builds {
174202
if build.ImageName == image {
@@ -338,3 +366,19 @@ func Perform(ctx context.Context, image string, files syncMap, cmdFn func(contex
338366

339367
return errs.Wait()
340368
}
369+
370+
func Init(ctx context.Context, artifacts []*latest.Artifact) error {
371+
for _, a := range artifacts {
372+
if a.Sync == nil {
373+
continue
374+
}
375+
376+
if a.Sync.Auto != nil && a.JibArtifact != nil {
377+
err := jib.InitSync(ctx, a.Workspace, a.JibArtifact)
378+
if err != nil {
379+
return errors.Wrapf(err, "failed to initialize sync state for %s", a.ImageName)
380+
}
381+
}
382+
}
383+
return nil
384+
}

pkg/skaffold/sync/sync_test.go

+93-1
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,14 @@ import (
2323
"strings"
2424
"testing"
2525

26+
"github.com/pkg/errors"
2627
v1 "k8s.io/api/core/v1"
2728
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2829
"k8s.io/client-go/kubernetes"
2930
"k8s.io/client-go/kubernetes/fake"
3031

3132
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/build"
33+
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/jib"
3234
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/filemon"
3335
pkgkubernetes "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes"
3436
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest"
@@ -37,6 +39,7 @@ import (
3739
)
3840

3941
func TestNewSyncItem(t *testing.T) {
42+
ctx := context.Background()
4043
tests := []struct {
4144
description string
4245
artifact *latest.Artifact
@@ -677,14 +680,48 @@ func TestNewSyncItem(t *testing.T) {
677680
Delete: map[string][]string{},
678681
},
679682
},
683+
684+
// Auto with Jib
685+
{
686+
description: "auto with jib",
687+
artifact: &latest.Artifact{
688+
ImageName: "test",
689+
Workspace: ".",
690+
Sync: &latest.Sync{
691+
Auto: &latest.Auto{},
692+
},
693+
ArtifactType: latest.ArtifactType{
694+
JibArtifact: &latest.JibArtifact{},
695+
},
696+
},
697+
evt: filemon.Events{
698+
Added: []string{"this actually doesn't matter"},
699+
},
700+
builds: []build.Artifact{
701+
{
702+
ImageName: "test",
703+
Tag: "test:123",
704+
},
705+
},
706+
expected: &Item{
707+
Image: "test:123",
708+
Copy: map[string][]string{
709+
"file.class": {"/some/file.class"},
710+
},
711+
Delete: nil,
712+
},
713+
},
680714
}
681715
for _, test := range tests {
682716
testutil.Run(t, test.description, func(t *testutil.T) {
683717
t.Override(&WorkingDir, func(string, map[string]bool) (string, error) { return test.workingDir, nil })
684718
t.Override(&SyncMap, func(*latest.Artifact, map[string]bool) (map[string][]string, error) { return test.dependencies, nil })
685719
t.Override(&Labels, func(string, map[string]bool) (map[string]string, error) { return test.labels, nil })
720+
t.Override(&jib.GetSyncDiff, func(context.Context, string, *latest.JibArtifact, filemon.Events) (map[string][]string, map[string][]string, error) {
721+
return map[string][]string{"file.class": {"/some/file.class"}}, nil, nil
722+
})
686723

687-
actual, err := NewItem(test.artifact, test.evt, test.builds, nil)
724+
actual, err := NewItem(ctx, test.artifact, test.evt, test.builds, nil)
688725

689726
t.CheckErrorAndDeepEqual(test.shouldErr, err, test.expected, actual)
690727
})
@@ -947,3 +984,58 @@ func TestSyncMap(t *testing.T) {
947984
})
948985
}
949986
}
987+
988+
func TestInit(t *testing.T) {
989+
ctx := context.Background()
990+
tests := []struct {
991+
description string
992+
artifact *latest.Artifact
993+
shouldInit bool
994+
initErrors bool
995+
}{
996+
{
997+
description: "sync off",
998+
artifact: &latest.Artifact{},
999+
shouldInit: false,
1000+
},
1001+
{
1002+
description: "sync on, auto off",
1003+
artifact: &latest.Artifact{Sync: &latest.Sync{}},
1004+
shouldInit: false,
1005+
},
1006+
{
1007+
description: "sync on, auto on, non-jib",
1008+
artifact: &latest.Artifact{Sync: &latest.Sync{Auto: &latest.Auto{}}},
1009+
shouldInit: false,
1010+
},
1011+
{
1012+
description: "sync on, auto on, jib",
1013+
artifact: &latest.Artifact{ArtifactType: latest.ArtifactType{JibArtifact: &latest.JibArtifact{}}, Sync: &latest.Sync{Auto: &latest.Auto{}}},
1014+
shouldInit: true,
1015+
initErrors: false,
1016+
},
1017+
{
1018+
description: "sync on, auto on, jib, init fails",
1019+
artifact: &latest.Artifact{ArtifactType: latest.ArtifactType{JibArtifact: &latest.JibArtifact{}}, Sync: &latest.Sync{Auto: &latest.Auto{}}},
1020+
shouldInit: true,
1021+
initErrors: true,
1022+
},
1023+
}
1024+
for _, test := range tests {
1025+
testutil.Run(t, test.description, func(t *testutil.T) {
1026+
isCalled := false
1027+
t.Override(&jib.InitSync, func(ctx context.Context, workspace string, a *latest.JibArtifact) error {
1028+
isCalled = true
1029+
if test.initErrors {
1030+
return errors.New("intentional test failure")
1031+
}
1032+
return nil
1033+
})
1034+
1035+
artifacts := []*latest.Artifact{test.artifact}
1036+
err := Init(ctx, artifacts)
1037+
t.CheckDeepEqual(test.shouldInit, isCalled)
1038+
t.CheckError(test.initErrors, err)
1039+
})
1040+
}
1041+
}

0 commit comments

Comments
 (0)