mirror of
https://github.com/coder/coder.git
synced 2025-07-15 22:20:27 +00:00
chore: track terraform modules in telemetry (#15450)
Addresses https://github.com/coder/nexus/issues/35. This PR: - Adds a `workspace_modules` table to track modules used by the Terraform provisioner in provisioner jobs. - Adds a `module_path` column to the `workspace_resources` table, allowing to identify which module a resource originates from. - Starts pushing this new information into telemetry. For the person reviewing this PR, do not fret about the 1,500 new lines - ~1,000 of them are auto-generated.
This commit is contained in:
64
provisioner/terraform/modules.go
Normal file
64
provisioner/terraform/modules.go
Normal file
@ -0,0 +1,64 @@
|
||||
package terraform
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/coder/coder/v2/provisionersdk/proto"
|
||||
)
|
||||
|
||||
type module struct {
|
||||
Source string `json:"Source"`
|
||||
Version string `json:"Version"`
|
||||
Key string `json:"Key"`
|
||||
}
|
||||
|
||||
type modulesFile struct {
|
||||
Modules []*module `json:"Modules"`
|
||||
}
|
||||
|
||||
func getModulesFilePath(workdir string) string {
|
||||
return filepath.Join(workdir, ".terraform", "modules", "modules.json")
|
||||
}
|
||||
|
||||
func parseModulesFile(filePath string) ([]*proto.Module, error) {
|
||||
modules := &modulesFile{}
|
||||
data, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("read modules file: %w", err)
|
||||
}
|
||||
if err := json.Unmarshal(data, modules); err != nil {
|
||||
return nil, xerrors.Errorf("unmarshal modules file: %w", err)
|
||||
}
|
||||
protoModules := make([]*proto.Module, len(modules.Modules))
|
||||
for i, m := range modules.Modules {
|
||||
protoModules[i] = &proto.Module{Source: m.Source, Version: m.Version, Key: m.Key}
|
||||
}
|
||||
return protoModules, nil
|
||||
}
|
||||
|
||||
// getModules returns the modules from the modules file if it exists.
|
||||
// It returns nil if the file does not exist.
|
||||
// Modules become available after terraform init.
|
||||
func getModules(workdir string) ([]*proto.Module, error) {
|
||||
filePath := getModulesFilePath(workdir)
|
||||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
||||
return nil, nil
|
||||
}
|
||||
modules, err := parseModulesFile(filePath)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("parse modules file: %w", err)
|
||||
}
|
||||
filteredModules := []*proto.Module{}
|
||||
for _, m := range modules {
|
||||
// Empty string means root module. It's always present, so we skip it.
|
||||
if m.Source == "" {
|
||||
continue
|
||||
}
|
||||
filteredModules = append(filteredModules, m)
|
||||
}
|
||||
return filteredModules, nil
|
||||
}
|
Reference in New Issue
Block a user