fix: revert fix: persist terraform modules during template import (#17665) (#17734)

This reverts commit ae3d90b057.
This commit is contained in:
Jon Ayers
2025-05-08 22:03:08 -04:00
committed by GitHub
parent ae3d90b057
commit a9f1a6b2a2
27 changed files with 229 additions and 587 deletions
+1 -3
View File
@@ -52,8 +52,7 @@ var (
PlanComplete = []*proto.Response{{
Type: &proto.Response_Plan{
Plan: &proto.PlanComplete{
Plan: []byte("{}"),
ModuleFiles: []byte{},
Plan: []byte("{}"),
},
},
}}
@@ -250,7 +249,6 @@ func TarWithOptions(ctx context.Context, logger slog.Logger, responses *Response
Parameters: resp.GetApply().GetParameters(),
ExternalAuthProviders: resp.GetApply().GetExternalAuthProviders(),
Plan: []byte("{}"),
ModuleFiles: []byte{},
}},
})
}
-7
View File
@@ -307,12 +307,6 @@ func (e *executor) plan(ctx, killCtx context.Context, env, vars []string, logr l
graphTimings.ingest(createGraphTimingsEvent(timingGraphComplete))
moduleFiles, err := getModulesArchive(e.workdir)
if err != nil {
// TODO: we probably want to persist this error or make it louder eventually
e.logger.Warn(ctx, "failed to archive terraform modules", slog.Error(err))
}
return &proto.PlanComplete{
Parameters: state.Parameters,
Resources: state.Resources,
@@ -320,7 +314,6 @@ func (e *executor) plan(ctx, killCtx context.Context, env, vars []string, logr l
Timings: append(e.timings.aggregate(), graphTimings.aggregate()...),
Presets: state.Presets,
Plan: plan,
ModuleFiles: moduleFiles,
}, nil
}
+1 -67
View File
@@ -1,13 +1,9 @@
package terraform
import (
"archive/tar"
"bytes"
"encoding/json"
"io/fs"
"os"
"path/filepath"
"strings"
"golang.org/x/xerrors"
@@ -24,12 +20,8 @@ type modulesFile struct {
Modules []*module `json:"Modules"`
}
func getModulesDirectory(workdir string) string {
return filepath.Join(workdir, ".terraform", "modules")
}
func getModulesFilePath(workdir string) string {
return filepath.Join(getModulesDirectory(workdir), "modules.json")
return filepath.Join(workdir, ".terraform", "modules", "modules.json")
}
func parseModulesFile(filePath string) ([]*proto.Module, error) {
@@ -70,61 +62,3 @@ func getModules(workdir string) ([]*proto.Module, error) {
}
return filteredModules, nil
}
func getModulesArchive(workdir string) ([]byte, error) {
modulesDir := getModulesDirectory(workdir)
if _, err := os.ReadDir(modulesDir); err != nil {
if os.IsNotExist(err) {
return []byte{}, nil
}
return nil, err
}
empty := true
var b bytes.Buffer
w := tar.NewWriter(&b)
err := filepath.WalkDir(modulesDir, func(filePath string, info fs.DirEntry, err error) error {
if err != nil {
return xerrors.Errorf("failed to create modules archive: %w", err)
}
if info.IsDir() {
return nil
}
archivePath, found := strings.CutPrefix(filePath, workdir+string(os.PathSeparator))
if !found {
return xerrors.Errorf("walked invalid file path: %q", filePath)
}
content, err := os.ReadFile(filePath)
if err != nil {
return xerrors.Errorf("failed to read module file while archiving: %w", err)
}
empty = false
err = w.WriteHeader(&tar.Header{
Name: archivePath,
Size: int64(len(content)),
Mode: 0o644,
Uid: 1000,
Gid: 1000,
})
if err != nil {
return xerrors.Errorf("failed to add module file to archive: %w", err)
}
if _, err = w.Write(content); err != nil {
return xerrors.Errorf("failed to write module file to archive: %w", err)
}
return nil
})
if err != nil {
return nil, err
}
err = w.Close()
if err != nil {
return nil, xerrors.Errorf("failed to close module files archive: %w", err)
}
// Don't persist empty tar files in the database
if empty {
return []byte{}, nil
}
return b.Bytes(), nil
}
@@ -1,47 +0,0 @@
package terraform
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"io/fs"
"path/filepath"
"runtime"
"strings"
"testing"
"github.com/stretchr/testify/require"
archivefs "github.com/coder/coder/v2/archive/fs"
)
// The .tar archive is different on Windows because of git converting LF line
// endings to CRLF line endings, so many of the assertions in this test are
// platform specific.
func TestGetModulesArchive(t *testing.T) {
t.Parallel()
archive, err := getModulesArchive(filepath.Join("testdata", "modules-source-caching"))
require.NoError(t, err)
// Check that all of the files it should contain are correct
r := bytes.NewBuffer(archive)
tarfs := archivefs.FromTarReader(r)
content, err := fs.ReadFile(tarfs, ".terraform/modules/example_module/main.tf")
require.NoError(t, err)
require.True(t, strings.HasPrefix(string(content), "terraform {"))
if runtime.GOOS != "windows" {
require.Len(t, content, 3691)
} else {
require.Len(t, content, 3812)
}
// It should always be byte-identical to optimize storage
hashBytes := sha256.Sum256(archive)
hash := hex.EncodeToString(hashBytes[:])
if runtime.GOOS != "windows" {
require.Equal(t, "05d2994c1a50ce573fe2c2b29507e5131ba004d15812d8bb0a46dc732f3211f5", hash)
} else {
require.Equal(t, "0001fc95ac0ac18188931db2ef28c42f51919ee24bc18482fab38d1ea9c7a4e8", hash)
}
}
@@ -1,121 +0,0 @@
terraform {
required_version = ">= 1.0"
required_providers {
coder = {
source = "coder/coder"
version = ">= 0.12"
}
}
}
variable "url" {
description = "The URL of the Git repository."
type = string
}
variable "base_dir" {
default = ""
description = "The base directory to clone the repository. Defaults to \"$HOME\"."
type = string
}
variable "agent_id" {
description = "The ID of a Coder agent."
type = string
}
variable "git_providers" {
type = map(object({
provider = string
}))
description = "A mapping of URLs to their git provider."
default = {
"https://github.com/" = {
provider = "github"
},
"https://gitlab.com/" = {
provider = "gitlab"
},
}
validation {
error_message = "Allowed values for provider are \"github\" or \"gitlab\"."
condition = alltrue([for provider in var.git_providers : contains(["github", "gitlab"], provider.provider)])
}
}
variable "branch_name" {
description = "The branch name to clone. If not provided, the default branch will be cloned."
type = string
default = ""
}
variable "folder_name" {
description = "The destination folder to clone the repository into."
type = string
default = ""
}
locals {
# Remove query parameters and fragments from the URL
url = replace(replace(var.url, "/\\?.*/", ""), "/#.*/", "")
# Find the git provider based on the URL and determine the tree path
provider_key = try(one([for key in keys(var.git_providers) : key if startswith(local.url, key)]), null)
provider = try(lookup(var.git_providers, local.provider_key).provider, "")
tree_path = local.provider == "gitlab" ? "/-/tree/" : local.provider == "github" ? "/tree/" : ""
# Remove tree and branch name from the URL
clone_url = var.branch_name == "" && local.tree_path != "" ? replace(local.url, "/${local.tree_path}.*/", "") : local.url
# Extract the branch name from the URL
branch_name = var.branch_name == "" && local.tree_path != "" ? replace(replace(local.url, local.clone_url, ""), "/.*${local.tree_path}/", "") : var.branch_name
# Extract the folder name from the URL
folder_name = var.folder_name == "" ? replace(basename(local.clone_url), ".git", "") : var.folder_name
# Construct the path to clone the repository
clone_path = var.base_dir != "" ? join("/", [var.base_dir, local.folder_name]) : join("/", ["~", local.folder_name])
# Construct the web URL
web_url = startswith(local.clone_url, "git@") ? replace(replace(local.clone_url, ":", "/"), "git@", "https://") : local.clone_url
}
output "repo_dir" {
value = local.clone_path
description = "Full path of cloned repo directory"
}
output "git_provider" {
value = local.provider
description = "The git provider of the repository"
}
output "folder_name" {
value = local.folder_name
description = "The name of the folder that will be created"
}
output "clone_url" {
value = local.clone_url
description = "The exact Git repository URL that will be cloned"
}
output "web_url" {
value = local.web_url
description = "Git https repository URL (may be invalid for unsupported providers)"
}
output "branch_name" {
value = local.branch_name
description = "Git branch name (may be empty)"
}
resource "coder_script" "git_clone" {
agent_id = var.agent_id
script = templatefile("${path.module}/run.sh", {
CLONE_PATH = local.clone_path,
REPO_URL : local.clone_url,
BRANCH_NAME : local.branch_name,
})
display_name = "Git Clone"
icon = "/icon/git.svg"
run_on_start = true
start_blocks_login = true
}
@@ -1 +0,0 @@
{"Modules":[{"Key":"","Source":"","Dir":"."},{"Key":"example_module","Source":"example_module","Dir":".terraform/modules/example_module"}]}