Skip to content

Commit 0c1eaf6

Browse files
committed
add repo mode
1 parent 88ad94f commit 0c1eaf6

File tree

2 files changed

+113
-8
lines changed

2 files changed

+113
-8
lines changed

internal/provider/cached_image_data_source.go

+8-7
Original file line numberDiff line numberDiff line change
@@ -295,13 +295,14 @@ func (d *CachedImageDataSource) Read(ctx context.Context, req datasource.ReadReq
295295
// This may require changing this to be a resource instead of a data source.
296296
opts := eboptions.Options{
297297
// These options are always required
298-
CacheRepo: data.CacheRepo.ValueString(),
299-
Filesystem: osfs.New("/"),
300-
ForceSafe: false, // This should never be set to true, as this may be running outside of a container!
301-
GetCachedImage: true, // always!
302-
Logger: tfLogFunc(ctx),
303-
Verbose: data.Verbose.ValueBool(),
304-
WorkspaceFolder: workspaceFolder,
298+
CacheRepo: data.CacheRepo.ValueString(),
299+
Filesystem: osfs.New("/"),
300+
ForceSafe: false, // This should never be set to true, as this may be running outside of a container!
301+
GetCachedImage: true, // always!
302+
Logger: tfLogFunc(ctx),
303+
Verbose: data.Verbose.ValueBool(),
304+
WorkspaceFolder: workspaceFolder,
305+
RemoteRepoBuildMode: true,
305306

306307
// Options related to compiling the devcontainer
307308
BuildContextPath: data.BuildContextPath.ValueString(),

internal/provider/provider_test.go

+105-1
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,25 +82,69 @@ 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,
@@ -81,14 +154,20 @@ func seedCache(ctx context.Context, t testing.TB, deps testDependencies) {
81154
"ENVBUILDER_INIT_SCRIPT=exit",
82155
"ENVBUILDER_PUSH_IMAGE=true",
83156
"ENVBUILDER_VERBOSE=true",
157+
fmt.Sprintf("ENVBUILDER_GIT_URL=ssh://git@localhost:%s/srv/git/repo.git", sshPort),
158+
"ENVBUILDER_GIT_SSH_PRIVATE_KEY_PATH=/tmp/ssh/id_ed25516",
84159
},
85160
Labels: map[string]string{
86161
testContainerLabel: "true",
87162
},
88163
}, &container.HostConfig{
89164
NetworkMode: container.NetworkMode("host"),
90-
Binds: []string{deps.RepoDir + ":" + "/workspaces/empty"},
165+
Binds: []string{
166+
// deps.RepoDir + ":" + "/workspaces/empty",
167+
deps.SSHDir + ":/tmp/ssh",
168+
},
91169
}, nil, nil, "")
170+
92171
require.NoError(t, err, "failed to run envbuilder to seed cache")
93172
t.Cleanup(func() {
94173
_ = cli.ContainerRemove(ctx, ctr.ID, container.RemoveOptions{
@@ -134,6 +213,8 @@ func getEnvOrDefault(env, defVal string) string {
134213
}
135214

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

0 commit comments

Comments
 (0)