mirror of
https://github.com/coder/coder.git
synced 2026-09-23 14:03:57 +08:00
> [!NOTE]
> This PR was authored by Coder Agents on behalf of @jeremyruppel.
Adds `scripts/templatebuildermodulegen/`, a Go tool that fetches module metadata from the Coder registry HTTP API and generates the `module.json` manifests and `.tf.tmpl` files used by the template builder catalog.
The generator calls `GET /api/modules/{id}` for per-module metadata (display name, description, icon, tags, variables) and the Terraform protocol versions endpoint for semver resolution. No git clone or HCL parsing required.
Split into four files:
- `main.go`: orchestration, module config map, CLI flags
- `types.go`: output types (`ModuleManifest`, `ModuleVariable`) and API response types
- `fetch.go`: HTTP fetching, version resolution, variable conversion, icon normalization
- `write.go`: JSON writer, `.tf.tmpl` Go template and writer
82 lines
1.8 KiB
Go
82 lines
1.8 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"text/template"
|
|
)
|
|
|
|
func writeModuleJSON(path string, m ModuleManifest) error {
|
|
data, err := json.MarshalIndent(m, "", " ")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
data = append(data, '\n')
|
|
return os.WriteFile(path, data, 0o600)
|
|
}
|
|
|
|
var tfTmplTemplate = template.Must(template.New("tf.tmpl").Funcs(template.FuncMap{
|
|
"hclValue": func(v ModuleVariable) string {
|
|
if v.Sensitive {
|
|
return "var." + v.Name
|
|
}
|
|
return "{{ .Variables." + v.Name + " }}"
|
|
},
|
|
}).Parse(`{{- range .SensitiveVars }}
|
|
variable "{{ .Name }}" {
|
|
description = "{{ .Description }}"
|
|
type = {{ .Type }}
|
|
sensitive = true
|
|
}
|
|
{{ end -}}
|
|
module "{{ .ID }}" {
|
|
count = data.coder_workspace.me.start_count
|
|
source = "{{"{{"}} .RegistryBase {{"}}"}}/coder/{{ .ID }}/coder"
|
|
version = "{{"{{"}} .PinnedVersion {{"}}"}}"
|
|
agent_id = coder_agent.{{"{{"}} .AgentResourceName {{"}}"}}.id
|
|
{{- range .NonComputedVars }}
|
|
{{- if .Sensitive }}
|
|
{{ .Name }} = var.{{ .Name }}
|
|
{{- else }}
|
|
{{ .Name }} = {{"{{"}} .Variables.{{ .Name }} {{"}}"}}
|
|
{{- end }}
|
|
{{- end }}
|
|
}
|
|
`))
|
|
|
|
type tfTmplData struct {
|
|
ID string
|
|
SensitiveVars []ModuleVariable
|
|
NonComputedVars []ModuleVariable
|
|
}
|
|
|
|
func writeTFTmpl(path string, m ModuleManifest) error {
|
|
var sensitiveVars []ModuleVariable
|
|
var nonComputedVars []ModuleVariable
|
|
for _, v := range m.Variables {
|
|
if v.Computed {
|
|
continue
|
|
}
|
|
nonComputedVars = append(nonComputedVars, v)
|
|
if v.Sensitive {
|
|
sensitiveVars = append(sensitiveVars, v)
|
|
}
|
|
}
|
|
|
|
data := tfTmplData{
|
|
ID: m.ID,
|
|
SensitiveVars: sensitiveVars,
|
|
NonComputedVars: nonComputedVars,
|
|
}
|
|
|
|
f, err := os.Create(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = tfTmplTemplate.Execute(f, data)
|
|
if closeErr := f.Close(); err == nil {
|
|
err = closeErr
|
|
}
|
|
return err
|
|
}
|