github.com/grahambrereton-form3/tilt@v0.10.18/internal/engine/docker_compose_build_and_deployer_test.go (about) 1 package engine 2 3 import ( 4 "archive/tar" 5 "context" 6 "fmt" 7 "testing" 8 9 "github.com/stretchr/testify/assert" 10 11 "github.com/windmilleng/wmclient/pkg/dirs" 12 13 "github.com/windmilleng/tilt/internal/container" 14 "github.com/windmilleng/tilt/internal/docker" 15 "github.com/windmilleng/tilt/internal/dockercompose" 16 "github.com/windmilleng/tilt/internal/store" 17 "github.com/windmilleng/tilt/internal/testutils" 18 "github.com/windmilleng/tilt/internal/testutils/manifestbuilder" 19 "github.com/windmilleng/tilt/internal/testutils/tempdir" 20 "github.com/windmilleng/tilt/pkg/model" 21 ) 22 23 func TestDockerComposeTargetBuilt(t *testing.T) { 24 f := newDCBDFixture(t) 25 defer f.TearDown() 26 27 expectedContainerID := "fake-container-id" 28 f.dcCli.ContainerIdOutput = container.ID(expectedContainerID) 29 30 manifest := manifestbuilder.New(f, "fe").WithDockerCompose().Build() 31 dcTarg := manifest.DockerComposeTarget() 32 33 res, err := f.dcbad.BuildAndDeploy(f.ctx, f.st, buildTargets(manifest), store.BuildStateSet{}) 34 if err != nil { 35 t.Fatal(err) 36 } 37 if assert.Len(t, f.dcCli.UpCalls, 1, "expect one call to `docker-compose up`") { 38 call := f.dcCli.UpCalls[0] 39 assert.Equal(t, dcTarg.ConfigPaths, call.PathToConfig) 40 assert.Equal(t, "fe", call.ServiceName.String()) 41 assert.True(t, call.ShouldBuild) 42 } 43 44 dRes := res[dcTarg.ID()].(store.DockerComposeBuildResult) 45 assert.Equal(t, expectedContainerID, dRes.DockerComposeContainerID.String()) 46 } 47 48 func TestTiltBuildsImage(t *testing.T) { 49 f := newDCBDFixture(t) 50 defer f.TearDown() 51 52 iTarget := NewSanchoDockerBuildImageTarget(f) 53 manifest := manifestbuilder.New(f, "fe"). 54 WithDockerCompose(). 55 WithImageTarget(iTarget). 56 Build() 57 dcTarg := manifest.DockerComposeTarget() 58 59 res, err := f.dcbad.BuildAndDeploy(f.ctx, f.st, buildTargets(manifest), store.BuildStateSet{}) 60 if err != nil { 61 t.Fatal(err) 62 } 63 64 assert.Equal(t, 1, f.dCli.BuildCount, "expect one docker build") 65 66 expectedTag := fmt.Sprintf("%s:%s", iTarget.DeploymentRef, docker.TagLatest) 67 assert.Equal(t, expectedTag, f.dCli.TagTarget) 68 69 if assert.Len(t, f.dcCli.UpCalls, 1, "expect one call to `docker-compose up`") { 70 call := f.dcCli.UpCalls[0] 71 assert.Equal(t, dcTarg.ConfigPaths, call.PathToConfig) 72 assert.Equal(t, "fe", call.ServiceName.String()) 73 assert.False(t, call.ShouldBuild, "should call `up` without `--build` b/c Tilt is doing the building") 74 } 75 76 assert.Len(t, res, 2, "expect two results (one for each spec)") 77 } 78 79 func TestTiltBuildsImageWithTag(t *testing.T) { 80 f := newDCBDFixture(t) 81 defer f.TearDown() 82 83 refWithTag := "gcr.io/foo:bar" 84 iTarget := model.NewImageTarget(container.MustParseSelector(refWithTag)). 85 WithBuildDetails(model.DockerBuild{}) 86 manifest := manifestbuilder.New(f, "fe"). 87 WithDockerCompose(). 88 WithImageTarget(iTarget). 89 Build() 90 91 _, err := f.dcbad.BuildAndDeploy(f.ctx, f.st, buildTargets(manifest), store.BuildStateSet{}) 92 if err != nil { 93 t.Fatal(err) 94 } 95 96 assert.Equal(t, refWithTag, f.dCli.TagTarget) 97 } 98 99 func TestDCBADRejectsAllSpecsIfOneUnsupported(t *testing.T) { 100 f := newDCBDFixture(t) 101 defer f.TearDown() 102 103 specs := []model.TargetSpec{model.DockerComposeTarget{}, model.ImageTarget{}, model.K8sTarget{}} 104 105 iTarg, dcTarg := f.dcbad.extract(specs) 106 assert.Empty(t, iTarg) 107 assert.Empty(t, dcTarg) 108 } 109 110 func TestMultiStageDockerCompose(t *testing.T) { 111 f := newDCBDFixture(t) 112 defer f.TearDown() 113 114 manifest := NewSanchoDockerBuildMultiStageManifest(f). 115 WithDeployTarget(defaultDockerComposeTarget(f, "sancho")) 116 117 stateSet := store.BuildStateSet{} 118 _, err := f.dcbad.BuildAndDeploy(f.ctx, f.st, buildTargets(manifest), stateSet) 119 if err != nil { 120 t.Fatal(err) 121 } 122 123 assert.Equal(t, 2, f.dCli.BuildCount) 124 assert.Equal(t, 0, f.dCli.PushCount) 125 126 expected := expectedFile{ 127 Path: "Dockerfile", 128 Contents: ` 129 FROM sancho-base:latest 130 ADD . . 131 RUN go install github.com/windmilleng/sancho 132 ENTRYPOINT /go/bin/sancho 133 `, 134 } 135 testutils.AssertFileInTar(t, tar.NewReader(f.dCli.BuildOptions.Context), expected) 136 } 137 138 func TestMultiStageDockerComposeWithOnlyOneDirtyImage(t *testing.T) { 139 f := newDCBDFixture(t) 140 defer f.TearDown() 141 142 manifest := NewSanchoDockerBuildMultiStageManifest(f). 143 WithDeployTarget(defaultDockerComposeTarget(f, "sancho")) 144 145 iTargetID := manifest.ImageTargets[0].ID() 146 result := store.NewImageBuildResult(iTargetID, container.MustParseNamedTagged("sancho-base:tilt-prebuilt")) 147 state := store.NewBuildState(result, nil) 148 stateSet := store.BuildStateSet{iTargetID: state} 149 f.dCli.ImageListCount = 1 150 _, err := f.dcbad.BuildAndDeploy(f.ctx, f.st, buildTargets(manifest), stateSet) 151 if err != nil { 152 t.Fatal(err) 153 } 154 155 assert.Equal(t, 1, f.dCli.BuildCount) 156 assert.Equal(t, 0, f.dCli.PushCount) 157 158 expected := expectedFile{ 159 Path: "Dockerfile", 160 Contents: ` 161 FROM sancho-base:tilt-prebuilt 162 ADD . . 163 RUN go install github.com/windmilleng/sancho 164 ENTRYPOINT /go/bin/sancho 165 `, 166 } 167 testutils.AssertFileInTar(t, tar.NewReader(f.dCli.BuildOptions.Context), expected) 168 } 169 170 type dcbdFixture struct { 171 *tempdir.TempDirFixture 172 ctx context.Context 173 dcCli *dockercompose.FakeDCClient 174 dCli *docker.FakeClient 175 dcbad *DockerComposeBuildAndDeployer 176 st *store.Store 177 } 178 179 func newDCBDFixture(t *testing.T) *dcbdFixture { 180 ctx, _, _ := testutils.CtxAndAnalyticsForTest() 181 182 f := tempdir.NewTempDirFixture(t) 183 184 dir := dirs.NewWindmillDirAt(f.Path()) 185 dcCli := dockercompose.NewFakeDockerComposeClient(t, ctx) 186 dCli := docker.NewFakeClient() 187 dcbad, err := provideDockerComposeBuildAndDeployer(ctx, dcCli, dCli, dir) 188 if err != nil { 189 t.Fatal(err) 190 } 191 st, _ := store.NewStoreForTesting() 192 return &dcbdFixture{ 193 TempDirFixture: f, 194 ctx: ctx, 195 dcCli: dcCli, 196 dCli: dCli, 197 dcbad: dcbad, 198 st: st, 199 } 200 } 201 202 func defaultDockerComposeTarget(f Fixture, name string) model.DockerComposeTarget { 203 return model.DockerComposeTarget{ 204 Name: model.TargetName(name), 205 ConfigPaths: []string{f.JoinPath("docker-compose.yml")}, 206 } 207 }