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

Commit2b44855

Browse files
feat(scaletest): addautostart scaletest command (#20161)
Closescoder/internal#911
1 parente1619da commit2b44855

File tree

2 files changed

+236
-0
lines changed

2 files changed

+236
-0
lines changed

‎cli/exp_scaletest.go‎

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"github.com/coder/coder/v2/codersdk"
3434
"github.com/coder/coder/v2/codersdk/workspacesdk"
3535
"github.com/coder/coder/v2/scaletest/agentconn"
36+
"github.com/coder/coder/v2/scaletest/autostart"
3637
"github.com/coder/coder/v2/scaletest/createusers"
3738
"github.com/coder/coder/v2/scaletest/createworkspaces"
3839
"github.com/coder/coder/v2/scaletest/dashboard"
@@ -60,6 +61,7 @@ func (r *RootCmd) scaletestCmd() *serpent.Command {
6061
r.scaletestCreateWorkspaces(),
6162
r.scaletestWorkspaceUpdates(),
6263
r.scaletestWorkspaceTraffic(),
64+
r.scaletestAutostart(),
6365
},
6466
}
6567

@@ -1682,6 +1684,239 @@ func (r *RootCmd) scaletestDashboard() *serpent.Command {
16821684
returncmd
16831685
}
16841686

1687+
const (
1688+
autostartTestName="autostart"
1689+
)
1690+
1691+
func (r*RootCmd)scaletestAutostart()*serpent.Command {
1692+
var (
1693+
workspaceCountint64
1694+
workspaceJobTimeout time.Duration
1695+
autostartDelay time.Duration
1696+
autostartTimeout time.Duration
1697+
templatestring
1698+
noCleanupbool
1699+
1700+
parameterFlagsworkspaceParameterFlags
1701+
tracingFlags=&scaletestTracingFlags{}
1702+
timeoutStrategy=&timeoutFlags{}
1703+
cleanupStrategy=newScaletestCleanupStrategy()
1704+
output=&scaletestOutputFlags{}
1705+
prometheusFlags=&scaletestPrometheusFlags{}
1706+
)
1707+
1708+
cmd:=&serpent.Command{
1709+
Use:"autostart",
1710+
Short:"Replicate a thundering herd of autostarting workspaces",
1711+
Handler:func(inv*serpent.Invocation)error {
1712+
ctx:=inv.Context()
1713+
client,err:=r.InitClient(inv)
1714+
iferr!=nil {
1715+
returnerr
1716+
}
1717+
1718+
notifyCtx,stop:=signal.NotifyContext(ctx,StopSignals...)// Checked later.
1719+
deferstop()
1720+
ctx=notifyCtx
1721+
1722+
me,err:=requireAdmin(ctx,client)
1723+
iferr!=nil {
1724+
returnerr
1725+
}
1726+
1727+
client.HTTPClient=&http.Client{
1728+
Transport:&codersdk.HeaderTransport{
1729+
Transport:http.DefaultTransport,
1730+
Header:map[string][]string{
1731+
codersdk.BypassRatelimitHeader: {"true"},
1732+
},
1733+
},
1734+
}
1735+
1736+
ifworkspaceCount<=0 {
1737+
returnxerrors.Errorf("--workspace-count must be greater than zero")
1738+
}
1739+
1740+
outputs,err:=output.parse()
1741+
iferr!=nil {
1742+
returnxerrors.Errorf("could not parse --output flags")
1743+
}
1744+
1745+
tpl,err:=parseTemplate(ctx,client,me.OrganizationIDs,template)
1746+
iferr!=nil {
1747+
returnxerrors.Errorf("parse template: %w",err)
1748+
}
1749+
1750+
cliRichParameters,err:=asWorkspaceBuildParameters(parameterFlags.richParameters)
1751+
iferr!=nil {
1752+
returnxerrors.Errorf("can't parse given parameter values: %w",err)
1753+
}
1754+
1755+
richParameters,err:=prepWorkspaceBuild(inv,client,prepWorkspaceBuildArgs{
1756+
Action:WorkspaceCreate,
1757+
TemplateVersionID:tpl.ActiveVersionID,
1758+
1759+
RichParameterFile:parameterFlags.richParameterFile,
1760+
RichParameters:cliRichParameters,
1761+
})
1762+
iferr!=nil {
1763+
returnxerrors.Errorf("prepare build: %w",err)
1764+
}
1765+
1766+
tracerProvider,closeTracing,tracingEnabled,err:=tracingFlags.provider(ctx)
1767+
iferr!=nil {
1768+
returnxerrors.Errorf("create tracer provider: %w",err)
1769+
}
1770+
tracer:=tracerProvider.Tracer(scaletestTracerName)
1771+
1772+
reg:=prometheus.NewRegistry()
1773+
metrics:=autostart.NewMetrics(reg)
1774+
1775+
setupBarrier:=new(sync.WaitGroup)
1776+
setupBarrier.Add(int(workspaceCount))
1777+
1778+
th:=harness.NewTestHarness(timeoutStrategy.wrapStrategy(harness.ConcurrentExecutionStrategy{}),cleanupStrategy.toStrategy())
1779+
fori:=rangeworkspaceCount {
1780+
id:=strconv.Itoa(int(i))
1781+
config:= autostart.Config{
1782+
User: createusers.Config{
1783+
OrganizationID:me.OrganizationIDs[0],
1784+
},
1785+
Workspace: workspacebuild.Config{
1786+
OrganizationID:me.OrganizationIDs[0],
1787+
Request: codersdk.CreateWorkspaceRequest{
1788+
TemplateID:tpl.ID,
1789+
RichParameterValues:richParameters,
1790+
},
1791+
},
1792+
WorkspaceJobTimeout:workspaceJobTimeout,
1793+
AutostartDelay:autostartDelay,
1794+
AutostartTimeout:autostartTimeout,
1795+
Metrics:metrics,
1796+
SetupBarrier:setupBarrier,
1797+
}
1798+
iferr:=config.Validate();err!=nil {
1799+
returnxerrors.Errorf("validate config: %w",err)
1800+
}
1801+
varrunner harness.Runnable=autostart.NewRunner(client,config)
1802+
iftracingEnabled {
1803+
runner=&runnableTraceWrapper{
1804+
tracer:tracer,
1805+
spanName:fmt.Sprintf("%s/%s",autostartTestName,id),
1806+
runner:runner,
1807+
}
1808+
}
1809+
th.AddRun(autostartTestName,id,runner)
1810+
}
1811+
1812+
logger:=inv.Logger
1813+
prometheusSrvClose:=ServeHandler(ctx,logger,promhttp.HandlerFor(reg, promhttp.HandlerOpts{}),prometheusFlags.Address,"prometheus")
1814+
deferprometheusSrvClose()
1815+
1816+
deferfunc() {
1817+
_,_=fmt.Fprintln(inv.Stderr,"\nUploading traces...")
1818+
iferr:=closeTracing(ctx);err!=nil {
1819+
_,_=fmt.Fprintf(inv.Stderr,"\nError uploading traces: %+v\n",err)
1820+
}
1821+
// Wait for prometheus metrics to be scraped
1822+
_,_=fmt.Fprintf(inv.Stderr,"Waiting %s for prometheus metrics to be scraped\n",prometheusFlags.Wait)
1823+
<-time.After(prometheusFlags.Wait)
1824+
}()
1825+
1826+
_,_=fmt.Fprintln(inv.Stderr,"Running autostart load test...")
1827+
testCtx,testCancel:=timeoutStrategy.toContext(ctx)
1828+
defertestCancel()
1829+
err=th.Run(testCtx)
1830+
iferr!=nil {
1831+
returnxerrors.Errorf("run test harness (harness failure, not a test failure): %w",err)
1832+
}
1833+
1834+
// If the command was interrupted, skip stats.
1835+
ifnotifyCtx.Err()!=nil {
1836+
returnnotifyCtx.Err()
1837+
}
1838+
1839+
res:=th.Results()
1840+
for_,o:=rangeoutputs {
1841+
err=o.write(res,inv.Stdout)
1842+
iferr!=nil {
1843+
returnxerrors.Errorf("write output %q to %q: %w",o.format,o.path,err)
1844+
}
1845+
}
1846+
1847+
if!noCleanup {
1848+
_,_=fmt.Fprintln(inv.Stderr,"\nCleaning up...")
1849+
cleanupCtx,cleanupCancel:=cleanupStrategy.toContext(ctx)
1850+
defercleanupCancel()
1851+
err=th.Cleanup(cleanupCtx)
1852+
iferr!=nil {
1853+
returnxerrors.Errorf("cleanup tests: %w",err)
1854+
}
1855+
}
1856+
1857+
ifres.TotalFail>0 {
1858+
returnxerrors.New("load test failed, see above for more details")
1859+
}
1860+
1861+
returnnil
1862+
},
1863+
}
1864+
1865+
cmd.Options= serpent.OptionSet{
1866+
{
1867+
Flag:"workspace-count",
1868+
FlagShorthand:"c",
1869+
Env:"CODER_SCALETEST_WORKSPACE_COUNT",
1870+
Description:"Required: Total number of workspaces to create.",
1871+
Value:serpent.Int64Of(&workspaceCount),
1872+
Required:true,
1873+
},
1874+
{
1875+
Flag:"workspace-job-timeout",
1876+
Env:"CODER_SCALETEST_WORKSPACE_JOB_TIMEOUT",
1877+
Default:"5m",
1878+
Description:"Timeout for workspace jobs (e.g. build, start).",
1879+
Value:serpent.DurationOf(&workspaceJobTimeout),
1880+
},
1881+
{
1882+
Flag:"autostart-delay",
1883+
Env:"CODER_SCALETEST_AUTOSTART_DELAY",
1884+
Default:"2m",
1885+
Description:"How long after all the workspaces have been stopped to schedule them to be started again.",
1886+
Value:serpent.DurationOf(&autostartDelay),
1887+
},
1888+
{
1889+
Flag:"autostart-timeout",
1890+
Env:"CODER_SCALETEST_AUTOSTART_TIMEOUT",
1891+
Default:"5m",
1892+
Description:"Timeout for the autostart build to be initiated after the scheduled start time.",
1893+
Value:serpent.DurationOf(&autostartTimeout),
1894+
},
1895+
{
1896+
Flag:"template",
1897+
FlagShorthand:"t",
1898+
Env:"CODER_SCALETEST_TEMPLATE",
1899+
Description:"Required: Name or ID of the template to use for workspaces.",
1900+
Value:serpent.StringOf(&template),
1901+
Required:true,
1902+
},
1903+
{
1904+
Flag:"no-cleanup",
1905+
Env:"CODER_SCALETEST_NO_CLEANUP",
1906+
Description:"Do not clean up resources after the test completes.",
1907+
Value:serpent.BoolOf(&noCleanup),
1908+
},
1909+
}
1910+
1911+
cmd.Options=append(cmd.Options,parameterFlags.cliParameters()...)
1912+
tracingFlags.attach(&cmd.Options)
1913+
timeoutStrategy.attach(&cmd.Options)
1914+
cleanupStrategy.attach(&cmd.Options)
1915+
output.attach(&cmd.Options)
1916+
prometheusFlags.attach(&cmd.Options)
1917+
returncmd
1918+
}
1919+
16851920
typerunnableTraceWrapperstruct {
16861921
tracer trace.Tracer
16871922
spanNamestring

‎scaletest/autostart/run.go‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ func (r *Runner) Run(ctx context.Context, id string, logs io.Writer) error {
8080
workspaceBuildConfig.UserID=newUser.ID.String()
8181
// We'll wait for the build ourselves to avoid multiple API requests
8282
workspaceBuildConfig.NoWaitForBuild=true
83+
workspaceBuildConfig.NoWaitForAgents=true
8384

8485
r.workspacebuildRunner=workspacebuild.NewRunner(newUserClient,workspaceBuildConfig)
8586
workspace,err:=r.workspacebuildRunner.RunReturningWorkspace(ctx,id,logs)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp