diff --git a/internal/containerupdate/exec_updater.go b/internal/containerupdate/exec_updater.go index c3992f1b77..d54cb43907 100644 --- a/internal/containerupdate/exec_updater.go +++ b/internal/containerupdate/exec_updater.go @@ -39,6 +39,7 @@ func (cu *ExecUpdater) UpdateContainer(ctx context.Context, cInfo store.Containe l := logger.Get(ctx) w := logger.Get(ctx).Writer(logger.InfoLvl) + // delete files (if any) if len(filesToDelete) > 0 { err := cu.kCli.Exec(ctx, cInfo.PodID, cInfo.ContainerName, cInfo.Namespace, @@ -48,12 +49,14 @@ func (cu *ExecUpdater) UpdateContainer(ctx context.Context, cInfo store.Containe } } + // copy files to container err := cu.kCli.Exec(ctx, cInfo.PodID, cInfo.ContainerName, cInfo.Namespace, []string{"tar", "-C", "/", "-x", "-f", "-"}, archiveToCopy, w, w) if err != nil { return err } + // run commands for i, c := range cmds { l.Infof("[CMD %d/%d] %s", i+1, len(cmds), strings.Join(c.Argv, " ")) err := cu.kCli.Exec(ctx, cInfo.PodID, cInfo.ContainerName, cInfo.Namespace, diff --git a/internal/engine/build_and_deployer.go b/internal/engine/build_and_deployer.go index 5d5b18043a..be3824ce8f 100644 --- a/internal/engine/build_and_deployer.go +++ b/internal/engine/build_and_deployer.go @@ -123,17 +123,13 @@ func (composite *CompositeBuildAndDeployer) BuildAndDeploy(ctx context.Context, func DefaultBuildOrder(lubad *LiveUpdateBuildAndDeployer, ibad *ImageBuildAndDeployer, dcbad *DockerComposeBuildAndDeployer, ltbad *LocalTargetBuildAndDeployer, updMode buildcontrol.UpdateMode, env k8s.Env, runtime container.Runtime) BuildOrder { - if updMode == buildcontrol.UpdateModeImage || updMode == buildcontrol.UpdateModeNaive { + if updMode == buildcontrol.UpdateModeImage { return BuildOrder{dcbad, ibad, ltbad} } - if updMode == buildcontrol.UpdateModeSynclet || shouldUseSynclet(updMode, env, runtime) { + if updMode == buildcontrol.UpdateModeSynclet { ibad.SetInjectSynclet(true) } return BuildOrder{lubad, dcbad, ibad, ltbad} } - -func shouldUseSynclet(updMode buildcontrol.UpdateMode, env k8s.Env, runtime container.Runtime) bool { - return updMode == buildcontrol.UpdateModeAuto && !env.UsesLocalDockerRegistry() && runtime == container.RuntimeDocker -} diff --git a/internal/engine/build_and_deployer_live_update_test.go b/internal/engine/build_and_deployer_live_update_test.go index aeb2feeade..b2d09e614b 100644 --- a/internal/engine/build_and_deployer_live_update_test.go +++ b/internal/engine/build_and_deployer_live_update_test.go @@ -9,6 +9,8 @@ import ( "github.com/stretchr/testify/require" "k8s.io/client-go/util/exec" + "github.com/tilt-dev/tilt/internal/engine/buildcontrol" + "github.com/tilt-dev/tilt/internal/k8s/testyaml" "github.com/tilt-dev/tilt/internal/docker" @@ -219,7 +221,7 @@ func TestLiveUpdateDockerBuildLocalContainerSameImgMultipleContainers(t *testing } func TestLiveUpdateDockerBuildSyncletSameImgMultipleContainers(t *testing.T) { - f := newBDFixture(t, k8s.EnvGKE, container.RuntimeDocker) + f := newBDFixtureWithUpdateMode(t, k8s.EnvGKE, container.RuntimeDocker, buildcontrol.UpdateModeSynclet) defer f.TearDown() m := NewSanchoLiveUpdateManifest(f) @@ -292,7 +294,7 @@ func TestLiveUpdateDockerBuildLocalContainerDiffImgMultipleContainers(t *testing } func TestLiveUpdateDockerBuildSyncletDiffImgMultipleContainers(t *testing.T) { - f := newBDFixture(t, k8s.EnvGKE, container.RuntimeDocker) + f := newBDFixtureWithUpdateMode(t, k8s.EnvGKE, container.RuntimeDocker, buildcontrol.UpdateModeSynclet) defer f.TearDown() sanchoTarg := NewSanchoLiveUpdateImageTarget(f) @@ -504,7 +506,7 @@ func TestLiveUpdateDockerContainerUserRunFailureDoesntFallBack(t *testing.T) { // TODO(maia): make this test actually touch gRPC de/serialization, // which is where most of this logic lives func TestLiveUpdateSyncletUserRunFailureDoesntFallBack(t *testing.T) { - f := newBDFixture(t, k8s.EnvGKE, container.RuntimeDocker) + f := newBDFixtureWithUpdateMode(t, k8s.EnvGKE, container.RuntimeDocker, buildcontrol.UpdateModeSynclet) defer f.TearDown() f.docker.SetExecError(userFailureErrDocker) @@ -777,7 +779,7 @@ func TestLiveUpdateRunTriggerLocalContainer(t *testing.T) { } func TestLiveUpdateRunTriggerSynclet(t *testing.T) { - f := newBDFixture(t, k8s.EnvGKE, container.RuntimeDocker) + f := newBDFixtureWithUpdateMode(t, k8s.EnvGKE, container.RuntimeDocker, buildcontrol.UpdateModeSynclet) defer f.TearDown() runs := []model.LiveUpdateRunStep{ @@ -803,10 +805,38 @@ func TestLiveUpdateRunTriggerSynclet(t *testing.T) { runTestCase(t, f, tCase) } -func TestLiveUpdateDockerBuildSynclet(t *testing.T) { +func TestLiveUpdateRunTriggerExec(t *testing.T) { f := newBDFixture(t, k8s.EnvGKE, container.RuntimeDocker) defer f.TearDown() + runs := []model.LiveUpdateRunStep{ + model.LiveUpdateRunStep{Command: model.ToUnixCmd("echo hello")}, + model.LiveUpdateRunStep{Command: model.ToUnixCmd("echo a"), Triggers: f.NewPathSet("a.txt")}, // matches changed file + model.LiveUpdateRunStep{Command: model.ToUnixCmd("echo b"), Triggers: f.NewPathSet("b.txt")}, // does NOT match changed file + } + lu := assembleLiveUpdate(SanchoSyncSteps(f), runs, false, nil, f) + tCase := testCase{ + manifest: manifestbuilder.New(f, "sancho"). + WithK8sYAML(SanchoYAML). + WithImageTarget(NewSanchoDockerBuildImageTarget(f)). + WithLiveUpdate(lu). + Build(), + changedFiles: []string{"a.txt"}, + expectDockerBuildCount: 0, + expectDockerPushCount: 0, + expectSyncletUpdateContainerCount: 0, + expectDockerCopyCount: 0, + expectDockerExecCount: 0, // one run's triggers don't match -- should only exec the other two. + expectDockerRestartCount: 0, + expectK8sExecCount: 3, // one copy, two runs (third run's triggers don't match so don't exec it) + } + runTestCase(t, f, tCase) +} + +func TestLiveUpdateDockerBuildSynclet(t *testing.T) { + f := newBDFixtureWithUpdateMode(t, k8s.EnvGKE, container.RuntimeDocker, buildcontrol.UpdateModeSynclet) + defer f.TearDown() + tCase := testCase{ manifest: NewSanchoLiveUpdateManifest(f), changedFiles: []string{"a.txt"}, @@ -821,7 +851,7 @@ func TestLiveUpdateDockerBuildSynclet(t *testing.T) { } func TestLiveUpdateCustomBuildSynclet(t *testing.T) { - f := newBDFixture(t, k8s.EnvGKE, container.RuntimeDocker) + f := newBDFixtureWithUpdateMode(t, k8s.EnvGKE, container.RuntimeDocker, buildcontrol.UpdateModeSynclet) defer f.TearDown() lu := assembleLiveUpdate(SanchoSyncSteps(f), SanchoRunSteps, true, nil, f) @@ -842,10 +872,33 @@ func TestLiveUpdateCustomBuildSynclet(t *testing.T) { runTestCase(t, f, tCase) } -func TestLiveUpdateHotReloadSynclet(t *testing.T) { +func TestLiveUpdateCustomBuildExec(t *testing.T) { f := newBDFixture(t, k8s.EnvGKE, container.RuntimeDocker) defer f.TearDown() + lu := assembleLiveUpdate(SanchoSyncSteps(f), SanchoRunSteps, false, nil, f) + tCase := testCase{ + manifest: manifestbuilder.New(f, "sancho"). + WithK8sYAML(SanchoYAML). + WithImageTarget(NewSanchoCustomBuildImageTarget(f)). + WithLiveUpdate(lu). + Build(), + changedFiles: []string{"app/a.txt"}, + expectDockerBuildCount: 0, + expectDockerPushCount: 0, + expectSyncletUpdateContainerCount: 0, + expectDockerCopyCount: 0, + expectDockerExecCount: 0, + expectDockerRestartCount: 0, + expectK8sExecCount: 2, + } + runTestCase(t, f, tCase) +} + +func TestLiveUpdateHotReloadSynclet(t *testing.T) { + f := newBDFixtureWithUpdateMode(t, k8s.EnvGKE, container.RuntimeDocker, buildcontrol.UpdateModeSynclet) + defer f.TearDown() + lu := assembleLiveUpdate(SanchoSyncSteps(f), SanchoRunSteps, false, nil, f) tCase := testCase{ manifest: manifestbuilder.New(f, "sancho"). @@ -901,13 +954,14 @@ func TestLiveUpdateDockerBuildExec(t *testing.T) { changedFiles: []string{"a.txt"}, expectDockerBuildCount: 0, expectDockerPushCount: 0, - expectK8sExecCount: 2, // one tar archive, one run cmd + expectK8sExecCount: 2, // one tar archive, one run cmd + expectSyncletDeploy: false, // exec updater should not deploy synclet } runTestCase(t, f, tCase) } func TestDockerBuildWithoutLiveUpdateDoesNotDeploySynclet(t *testing.T) { - f := newBDFixture(t, k8s.EnvGKE, container.RuntimeDocker) + f := newBDFixtureWithUpdateMode(t, k8s.EnvGKE, container.RuntimeDocker, buildcontrol.UpdateModeSynclet) defer f.TearDown() tCase := testCase{ @@ -922,7 +976,7 @@ func TestDockerBuildWithoutLiveUpdateDoesNotDeploySynclet(t *testing.T) { } func TestLiveUpdateDockerBuildDeploysSynclet(t *testing.T) { - f := newBDFixture(t, k8s.EnvGKE, container.RuntimeDocker) + f := newBDFixtureWithUpdateMode(t, k8s.EnvGKE, container.RuntimeDocker, buildcontrol.UpdateModeSynclet) defer f.TearDown() tCase := testCase{ @@ -960,7 +1014,7 @@ func TestLiveUpdateLocalContainerFallBackOn(t *testing.T) { } func TestLiveUpdateSyncletFallBackOn(t *testing.T) { - f := newBDFixture(t, k8s.EnvGKE, container.RuntimeDocker) + f := newBDFixtureWithUpdateMode(t, k8s.EnvGKE, container.RuntimeDocker, buildcontrol.UpdateModeSynclet) defer f.TearDown() lu := assembleLiveUpdate(SanchoSyncSteps(f), SanchoRunSteps, true, []string{"a.txt"}, f) @@ -983,6 +1037,29 @@ func TestLiveUpdateSyncletFallBackOn(t *testing.T) { runTestCase(t, f, tCase) } +func TestLiveUpdateExecFallBackOn(t *testing.T) { + f := newBDFixture(t, k8s.EnvGKE, container.RuntimeDocker) + defer f.TearDown() + + lu := assembleLiveUpdate(SanchoSyncSteps(f), SanchoRunSteps, false, []string{"a.txt"}, f) + tCase := testCase{ + manifest: manifestbuilder.New(f, "sancho"). + WithK8sYAML(SanchoYAML). + WithImageTarget(NewSanchoDockerBuildImageTarget(f)). + WithLiveUpdate(lu). + Build(), + changedFiles: []string{"a.txt"}, + expectDockerBuildCount: 1, // we did a Docker build instead of an in-place update! + expectDockerPushCount: 1, + expectDockerCopyCount: 0, + expectDockerExecCount: 0, + expectDockerRestartCount: 0, + expectK8sDeploy: true, // because we fell back to image builder, we also did a k8s deploy + logsContain: []string{"Detected change to fall_back_on file", "a.txt"}, + } + runTestCase(t, f, tCase) +} + func TestLiveUpdateLocalContainerChangedFileNotMatchingSyncFallsBack(t *testing.T) { f := newBDFixture(t, k8s.EnvDockerDesktop, container.RuntimeDocker) defer f.TearDown() @@ -1015,7 +1092,7 @@ func TestLiveUpdateLocalContainerChangedFileNotMatchingSyncFallsBack(t *testing. } func TestLiveUpdateSyncletChangedFileNotMatchingSyncFallsBack(t *testing.T) { - f := newBDFixture(t, k8s.EnvGKE, container.RuntimeDocker) + f := newBDFixtureWithUpdateMode(t, k8s.EnvGKE, container.RuntimeDocker, buildcontrol.UpdateModeSynclet) defer f.TearDown() steps := []model.LiveUpdateSyncStep{model.LiveUpdateSyncStep{ @@ -1046,6 +1123,37 @@ func TestLiveUpdateSyncletChangedFileNotMatchingSyncFallsBack(t *testing.T) { runTestCase(t, f, tCase) } +func TestLiveUpdateExecChangedFileNotMatchingSyncFallsBack(t *testing.T) { + f := newBDFixture(t, k8s.EnvGKE, container.RuntimeDocker) + defer f.TearDown() + + steps := []model.LiveUpdateSyncStep{model.LiveUpdateSyncStep{ + Source: f.JoinPath("specific/directory"), + Dest: "/go/src/github.com/tilt-dev/sancho", + }} + + lu := assembleLiveUpdate(steps, SanchoRunSteps, false, []string{"a.txt"}, f) + tCase := testCase{ + manifest: manifestbuilder.New(f, "sancho"). + WithK8sYAML(SanchoYAML). + WithImageTarget(NewSanchoDockerBuildImageTarget(f)). + WithLiveUpdate(lu). + Build(), + changedFiles: []string{f.JoinPath("a.txt")}, // matches context but not sync'd directory + + expectDockerBuildCount: 1, // we did a Docker build instead of an in-place update! + expectDockerPushCount: 1, + expectDockerCopyCount: 0, + expectDockerExecCount: 0, + expectDockerRestartCount: 0, + expectK8sDeploy: true, // because we fell back to image builder, we also did a k8s deploy + + logsContain: []string{"Found file(s) not matching any sync", "a.txt"}, + logsDontContain: []string{"unexpected error"}, + } + runTestCase(t, f, tCase) +} + func TestLiveUpdateSomeFilesMatchSyncSomeDontFallsBack(t *testing.T) { f := newBDFixture(t, k8s.EnvDockerDesktop, container.RuntimeDocker) defer f.TearDown() diff --git a/internal/engine/build_and_deployer_test.go b/internal/engine/build_and_deployer_test.go index f3302fb7ce..3aac4249b6 100644 --- a/internal/engine/build_and_deployer_test.go +++ b/internal/engine/build_and_deployer_test.go @@ -80,16 +80,16 @@ func TestGKEDeploy(t *testing.T) { t.Errorf("Expected yaml to contain %q. Actual:\n%s", expectedYaml, f.k8s.Yaml) } - if !strings.Contains(f.k8s.Yaml, sidecar.DefaultSyncletImageName) { - t.Errorf("Should deploy the synclet on docker-for-desktop: %s", f.k8s.Yaml) + if strings.Contains(f.k8s.Yaml, sidecar.DefaultSyncletImageName) { + t.Errorf("Should not deploy synclet without explicitly specifying updateMode=Synclet: %s", f.k8s.Yaml) } } -func TestDockerForMacDeploy(t *testing.T) { - f := newBDFixture(t, k8s.EnvDockerDesktop, container.RuntimeDocker) +func TestGKEDeployWithSynclet(t *testing.T) { + f := newBDFixtureWithUpdateMode(t, k8s.EnvGKE, container.RuntimeDocker, buildcontrol.UpdateModeSynclet) defer f.TearDown() - manifest := NewSanchoDockerBuildManifest(f) + manifest := NewSanchoLiveUpdateManifest(f) targets := buildTargets(manifest) _, err := f.bd.BuildAndDeploy(f.ctx, f.st, targets, store.BuildStateSet{}) if err != nil { @@ -100,8 +100,8 @@ func TestDockerForMacDeploy(t *testing.T) { t.Errorf("Expected 1 docker build, actual: %d", f.docker.BuildCount) } - if f.docker.PushCount != 0 { - t.Errorf("Expected no push to docker, actual: %d", f.docker.PushCount) + if f.docker.PushCount != 1 { + t.Errorf("Expected 1 push to docker, actual: %d", f.docker.PushCount) } expectedYaml := "image: gcr.io/some-project-162817/sancho:tilt-11cd0b38bc3ceb95" @@ -109,224 +109,112 @@ func TestDockerForMacDeploy(t *testing.T) { t.Errorf("Expected yaml to contain %q. Actual:\n%s", expectedYaml, f.k8s.Yaml) } - if strings.Contains(f.k8s.Yaml, sidecar.DefaultSyncletImageName) { - t.Errorf("Should not deploy the synclet on docker-for-desktop: %s", f.k8s.Yaml) + if !strings.Contains(f.k8s.Yaml, sidecar.DefaultSyncletImageName) { + t.Errorf("Should deploy the synclet when updateMode=Synclet specified: %s", f.k8s.Yaml) } } -func TestSyncletNamespaceGKE(t *testing.T) { - f := newBDFixture(t, k8s.EnvGKE, container.RuntimeDocker) +func TestNoSyncletDeployIfNoLiveUpdate(t *testing.T) { + f := newBDFixtureWithUpdateMode(t, k8s.EnvGKE, container.RuntimeDocker, buildcontrol.UpdateModeSynclet) defer f.TearDown() - assert.Equal(t, "", string(f.sCli.Namespace)) - assert.Equal(t, "", string(f.k8s.LastPodQueryNamespace)) - - manifest := NewSanchoLiveUpdateManifest(f) + manifest := NewSanchoDockerBuildManifest(f) targets := buildTargets(manifest) - result, err := f.bd.BuildAndDeploy(f.ctx, f.st, targets, store.BuildStateSet{}) + _, err := f.bd.BuildAndDeploy(f.ctx, f.st, targets, store.BuildStateSet{}) if err != nil { t.Fatal(err) } - cInfo := testContainerInfo - cInfo.Namespace = "sancho-ns" - - changed := f.WriteFile("a.txt", "a") - bs := resultToStateSet(result, []string{changed}, cInfo) - _, err = f.bd.BuildAndDeploy(f.ctx, f.st, buildTargets(manifest), bs) - if err != nil { - t.Fatal(err) + if f.docker.BuildCount != 1 { + t.Errorf("Expected 1 docker build, actual: %d", f.docker.BuildCount) } - assert.Equal(t, "sancho-ns", string(f.sCli.Namespace)) -} - -func TestYamlManifestDeploy(t *testing.T) { - f := newBDFixture(t, k8s.EnvGKE, container.RuntimeDocker) - defer f.TearDown() + if f.docker.PushCount != 1 { + t.Errorf("Expected 1 push to docker, actual: %d", f.docker.PushCount) + } - manifest := manifestbuilder.New(f, "some_yaml"). - WithK8sYAML(testyaml.TracerYAML).Build() - targets := buildTargets(manifest) - _, err := f.bd.BuildAndDeploy(f.ctx, f.st, targets, store.BuildStateSet{}) - if err != nil { - t.Fatal(err) + expectedYaml := "image: gcr.io/some-project-162817/sancho:tilt-11cd0b38bc3ceb95" + if !strings.Contains(f.k8s.Yaml, expectedYaml) { + t.Errorf("Expected yaml to contain %q. Actual:\n%s", expectedYaml, f.k8s.Yaml) } - assert.Equal(t, 0, f.sCli.UpdateContainerCount) - assert.Equal(t, 0, f.docker.BuildCount) - assert.Equal(t, 0, f.docker.PushCount) - f.assertK8sUpsertCalled(true) + if strings.Contains(f.k8s.Yaml, sidecar.DefaultSyncletImageName) { + t.Errorf("Should not deploy the synclet if manifest has no LiveUpdate instructions: %s", f.k8s.Yaml) + } } -func TestContainerBuildLocal(t *testing.T) { +func TestDockerForMacDeploy(t *testing.T) { f := newBDFixture(t, k8s.EnvDockerDesktop, container.RuntimeDocker) defer f.TearDown() - changed := f.WriteFile("a.txt", "a") - manifest := NewSanchoLiveUpdateManifest(f) + manifest := NewSanchoDockerBuildManifest(f) targets := buildTargets(manifest) - bs := resultToStateSet(alreadyBuiltSet, []string{changed}, testContainerInfo) - result, err := f.bd.BuildAndDeploy(f.ctx, f.st, targets, bs) + _, err := f.bd.BuildAndDeploy(f.ctx, f.st, targets, store.BuildStateSet{}) if err != nil { t.Fatal(err) } - if f.docker.BuildCount != 0 { - t.Errorf("Expected no docker build, actual: %d", f.docker.BuildCount) + if f.docker.BuildCount != 1 { + t.Errorf("Expected 1 docker build, actual: %d", f.docker.BuildCount) } + if f.docker.PushCount != 0 { t.Errorf("Expected no push to docker, actual: %d", f.docker.PushCount) } - if f.docker.CopyCount != 1 { - t.Errorf("Expected 1 copy to docker container call, actual: %d", f.docker.CopyCount) - } - if len(f.docker.ExecCalls) != 1 { - t.Errorf("Expected 1 exec in container call, actual: %d", len(f.docker.ExecCalls)) - } - f.assertContainerRestarts(1) - - id := manifest.ImageTargetAt(0).ID() - _, hasResult := result[id] - assert.True(t, hasResult) - assert.Equal(t, k8s.MagicTestContainerID, result.OneAndOnlyLiveUpdatedContainerID().String()) -} - -func TestContainerBuildSynclet(t *testing.T) { - f := newBDFixture(t, k8s.EnvGKE, container.RuntimeDocker) - defer f.TearDown() - changed := f.WriteFile("a.txt", "a") - bs := resultToStateSet(alreadyBuiltSet, []string{changed}, testContainerInfo) - manifest := NewSanchoLiveUpdateManifest(f) - targets := buildTargets(manifest) - result, err := f.bd.BuildAndDeploy(f.ctx, f.st, targets, bs) - if err != nil { - t.Fatal(err) + expectedYaml := "image: gcr.io/some-project-162817/sancho:tilt-11cd0b38bc3ceb95" + if !strings.Contains(f.k8s.Yaml, expectedYaml) { + t.Errorf("Expected yaml to contain %q. Actual:\n%s", expectedYaml, f.k8s.Yaml) } - assert.Equal(t, 0, f.docker.BuildCount, - "Expected no docker build, actual: %d", f.docker.BuildCount) - assert.Equal(t, 0, f.docker.PushCount, - "Expected no push to docker, actual: %d", f.docker.PushCount) - assert.Equal(t, 1, f.sCli.UpdateContainerCount, - "Expected 1 synclet UpdateContainer call, actual: %d", f.sCli.UpdateContainerCount) - assert.Equal(t, 1, f.docker.CopyCount, - "Expected 1 docker CopyToContainer (via synclet), actual: %d", f.docker.CopyCount) - assert.Len(t, f.docker.ExecCalls, 1, - "Expected 1 docker Exec call (via synclet), actual: %d", len(f.docker.ExecCalls)) - f.assertContainerRestarts(1) - assert.Equal(t, k8s.MagicTestContainerID, result.OneAndOnlyLiveUpdatedContainerID().String()) + if strings.Contains(f.k8s.Yaml, sidecar.DefaultSyncletImageName) { + t.Errorf("Should not deploy the synclet on docker-for-desktop: %s", f.k8s.Yaml) + } } -func TestContainerBuildLocalTriggeredRuns(t *testing.T) { - f := newBDFixture(t, k8s.EnvDockerDesktop, container.RuntimeDocker) +func TestSyncletNamespaceGKE(t *testing.T) { + f := newBDFixtureWithUpdateMode(t, k8s.EnvGKE, container.RuntimeDocker, buildcontrol.UpdateModeSynclet) defer f.TearDown() - manifest := NewSanchoLiveUpdateManifestWithTriggeredRuns(f, true) - changed := f.WriteFile("a.txt", "a") // matches one run trigger, not the other + assert.Equal(t, "", string(f.sCli.Namespace)) + assert.Equal(t, "", string(f.k8s.LastPodQueryNamespace)) + manifest := NewSanchoLiveUpdateManifest(f) targets := buildTargets(manifest) - bs := resultToStateSet(alreadyBuiltSet, []string{changed}, testContainerInfo) - result, err := f.bd.BuildAndDeploy(f.ctx, f.st, targets, bs) + result, err := f.bd.BuildAndDeploy(f.ctx, f.st, targets, store.BuildStateSet{}) if err != nil { t.Fatal(err) } - if f.docker.BuildCount != 0 { - t.Errorf("Expected no docker build, actual: %d", f.docker.BuildCount) - } - if f.docker.PushCount != 0 { - t.Errorf("Expected no push to docker, actual: %d", f.docker.PushCount) - } - if f.docker.CopyCount != 1 { - t.Errorf("Expected 1 copy to docker container call, actual: %d", f.docker.CopyCount) - } - if len(f.docker.ExecCalls) != 2 { - t.Errorf("Expected 2 exec in container calls, actual: %d", len(f.docker.ExecCalls)) - } - f.assertContainerRestarts(1) - - id := manifest.ImageTargetAt(0).ID() - _, hasResult := result[id] - assert.True(t, hasResult) - assert.Equal(t, k8s.MagicTestContainerID, result.OneAndOnlyLiveUpdatedContainerID().String()) -} - -func TestContainerBuildSyncletTriggeredRuns(t *testing.T) { - f := newBDFixture(t, k8s.EnvGKE, container.RuntimeDocker) - defer f.TearDown() - - manifest := NewSanchoLiveUpdateManifestWithTriggeredRuns(f, true) - changed := f.WriteFile("a.txt", "a") // matches one run trigger, not the other + cInfo := testContainerInfo + cInfo.Namespace = "sancho-ns" - targets := buildTargets(manifest) - bs := resultToStateSet(alreadyBuiltSet, []string{changed}, testContainerInfo) - result, err := f.bd.BuildAndDeploy(f.ctx, f.st, targets, bs) + changed := f.WriteFile("a.txt", "a") + bs := resultToStateSet(result, []string{changed}, cInfo) + _, err = f.bd.BuildAndDeploy(f.ctx, f.st, buildTargets(manifest), bs) if err != nil { t.Fatal(err) } - assert.Equal(t, 0, f.docker.BuildCount, "Expected no docker build, actual: %d", f.docker.BuildCount) - assert.Equal(t, 0, f.docker.PushCount, "Expected no push to docker, actual: %d", f.docker.PushCount) - assert.Equal(t, 1, f.sCli.UpdateContainerCount, - "Expected 1 synclet UpdateContainer call, actual: %d", f.sCli.UpdateContainerCount) - assert.Equal(t, 1, f.docker.CopyCount, - "Expected 1 docker CopyToContainer (via synclet), actual: %d", f.docker.CopyCount) - assert.Len(t, f.docker.ExecCalls, 2, - "Expected 1 docker Exec call (via synclet), actual: %d", len(f.docker.ExecCalls)) - f.assertContainerRestarts(1) - assert.Equal(t, k8s.MagicTestContainerID, result.OneAndOnlyLiveUpdatedContainerID().String()) + assert.Equal(t, "sancho-ns", string(f.sCli.Namespace)) } -func TestContainerBuildSyncletHotReload(t *testing.T) { +func TestYamlManifestDeploy(t *testing.T) { f := newBDFixture(t, k8s.EnvGKE, container.RuntimeDocker) defer f.TearDown() - manifest := NewSanchoLiveUpdateManifestWithTriggeredRuns(f, false) - changed := f.WriteFile("a.txt", "a") // matches one run trigger, not the other - bs := resultToStateSet(alreadyBuiltSet, []string{changed}, testContainerInfo) - + manifest := manifestbuilder.New(f, "some_yaml"). + WithK8sYAML(testyaml.TracerYAML).Build() targets := buildTargets(manifest) - _, err := f.bd.BuildAndDeploy(f.ctx, f.st, targets, bs) + _, err := f.bd.BuildAndDeploy(f.ctx, f.st, targets, store.BuildStateSet{}) if err != nil { t.Fatal(err) } - assert.Equal(t, 1, f.sCli.UpdateContainerCount, - "Expected 1 synclet UpdateContainer call, actual: %d", f.sCli.UpdateContainerCount) - f.assertContainerRestarts(0) -} - -func TestLiveUpdateFailure(t *testing.T) { - f := newBDFixture(t, k8s.EnvDockerDesktop, container.RuntimeDocker) - defer f.TearDown() - - changed := f.WriteFile("a.txt", "a") - bs := resultToStateSet(alreadyBuiltSet, []string{changed}, testContainerInfo) - f.docker.SetExecError(docker.ExitError{ExitCode: 1}) - - manifest := NewSanchoLiveUpdateManifest(f) - targets := buildTargets(manifest) - _, err := f.bd.BuildAndDeploy(f.ctx, f.st, targets, bs) - msg := "Run step \"go install github.com/tilt-dev/sancho\" failed with exit code: 1" - if err == nil || !strings.Contains(err.Error(), msg) { - t.Fatalf("Expected error message %q, actual: %v", msg, err) - } - - if f.docker.BuildCount != 0 { - t.Errorf("Expected no docker build, actual: %d", f.docker.BuildCount) - } - if f.docker.PushCount != 0 { - t.Errorf("Expected no push to docker, actual: %d", f.docker.PushCount) - } - if f.docker.CopyCount != 1 { - t.Errorf("Expected 1 copy to docker container call, actual: %d", f.docker.CopyCount) - } - if len(f.docker.ExecCalls) != 1 { - t.Errorf("Expected 1 exec in container call, actual: %d", len(f.docker.ExecCalls)) - } - f.assertContainerRestarts(0) + assert.Equal(t, 0, f.sCli.UpdateContainerCount) + assert.Equal(t, 0, f.docker.BuildCount) + assert.Equal(t, 0, f.docker.PushCount) + f.assertK8sUpsertCalled(true) } func TestLiveUpdateTaskKilled(t *testing.T) { @@ -570,33 +458,6 @@ func TestIgnoredFiles(t *testing.T) { }) } -func TestCustomBuildWithLiveUpdate(t *testing.T) { - f := newBDFixture(t, k8s.EnvGKE, container.RuntimeDocker) - defer f.TearDown() - sha := digest.Digest("sha256:11cd0eb38bc3ceb958ffb2f9bd70be3fb317ce7d255c8a4c3f4af30e298aa1aab") - f.docker.Images["gcr.io/some-project-162817/sancho:tilt-build-1551202573"] = types.ImageInspect{ID: string(sha)} - - manifest := NewSanchoCustomBuildManifestWithLiveUpdate(f) - targets := buildTargets(manifest) - - _, err := f.bd.BuildAndDeploy(f.ctx, f.st, targets, store.BuildStateSet{}) - if err != nil { - t.Fatal(err) - } - - if f.docker.BuildCount != 0 { - t.Errorf("Expected 0 docker build, actual: %d", f.docker.BuildCount) - } - - if f.docker.PushCount != 1 { - t.Errorf("Expected 1 push to docker, actual: %d", f.docker.PushCount) - } - - if !strings.Contains(f.k8s.Yaml, sidecar.DefaultSyncletImageName) { - t.Errorf("Should deploy the synclet for a custom build with a live update: %s", f.k8s.Yaml) - } -} - func TestCustomBuild(t *testing.T) { f := newBDFixture(t, k8s.EnvGKE, container.RuntimeDocker) defer f.TearDown() @@ -618,10 +479,6 @@ func TestCustomBuild(t *testing.T) { if f.docker.PushCount != 1 { t.Errorf("Expected 1 push to docker, actual: %d", f.docker.PushCount) } - - if strings.Contains(f.k8s.Yaml, sidecar.DefaultSyncletImageName) { - t.Errorf("Should not deploy the synclet for a custom build: %s", f.k8s.Yaml) - } } func TestCustomBuildDeterministicTag(t *testing.T) { @@ -646,10 +503,6 @@ func TestCustomBuildDeterministicTag(t *testing.T) { if f.docker.PushCount != 1 { t.Errorf("Expected 1 push to docker, actual: %d", f.docker.PushCount) } - - if strings.Contains(f.k8s.Yaml, sidecar.DefaultSyncletImageName) { - t.Errorf("Should not deploy the synclet for a custom build: %s", f.k8s.Yaml) - } } func TestContainerBuildMultiStage(t *testing.T) { @@ -704,14 +557,12 @@ func TestDockerComposeImageBuild(t *testing.T) { assert.Equal(t, 1, f.docker.BuildCount) assert.Equal(t, 0, f.docker.PushCount) - if strings.Contains(f.k8s.Yaml, sidecar.DefaultSyncletImageName) { - t.Errorf("Should not deploy the synclet for a docker-compose build: %s", f.k8s.Yaml) - } + assert.Empty(t, f.k8s.Yaml, "expect no k8s YAML for DockerCompose resource") assert.Len(t, f.dcCli.UpCalls, 1) } func TestDockerComposeLiveUpdate(t *testing.T) { - f := newBDFixture(t, k8s.EnvGKE, container.RuntimeDocker) + f := newBDFixture(t, k8s.EnvGKE, container.RuntimeContainerd) defer f.TearDown() manifest := NewSanchoLiveUpdateDCManifest(f) @@ -728,16 +579,14 @@ func TestDockerComposeLiveUpdate(t *testing.T) { assert.Equal(t, 0, f.docker.PushCount) assert.Equal(t, 1, f.docker.CopyCount) assert.Equal(t, 1, len(f.docker.ExecCalls)) - assert.Equal(t, 0, f.sCli.UpdateContainerCount, - "Expected no synclet UpdateContainer call, actual: %d", f.sCli.UpdateContainerCount) - if strings.Contains(f.k8s.Yaml, sidecar.DefaultSyncletImageName) { - t.Errorf("Should not deploy the synclet for a docker-compose build: %s", f.k8s.Yaml) - } + assert.Empty(t, f.k8s.Yaml, "expect no k8s YAML for DockerCompose resource") + assert.Empty(t, 0, f.k8s.ExecCalls, + "Expected no k8s Exec calls, actual: %d", f.k8s.ExecCalls) f.assertContainerRestarts(1) } func TestReturnLastUnexpectedError(t *testing.T) { - f := newBDFixture(t, k8s.EnvGKE, container.RuntimeDocker) + f := newBDFixture(t, k8s.EnvDockerDesktop, container.RuntimeDocker) defer f.TearDown() // next Docker build will throw an unexpected error -- this is one we want to return, @@ -801,7 +650,7 @@ func TestLiveUpdateWithRunFailureReturnsContainerIDs(t *testing.T) { } func TestLiveUpdateMultipleImagesSamePod(t *testing.T) { - f := newBDFixture(t, k8s.EnvGKE, container.RuntimeDocker) + f := newBDFixtureWithUpdateMode(t, k8s.EnvGKE, container.RuntimeDocker, buildcontrol.UpdateModeSynclet) defer f.TearDown() manifest, bs := multiImageLiveUpdateManifestAndBuildState(f) @@ -1013,6 +862,10 @@ type bdFixture struct { } func newBDFixture(t *testing.T, env k8s.Env, runtime container.Runtime) *bdFixture { + return newBDFixtureWithUpdateMode(t, env, runtime, buildcontrol.UpdateModeAuto) +} + +func newBDFixtureWithUpdateMode(t *testing.T, env k8s.Env, runtime container.Runtime, um buildcontrol.UpdateMode) *bdFixture { logs := new(bytes.Buffer) ctx, _, ta := testutils.ForkedCtxAndAnalyticsForTest(logs) ctx, cancel := context.WithCancel(ctx) @@ -1029,7 +882,7 @@ func newBDFixture(t *testing.T, env k8s.Env, runtime container.Runtime) *bdFixtu k8s := k8s.NewFakeK8sClient() k8s.Runtime = runtime sCli := synclet.NewTestSyncletClient(docker) - mode := buildcontrol.UpdateModeFlag(buildcontrol.UpdateModeAuto) + mode := buildcontrol.UpdateModeFlag(um) dcc := dockercompose.NewFakeDockerComposeClient(t, ctx) kl := &fakeKINDLoader{} bd, err := provideBuildAndDeployer(ctx, docker, k8s, dir, env, mode, sCli, dcc, fakeClock{now: time.Unix(1551202573, 0)}, kl, ta) diff --git a/internal/engine/buildcontrol/update_mode.go b/internal/engine/buildcontrol/update_mode.go index c764de6bac..333e6f4008 100644 --- a/internal/engine/buildcontrol/update_mode.go +++ b/internal/engine/buildcontrol/update_mode.go @@ -19,9 +19,6 @@ var ( // Only do image builds UpdateModeImage UpdateMode = "image" - // Only do image builds from scratch - UpdateModeNaive UpdateMode = "naive" - // Deploy a synclet to make container updates faster UpdateModeSynclet UpdateMode = "synclet" @@ -36,7 +33,6 @@ var ( var AllUpdateModes = []UpdateMode{ UpdateModeAuto, UpdateModeImage, - UpdateModeNaive, UpdateModeSynclet, UpdateModeContainer, UpdateModeKubectlExec, diff --git a/internal/engine/live_update_build_and_deployer.go b/internal/engine/live_update_build_and_deployer.go index e449fee0ee..79985c56ba 100644 --- a/internal/engine/live_update_build_and_deployer.go +++ b/internal/engine/live_update_build_and_deployer.go @@ -265,10 +265,6 @@ func (lubad *LiveUpdateBuildAndDeployer) containerUpdaterForSpecs(specs []model. return lubad.ecu } - if shouldUseSynclet(lubad.updMode, lubad.env, lubad.runtime) { - return lubad.scu - } - if lubad.runtime == container.RuntimeDocker && lubad.env.UsesLocalDockerRegistry() { return lubad.dcu }