Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita03b14b

Browse files
committed
endpoint
1 parentde74ccf commita03b14b

File tree

5 files changed

+249
-13
lines changed

5 files changed

+249
-13
lines changed

‎coderd/coderd.go

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1368,19 +1368,24 @@ func New(options *Options) *API {
13681368
r.Get("/timings",api.workspaceTimings)
13691369
})
13701370
})
1371-
r.Route("/workspacebuilds/{workspacebuild}",func(r chi.Router) {
1372-
r.Use(
1373-
apiKeyMiddleware,
1374-
httpmw.ExtractWorkspaceBuildParam(options.Database),
1375-
httpmw.ExtractWorkspaceParam(options.Database),
1376-
)
1377-
r.Get("/",api.workspaceBuild)
1378-
r.Patch("/cancel",api.patchCancelWorkspaceBuild)
1379-
r.Get("/logs",api.workspaceBuildLogs)
1380-
r.Get("/parameters",api.workspaceBuildParameters)
1381-
r.Get("/resources",api.workspaceBuildResourcesDeprecated)
1382-
r.Get("/state",api.workspaceBuildState)
1383-
r.Get("/timings",api.workspaceBuildTimings)
1371+
r.Route("/workspacebuilds",func(r chi.Router) {
1372+
r.Use(apiKeyMiddleware)
1373+
// Bulk endpoint for getting parameters for multiple builds
1374+
r.Get("/parameters",api.workspaceBuildParametersBulk)
1375+
1376+
r.Route("/{workspacebuild}",func(r chi.Router) {
1377+
r.Use(
1378+
httpmw.ExtractWorkspaceBuildParam(options.Database),
1379+
httpmw.ExtractWorkspaceParam(options.Database),
1380+
)
1381+
r.Get("/",api.workspaceBuild)
1382+
r.Patch("/cancel",api.patchCancelWorkspaceBuild)
1383+
r.Get("/logs",api.workspaceBuildLogs)
1384+
r.Get("/parameters",api.workspaceBuildParameters)
1385+
r.Get("/resources",api.workspaceBuildResourcesDeprecated)
1386+
r.Get("/state",api.workspaceBuildState)
1387+
r.Get("/timings",api.workspaceBuildTimings)
1388+
})
13841389
})
13851390
r.Route("/authcheck",func(r chi.Router) {
13861391
r.Use(apiKeyMiddleware)

‎coderd/workspacebuilds.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"slices"
1111
"sort"
1212
"strconv"
13+
"strings"
1314
"time"
1415

1516
"github.com/go-chi/chi/v5"
@@ -676,6 +677,65 @@ func (api *API) workspaceBuildParameters(rw http.ResponseWriter, r *http.Request
676677
httpapi.Write(ctx,rw,http.StatusOK,apiParameters)
677678
}
678679

680+
// @Summary Get build parameters for multiple workspace builds
681+
// @ID get-build-parameters-for-workspace-builds-bulk
682+
// @Security CoderSessionToken
683+
// @Produce json
684+
// @Tags Builds
685+
// @Param build_ids query string true "Comma-separated workspace build IDs"
686+
// @Success 200 {object} map[string][]codersdk.WorkspaceBuildParameter
687+
// @Router /workspacebuilds/parameters [get]
688+
func (api*API)workspaceBuildParametersBulk(rw http.ResponseWriter,r*http.Request) {
689+
ctx:=r.Context()
690+
691+
buildIDsParam:=r.URL.Query().Get("build_ids")
692+
ifbuildIDsParam=="" {
693+
httpapi.Write(ctx,rw,http.StatusBadRequest, codersdk.Response{
694+
Message:"build_ids query parameter is required",
695+
})
696+
return
697+
}
698+
699+
// Parse build IDs
700+
buildIDStrings:=strings.Split(buildIDsParam,",")
701+
buildIDs:=make([]uuid.UUID,0,len(buildIDStrings))
702+
for_,idStr:=rangebuildIDStrings {
703+
id,err:=uuid.Parse(strings.TrimSpace(idStr))
704+
iferr!=nil {
705+
httpapi.Write(ctx,rw,http.StatusBadRequest, codersdk.Response{
706+
Message:"Invalid build ID format",
707+
Detail:err.Error(),
708+
})
709+
return
710+
}
711+
buildIDs=append(buildIDs,id)
712+
}
713+
714+
parameters,err:=api.Database.GetWorkspaceBuildParametersByBuildIDs(ctx,buildIDs)
715+
iferr!=nil {
716+
httpapi.Write(ctx,rw,http.StatusInternalServerError, codersdk.Response{
717+
Message:"Internal error fetching workspace build parameters.",
718+
Detail:err.Error(),
719+
})
720+
return
721+
}
722+
723+
// Group parameters by build ID
724+
parametersByBuildID:=make(map[string][]codersdk.WorkspaceBuildParameter)
725+
for_,param:=rangeparameters {
726+
buildID:=param.WorkspaceBuildID.String()
727+
ifparametersByBuildID[buildID]==nil {
728+
parametersByBuildID[buildID]= []codersdk.WorkspaceBuildParameter{}
729+
}
730+
parametersByBuildID[buildID]=append(parametersByBuildID[buildID], codersdk.WorkspaceBuildParameter{
731+
Name:param.Name,
732+
Value:param.Value,
733+
})
734+
}
735+
736+
httpapi.Write(ctx,rw,http.StatusOK,parametersByBuildID)
737+
}
738+
679739
// @Summary Get workspace build logs
680740
// @ID get-workspace-build-logs
681741
// @Security CoderSessionToken

‎coderd/workspacebuilds_test.go

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1783,3 +1783,130 @@ func TestWorkspaceBuildTimings(t *testing.T) {
17831783
require.Len(t,res.AgentConnectionTimings,5)
17841784
})
17851785
}
1786+
1787+
funcTestWorkspaceBuildParametersBulk(t*testing.T) {
1788+
t.Parallel()
1789+
1790+
t.Run("EmptyBuildIDs",func(t*testing.T) {
1791+
t.Parallel()
1792+
client:=coderdtest.New(t,&coderdtest.Options{IncludeProvisionerDaemon:true})
1793+
_=coderdtest.CreateFirstUser(t,client)
1794+
1795+
ctx:=testutil.Context(t,testutil.WaitShort)
1796+
1797+
// Test with empty build IDs
1798+
params,err:=client.WorkspaceBuildParametersBulk(ctx, []uuid.UUID{})
1799+
require.NoError(t,err)
1800+
require.Empty(t,params)
1801+
})
1802+
1803+
t.Run("MultipleBuilds",func(t*testing.T) {
1804+
t.Parallel()
1805+
adminClient:=coderdtest.New(t,&coderdtest.Options{IncludeProvisionerDaemon:true})
1806+
first:=coderdtest.CreateFirstUser(t,adminClient)
1807+
memberClient,_:=coderdtest.CreateAnotherUser(t,adminClient,first.OrganizationID)
1808+
1809+
ctx:=testutil.Context(t,testutil.WaitLong)
1810+
1811+
// Create a template with parameters
1812+
version:=coderdtest.CreateTemplateVersion(t,adminClient,first.OrganizationID,&echo.Responses{
1813+
Parse:echo.ParseComplete,
1814+
ProvisionPlan: []*proto.Response{{
1815+
Type:&proto.Response_Plan{
1816+
Plan:&proto.PlanComplete{
1817+
Parameters: []*proto.RichParameter{
1818+
{
1819+
Name:"param1",
1820+
Type:"string",
1821+
DefaultValue:"default1",
1822+
},
1823+
{
1824+
Name:"param2",
1825+
Type:"string",
1826+
DefaultValue:"default2",
1827+
},
1828+
},
1829+
},
1830+
},
1831+
}},
1832+
ProvisionApply:echo.ApplyComplete,
1833+
})
1834+
template:=coderdtest.CreateTemplate(t,adminClient,first.OrganizationID,version.ID)
1835+
coderdtest.AwaitTemplateVersionJobCompleted(t,adminClient,version.ID)
1836+
1837+
// Create two workspaces with different parameters
1838+
workspace1:=coderdtest.CreateWorkspace(t,memberClient,template.ID,func(request*codersdk.CreateWorkspaceRequest) {
1839+
request.RichParameterValues= []codersdk.WorkspaceBuildParameter{
1840+
{Name:"param1",Value:"value1a"},
1841+
{Name:"param2",Value:"value2a"},
1842+
}
1843+
})
1844+
coderdtest.AwaitWorkspaceBuildJobCompleted(t,memberClient,workspace1.LatestBuild.ID)
1845+
1846+
workspace2:=coderdtest.CreateWorkspace(t,memberClient,template.ID,func(request*codersdk.CreateWorkspaceRequest) {
1847+
request.RichParameterValues= []codersdk.WorkspaceBuildParameter{
1848+
{Name:"param1",Value:"value1b"},
1849+
{Name:"param2",Value:"value2b"},
1850+
}
1851+
})
1852+
coderdtest.AwaitWorkspaceBuildJobCompleted(t,memberClient,workspace2.LatestBuild.ID)
1853+
1854+
workspace3:=coderdtest.CreateWorkspace(t,adminClient,template.ID,func(request*codersdk.CreateWorkspaceRequest) {
1855+
request.RichParameterValues= []codersdk.WorkspaceBuildParameter{
1856+
{Name:"param1",Value:"value1c"},
1857+
{Name:"param2",Value:"value2c"},
1858+
}
1859+
})
1860+
coderdtest.AwaitWorkspaceBuildJobCompleted(t,adminClient,workspace3.LatestBuild.ID)
1861+
1862+
// Test parameters endpoint as member
1863+
buildIDs:= []uuid.UUID{workspace1.LatestBuild.ID,workspace2.LatestBuild.ID}
1864+
paramsByBuild,err:=memberClient.WorkspaceBuildParametersBulk(ctx,buildIDs)
1865+
require.NoError(t,err)
1866+
require.Len(t,paramsByBuild,2)
1867+
1868+
// Check workspace1 parameters
1869+
build1Params:=paramsByBuild[workspace1.LatestBuild.ID.String()]
1870+
require.Len(t,build1Params,2)
1871+
require.ElementsMatch(t,build1Params, []codersdk.WorkspaceBuildParameter{
1872+
{Name:"param1",Value:"value1a"},
1873+
{Name:"param2",Value:"value2a"},
1874+
})
1875+
1876+
// Check workspace2 parameters
1877+
build2Params:=paramsByBuild[workspace2.LatestBuild.ID.String()]
1878+
require.Len(t,build2Params,2)
1879+
require.ElementsMatch(t,build2Params, []codersdk.WorkspaceBuildParameter{
1880+
{Name:"param1",Value:"value1b"},
1881+
{Name:"param2",Value:"value2b"},
1882+
})
1883+
1884+
// Test parameters endpoint as admin
1885+
buildIDs= []uuid.UUID{workspace1.LatestBuild.ID,workspace2.LatestBuild.ID,workspace3.LatestBuild.ID}
1886+
paramsByBuild,err=adminClient.WorkspaceBuildParametersBulk(ctx,buildIDs)
1887+
require.NoError(t,err)
1888+
require.Len(t,paramsByBuild,3)
1889+
1890+
// Check workspace3 parameters
1891+
build3Params:=paramsByBuild[workspace3.LatestBuild.ID.String()]
1892+
require.Len(t,build3Params,2)
1893+
require.ElementsMatch(t,build3Params, []codersdk.WorkspaceBuildParameter{
1894+
{Name:"param1",Value:"value1c"},
1895+
{Name:"param2",Value:"value2c"},
1896+
})
1897+
})
1898+
1899+
t.Run("NonExistentBuildIDs",func(t*testing.T) {
1900+
t.Parallel()
1901+
client:=coderdtest.New(t,&coderdtest.Options{IncludeProvisionerDaemon:true})
1902+
_=coderdtest.CreateFirstUser(t,client)
1903+
1904+
ctx:=testutil.Context(t,testutil.WaitShort)
1905+
1906+
// Test with non-existent build IDs
1907+
nonExistentID:=uuid.New()
1908+
params,err:=client.WorkspaceBuildParametersBulk(ctx, []uuid.UUID{nonExistentID})
1909+
require.NoError(t,err)
1910+
require.Empty(t,params)
1911+
})
1912+
}

‎codersdk/workspacebuilds.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"io"
88
"net/http"
9+
"strings"
910
"time"
1011

1112
"github.com/google/uuid"
@@ -178,6 +179,31 @@ func (c *Client) WorkspaceBuildParameters(ctx context.Context, build uuid.UUID)
178179
returnparams,json.NewDecoder(res.Body).Decode(&params)
179180
}
180181

182+
// WorkspaceBuildParametersBulk returns parameters for multiple workspace builds by their IDs.
183+
func (c*Client)WorkspaceBuildParametersBulk(ctx context.Context,buildIDs []uuid.UUID) (map[string][]WorkspaceBuildParameter,error) {
184+
iflen(buildIDs)==0 {
185+
returnmake(map[string][]WorkspaceBuildParameter),nil
186+
}
187+
188+
// Convert UUIDs to strings and join them
189+
buildIDStrings:=make([]string,len(buildIDs))
190+
fori,id:=rangebuildIDs {
191+
buildIDStrings[i]=id.String()
192+
}
193+
buildIDsParam:=strings.Join(buildIDStrings,",")
194+
195+
res,err:=c.Request(ctx,http.MethodGet,"/api/v2/workspacebuilds/parameters",nil,WithQueryParam("build_ids",buildIDsParam))
196+
iferr!=nil {
197+
returnnil,err
198+
}
199+
deferres.Body.Close()
200+
ifres.StatusCode!=http.StatusOK {
201+
returnnil,ReadBodyAsError(res)
202+
}
203+
varparamsmap[string][]WorkspaceBuildParameter
204+
returnparams,json.NewDecoder(res.Body).Decode(&params)
205+
}
206+
181207
typeTimingStagestring
182208

183209
const (

‎site/src/api/api.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2134,6 +2134,24 @@ class ApiMethods {
21342134
returnresponse.data;
21352135
};
21362136

2137+
getWorkspaceBuildParametersBulk=async(
2138+
buildIds:TypesGen.WorkspaceBuild["id"][],
2139+
):Promise<Record<string,TypesGen.WorkspaceBuildParameter[]>>=>{
2140+
if(buildIds.length===0){
2141+
return{};
2142+
}
2143+
2144+
constresponse=awaitthis.axios.get<
2145+
Record<string,TypesGen.WorkspaceBuildParameter[]>
2146+
>("/api/v2/workspacebuilds/parameters",{
2147+
params:{
2148+
build_ids:buildIds.join(","),
2149+
},
2150+
});
2151+
2152+
returnresponse.data;
2153+
};
2154+
21372155
getLicenses=async():Promise<GetLicensesResponse[]>=>{
21382156
constresponse=awaitthis.axios.get("/api/v2/licenses");
21392157
returnresponse.data;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp