mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: add GET /api/v2/templatebuilder/modules endpoint (#26117)
Implement `GET /api/v2/templatebuilder/modules`, which returns the filtered list of modules available for a given base template. Reads from the bundled catalog via `LoadModules()` and applies OS-compatibility filtering based on the `base` query param. Computed variables (e.g. `agent_id`) are excluded from the API response at the `ToSDK()` conversion boundary since they are wired automatically by the builder. The `Computed` field is removed from the SDK type. Adds `CompatibleWithOS()` to `ModuleManifest` for OS filtering. Returns 400 for unknown base IDs and 404 when the template builder is disabled. Depends on #26116 > [!NOTE] > This PR was authored by Coder Agents on behalf of @jeremyruppel.
This commit is contained in:
@@ -81,3 +81,107 @@ func TestTemplateBuilderBases(t *testing.T) {
|
||||
require.Equal(t, http.StatusNotFound, sdkErr.StatusCode())
|
||||
})
|
||||
}
|
||||
|
||||
func TestTemplateBuilderModules(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("OK", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
_ = coderdtest.CreateFirstUser(t, client)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
resp, err := client.TemplateBuilderModules(ctx, "")
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, resp.Modules)
|
||||
|
||||
for _, m := range resp.Modules {
|
||||
require.NotEmpty(t, m.ID)
|
||||
require.NotEmpty(t, m.Version)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("FilteredByBase", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
_ = coderdtest.CreateFirstUser(t, client)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
resp, err := client.TemplateBuilderModules(ctx, "docker")
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, m := range resp.Modules {
|
||||
if len(m.CompatibleOS) > 0 {
|
||||
require.Contains(t, m.CompatibleOS, "linux",
|
||||
"module %q should be compatible with linux when filtered by docker base", m.ID)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ComputedVariablesExcluded", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
_ = coderdtest.CreateFirstUser(t, client)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
resp, err := client.TemplateBuilderModules(ctx, "")
|
||||
require.NoError(t, err)
|
||||
|
||||
// The embedded code-server module has agent_id with computed=true.
|
||||
// It must not appear in the API response.
|
||||
var found bool
|
||||
for _, m := range resp.Modules {
|
||||
if m.ID == "code-server" {
|
||||
found = true
|
||||
for _, v := range m.Variables {
|
||||
require.NotEqual(t, "agent_id", v.Name,
|
||||
"computed variable agent_id must not appear in API response")
|
||||
}
|
||||
}
|
||||
}
|
||||
require.True(t, found, "code-server module must be in the catalog")
|
||||
})
|
||||
|
||||
t.Run("UnknownBaseReturns400", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
_ = coderdtest.CreateFirstUser(t, client)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
_, err := client.TemplateBuilderModules(ctx, "nonexistent")
|
||||
require.Error(t, err)
|
||||
|
||||
var sdkErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &sdkErr)
|
||||
require.Equal(t, http.StatusBadRequest, sdkErr.StatusCode())
|
||||
})
|
||||
|
||||
t.Run("DisabledReturns404", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
dv := coderdtest.DeploymentValues(t)
|
||||
dv.TemplateBuilder.Disabled = true
|
||||
|
||||
client := coderdtest.New(t, &coderdtest.Options{
|
||||
DeploymentValues: dv,
|
||||
})
|
||||
_ = coderdtest.CreateFirstUser(t, client)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
_, err := client.TemplateBuilderModules(ctx, "")
|
||||
require.Error(t, err)
|
||||
|
||||
var sdkErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &sdkErr)
|
||||
require.Equal(t, http.StatusNotFound, sdkErr.StatusCode())
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user