Skip to content

Commit 58c0b94

Browse files
committed
add git cloning
1 parent 74d4580 commit 58c0b94

File tree

4 files changed

+119
-33
lines changed

4 files changed

+119
-33
lines changed

go.mod

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ replace tailscale.com => github.com/coder/tailscale v1.1.1-0.20240702054557-aa55
1010

1111
require (
1212
github.com/GoogleContainerTools/kaniko v1.9.2
13-
github.com/coder/envbuilder v1.0.0-rc.0.0.20240731115920-cacbcb8fef6c
13+
github.com/coder/envbuilder v1.0.0-rc.0.0.20240802153943-5063d1b2ffa0
1414
github.com/docker/docker v26.1.4+incompatible
15+
github.com/docker/go-connections v0.5.0
1516
github.com/go-git/go-billy/v5 v5.5.0
17+
github.com/go-git/go-git/v5 v5.12.0
1618
github.com/google/go-containerregistry v0.19.1
1719
github.com/hashicorp/terraform-plugin-docs v0.19.4
1820
github.com/hashicorp/terraform-plugin-framework v1.10.0
@@ -115,7 +117,6 @@ require (
115117
github.com/docker/cli v26.1.0+incompatible // indirect
116118
github.com/docker/distribution v2.8.2+incompatible // indirect
117119
github.com/docker/docker-credential-helpers v0.8.1 // indirect
118-
github.com/docker/go-connections v0.5.0 // indirect
119120
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
120121
github.com/docker/go-metrics v0.0.1 // indirect
121122
github.com/docker/go-units v0.5.0 // indirect
@@ -128,7 +129,6 @@ require (
128129
github.com/fxamacker/cbor/v2 v2.4.0 // indirect
129130
github.com/go-chi/chi/v5 v5.0.10 // indirect
130131
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
131-
github.com/go-git/go-git/v5 v5.12.0 // indirect
132132
github.com/go-jose/go-jose/v4 v4.0.1 // indirect
133133
github.com/go-logr/logr v1.4.1 // indirect
134134
github.com/go-logr/stdr v1.2.2 // indirect

go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,8 @@ github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoC
186186
github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI=
187187
github.com/coder/coder/v2 v2.10.1-0.20240704130443-c2d44d16a352 h1:L/EjCuZxs5tOcqqCaASj/nu65TRYEFcTt8qRQfHZXX0=
188188
github.com/coder/coder/v2 v2.10.1-0.20240704130443-c2d44d16a352/go.mod h1:P1KoQSgnKEAG6Mnd3YlGzAophty+yKA9VV48LpfNRvo=
189-
github.com/coder/envbuilder v1.0.0-rc.0.0.20240731115920-cacbcb8fef6c h1:wb+i7vP0pl4R4r66dDRK7no86hFfPY+G/tCq8R9M+Cw=
190-
github.com/coder/envbuilder v1.0.0-rc.0.0.20240731115920-cacbcb8fef6c/go.mod h1:APdfhjDHEF5gkAyhn+9MoCem+qKS84iRkNQ5mBZsajQ=
189+
github.com/coder/envbuilder v1.0.0-rc.0.0.20240802153943-5063d1b2ffa0 h1:u38vVzEjaFq0or5ooaymKGPlmLH316kePJk/QL4J2bs=
190+
github.com/coder/envbuilder v1.0.0-rc.0.0.20240802153943-5063d1b2ffa0/go.mod h1:Ta/kWidN9AfB6bCB/1Cx0q+uQqCqFKgzKF2YXj+aGAg=
191191
github.com/coder/kaniko v0.0.0-20240717115058-0ba2908ca4d3 h1:Q7L6cjKfw3DIyhKIcgCJEmgxnUTBajmMDrHxXvxgBZs=
192192
github.com/coder/kaniko v0.0.0-20240717115058-0ba2908ca4d3/go.mod h1:YMK7BlxerzLlMwihGxNWUaFoN9LXCij4P+w/8/fNlcM=
193193
github.com/coder/pretty v0.0.0-20230908205945-e89ba86370e0 h1:3A0ES21Ke+FxEM8CXx9n47SZOKOpgSE1bbJzlE4qPVs=

internal/provider/cached_image_data_source.go

+8-24
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import (
1313
kconfig "github.com/GoogleContainerTools/kaniko/pkg/config"
1414
"github.com/coder/envbuilder"
1515
"github.com/coder/envbuilder/constants"
16-
ebgit "github.com/coder/envbuilder/git"
1716
eblog "github.com/coder/envbuilder/log"
1817
eboptions "github.com/coder/envbuilder/options"
1918
"github.com/go-git/go-billy/v5/osfs"
@@ -269,13 +268,14 @@ func (d *CachedImageDataSource) Read(ctx context.Context, req datasource.ReadReq
269268
// This may require changing this to be a resource instead of a data source.
270269
opts := eboptions.Options{
271270
// These options are always required
272-
CacheRepo: data.CacheRepo.ValueString(),
273-
Filesystem: osfs.New("/"),
274-
ForceSafe: false, // This should never be set to true, as this may be running outside of a container!
275-
GetCachedImage: true, // always!
276-
Logger: tfLogFunc(ctx),
277-
Verbose: data.Verbose.ValueBool(),
278-
WorkspaceFolder: tmpDir,
271+
CacheRepo: data.CacheRepo.ValueString(),
272+
Filesystem: osfs.New("/"),
273+
ForceSafe: false, // This should never be set to true, as this may be running outside of a container!
274+
GetCachedImage: true, // always!
275+
Logger: tfLogFunc(ctx),
276+
Verbose: data.Verbose.ValueBool(),
277+
WorkspaceFolder: tmpDir,
278+
RemoteRepoBuildMode: true,
279279

280280
// Options related to compiling the devcontainer
281281
BuildContextPath: data.BuildContextPath.ValueString(),
@@ -316,22 +316,6 @@ func (d *CachedImageDataSource) Read(ctx context.Context, req datasource.ReadReq
316316
SkipRebuild: false,
317317
}
318318

319-
cloneOpts, err := ebgit.CloneOptionsFromOptions(opts)
320-
if err != nil {
321-
resp.Diagnostics.AddError("Failed to create git clone options", err.Error())
322-
return
323-
}
324-
325-
w := ebgit.ProgressWriter(func(line string) { tflog.Info(ctx, line) })
326-
defer w.Close()
327-
cloneOpts.Progress = w
328-
329-
err = ebgit.ShallowCloneRepo(ctx, cloneOpts)
330-
if err != nil {
331-
resp.Diagnostics.AddError("Failed to clone git repository", err.Error())
332-
return
333-
}
334-
335319
image, err := envbuilder.RunCacheProbe(ctx, opts)
336320
data.Exists = types.BoolValue(err == nil)
337321
if err != nil {

internal/provider/provider_test.go

+106-4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package provider
66
import (
77
"bufio"
88
"context"
9+
"fmt"
910
"io"
1011
"os"
1112
"path/filepath"
@@ -14,19 +15,45 @@ import (
1415
"testing"
1516

1617
"github.com/coder/terraform-provider-envbuilder/testutil/registrytest"
18+
"github.com/go-git/go-git/v5"
19+
"github.com/go-git/go-git/v5/plumbing"
20+
"github.com/go-git/go-git/v5/plumbing/object"
1721
"github.com/hashicorp/terraform-plugin-framework/providerserver"
1822
"github.com/hashicorp/terraform-plugin-go/tfprotov6"
1923

2024
"github.com/docker/docker/api/types/container"
2125
"github.com/docker/docker/api/types/image"
2226
"github.com/docker/docker/client"
27+
"github.com/docker/go-connections/nat"
2328
"github.com/stretchr/testify/require"
2429
)
2530

2631
const (
2732
testContainerLabel = "terraform-provider-envbuilder-test"
2833
)
2934

35+
// nolint:gosec // Throw-away key for testing. DO NOT REUSE.
36+
const (
37+
testSSHHostKey = `-----BEGIN OPENSSH PRIVATE KEY-----
38+
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
39+
QyNTUxOQAAACDBC7DRHALRN3JJrkDQETyL2Vg5O6QsWTE2YWAt9bIZiAAAAKj5O8yU+TvM
40+
lAAAAAtzc2gtZWQyNTUxOQAAACDBC7DRHALRN3JJrkDQETyL2Vg5O6QsWTE2YWAt9bIZiA
41+
AAAED9b0qGgjoDx9YiyCHGBE6ogdnD6IbQsgfaFDI0aE+x3cELsNEcAtE3ckmuQNARPIvZ
42+
WDk7pCxZMTZhYC31shmIAAAAInRlcnJhZm9ybS1wcm92aWRlci1lbnZidWlsZGVyLXRlc3
43+
QBAgM=
44+
-----END OPENSSH PRIVATE KEY-----`
45+
testSSHHostPubKey = `ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMELsNEcAtE3ckmuQNARPIvZWDk7pCxZMTZhYC31shmI terraform-provider-envbuilder-test`
46+
testSSHUserKey = `-----BEGIN OPENSSH PRIVATE KEY-----
47+
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
48+
QyNTUxOQAAACCtxz9h0yXzi/HqZBpSkA2xFo28v5W8O4HimI0ZzNpQkwAAAKhv/+X2b//l
49+
9gAAAAtzc2gtZWQyNTUxOQAAACCtxz9h0yXzi/HqZBpSkA2xFo28v5W8O4HimI0ZzNpQkw
50+
AAAED/G0HuohvSa8q6NzkZ+wRPW0PhPpo9Th8fvcBQDaxCia3HP2HTJfOL8epkGlKQDbEW
51+
jby/lbw7geKYjRnM2lCTAAAAInRlcnJhZm9ybS1wcm92aWRlci1lbnZidWlsZGVyLXRlc3
52+
QBAgM=
53+
-----END OPENSSH PRIVATE KEY-----`
54+
testSSHUserPubKey = `ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK3HP2HTJfOL8epkGlKQDbEWjby/lbw7geKYjRnM2lCT terraform-provider-envbuilder-test`
55+
)
56+
3057
// testAccProtoV6ProviderFactories are used to instantiate a provider during
3158
// acceptance testing. The factory function will be invoked for every Terraform
3259
// CLI command executed to create a provider server to which the CLI can
@@ -45,6 +72,8 @@ type testDependencies struct {
4572
BuilderImage string
4673
RepoDir string
4774
CacheRepo string
75+
GitImage string
76+
SSHDir string
4877
}
4978

5079
func setup(t testing.TB, files map[string]string) testDependencies {
@@ -53,44 +82,93 @@ func setup(t testing.TB, files map[string]string) testDependencies {
5382
envbuilderImage := getEnvOrDefault("ENVBUILDER_IMAGE", "ghcr.io/coder/envbuilder-preview")
5483
envbuilderVersion := getEnvOrDefault("ENVBUILDER_VERSION", "latest")
5584
envbuilderImageRef := envbuilderImage + ":" + envbuilderVersion
85+
gitImageRef := "rockstorm/git-server:2.45"
5686

5787
// TODO: envbuilder creates /.envbuilder/bin/envbuilder owned by root:root which we are unable to clean up.
5888
// This causes tests to fail.
5989
repoDir := t.TempDir()
6090
regDir := t.TempDir()
6191
reg := registrytest.New(t, regDir)
6292
writeFiles(t, files, repoDir)
93+
initGitRepo(t, repoDir)
94+
95+
sshDir := t.TempDir()
96+
writeFiles(t, map[string]string{
97+
"id_ed25516": testSSHUserKey,
98+
"authorized_keys": testSSHUserPubKey,
99+
}, sshDir)
100+
63101
return testDependencies{
64102
BuilderImage: envbuilderImageRef,
65103
CacheRepo: reg + "/test",
66104
RepoDir: repoDir,
105+
GitImage: gitImageRef,
106+
SSHDir: sshDir,
67107
}
68108
}
69109

70110
func seedCache(ctx context.Context, t testing.TB, deps testDependencies) {
71111
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
72112
require.NoError(t, err, "init docker client")
73113
t.Cleanup(func() { _ = cli.Close() })
114+
115+
ensureImage(ctx, t, cli, deps.GitImage)
74116
ensureImage(ctx, t, cli, deps.BuilderImage)
117+
118+
// TODO(mafredri): Use a dynamic port?
119+
sshPort := "2222"
120+
121+
gitCtr, err := cli.ContainerCreate(ctx, &container.Config{
122+
Image: deps.GitImage,
123+
Env: []string{
124+
"SSH_AUTH_METHODS=publickey",
125+
},
126+
Labels: map[string]string{
127+
testContainerLabel: "true",
128+
},
129+
}, &container.HostConfig{
130+
PortBindings: nat.PortMap{
131+
"22/tcp": []nat.PortBinding{{HostIP: "localhost", HostPort: sshPort}},
132+
},
133+
Binds: []string{
134+
deps.RepoDir + ":/srv/git/repo.git",
135+
deps.SSHDir + ":/home/git/.ssh",
136+
},
137+
}, nil, nil, "")
138+
require.NoError(t, err, "failed to run git server")
139+
t.Cleanup(func() {
140+
_ = cli.ContainerRemove(ctx, gitCtr.ID, container.RemoveOptions{
141+
RemoveVolumes: true,
142+
Force: true,
143+
})
144+
})
145+
err = cli.ContainerStart(ctx, gitCtr.ID, container.StartOptions{})
146+
require.NoError(t, err)
147+
75148
// Run envbuilder using this dir as a local layer cache
76149
ctr, err := cli.ContainerCreate(ctx, &container.Config{
77150
Image: deps.BuilderImage,
78151
Env: []string{
79152
"ENVBUILDER_CACHE_REPO=" + deps.CacheRepo,
80-
"ENVBUILDER_DEVCONTAINER_DIR=" + deps.RepoDir,
81153
"ENVBUILDER_EXIT_ON_BUILD_FAILURE=true",
82154
"ENVBUILDER_INIT_SCRIPT=exit",
155+
fmt.Sprintf("ENVBUILDER_GIT_URL=ssh://git@localhost:%s/srv/git/repo.git", sshPort),
156+
"ENVBUILDER_GIT_SSH_PRIVATE_KEY_PATH=/tmp/ssh/id_ed25516",
83157
// FIXME: Enabling this options causes envbuilder to add its binary to the image under the path
84158
// /.envbuilder/bin/envbuilder. This file will have ownership root:root and permissions 0o755.
85159
// Because of this, t.Cleanup() will be unable to delete the temp dir, causing the test to fail.
86160
// "ENVBUILDER_PUSH_IMAGE=true",
87161
},
88162
Labels: map[string]string{
89163
testContainerLabel: "true",
90-
}}, &container.HostConfig{
164+
},
165+
}, &container.HostConfig{
91166
NetworkMode: container.NetworkMode("host"),
92-
Binds: []string{deps.RepoDir + ":" + deps.RepoDir},
167+
Binds: []string{
168+
deps.SSHDir + ":/tmp/ssh",
169+
},
93170
}, nil, nil, "")
171+
94172
require.NoError(t, err, "failed to run envbuilder to seed cache")
95173
t.Cleanup(func() {
96174
_ = cli.ContainerRemove(ctx, ctr.ID, container.RemoveOptions{
@@ -126,7 +204,6 @@ SCANLOGS:
126204
}
127205
}
128206
}
129-
130207
}
131208

132209
func getEnvOrDefault(env, defVal string) string {
@@ -137,6 +214,8 @@ func getEnvOrDefault(env, defVal string) string {
137214
}
138215

139216
func writeFiles(t testing.TB, files map[string]string, destPath string) {
217+
t.Helper()
218+
140219
for relPath, content := range files {
141220
absPath := filepath.Join(destPath, relPath)
142221
d := filepath.Dir(absPath)
@@ -165,3 +244,26 @@ func ensureImage(ctx context.Context, t testing.TB, cli *client.Client, ref stri
165244
_, err = io.ReadAll(resp)
166245
require.NoError(t, err)
167246
}
247+
248+
func initGitRepo(t testing.TB, dir string) {
249+
t.Helper()
250+
251+
repo, err := git.PlainInitWithOptions(dir, &git.PlainInitOptions{
252+
InitOptions: git.InitOptions{
253+
DefaultBranch: plumbing.ReferenceName("refs/heads/main"),
254+
},
255+
})
256+
require.NoError(t, err, "init git repo")
257+
wt, err := repo.Worktree()
258+
require.NoError(t, err, "get worktree")
259+
_, err = wt.Add(".")
260+
require.NoError(t, err, "add files")
261+
_, err = wt.Commit("initial commit", &git.CommitOptions{
262+
Author: &object.Signature{
263+
Name: "test",
264+
265+
},
266+
})
267+
require.NoError(t, err, "commit files")
268+
t.Logf("initialized git repo at %s", dir)
269+
}

0 commit comments

Comments
 (0)