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

Commitf918977

Browse files
authored
feat: add new loadtest type agentconn (#4899)
1 parent56b963a commitf918977

File tree

5 files changed

+898
-2
lines changed

5 files changed

+898
-2
lines changed

‎cli/loadtestconfig.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
"github.com/coder/coder/coderd/httpapi"
99
"github.com/coder/coder/codersdk"
10+
"github.com/coder/coder/loadtest/agentconn"
1011
"github.com/coder/coder/loadtest/harness"
1112
"github.com/coder/coder/loadtest/placebo"
1213
"github.com/coder/coder/loadtest/workspacebuild"
@@ -86,6 +87,7 @@ func (s LoadTestStrategy) ExecutionStrategy() harness.ExecutionStrategy {
8687
typeLoadTestTypestring
8788

8889
const (
90+
LoadTestTypeAgentConnLoadTestType="agentconn"
8991
LoadTestTypePlaceboLoadTestType="placebo"
9092
LoadTestTypeWorkspaceBuildLoadTestType="workspacebuild"
9193
)
@@ -97,6 +99,8 @@ type LoadTest struct {
9799
// the count is 0 or negative, defaults to 1.
98100
Countint`json:"count"`
99101

102+
// AgentConn must be set if type == "agentconn".
103+
AgentConn*agentconn.Config`json:"agentconn,omitempty"`
100104
// Placebo must be set if type == "placebo".
101105
Placebo*placebo.Config`json:"placebo,omitempty"`
102106
// WorkspaceBuild must be set if type == "workspacebuild".
@@ -105,17 +109,20 @@ type LoadTest struct {
105109

106110
func (tLoadTest)NewRunner(client*codersdk.Client) (harness.Runnable,error) {
107111
switcht.Type {
112+
caseLoadTestTypeAgentConn:
113+
ift.AgentConn==nil {
114+
returnnil,xerrors.New("agentconn config must be set")
115+
}
116+
returnagentconn.NewRunner(client,*t.AgentConn),nil
108117
caseLoadTestTypePlacebo:
109118
ift.Placebo==nil {
110119
returnnil,xerrors.New("placebo config must be set")
111120
}
112-
113121
returnplacebo.NewRunner(*t.Placebo),nil
114122
caseLoadTestTypeWorkspaceBuild:
115123
ift.WorkspaceBuild==nil {
116124
returnnil,xerrors.Errorf("workspacebuild config must be set")
117125
}
118-
119126
returnworkspacebuild.NewRunner(client,*t.WorkspaceBuild),nil
120127
default:
121128
returnnil,xerrors.Errorf("unknown test type %q",t.Type)
@@ -155,6 +162,15 @@ func (s *LoadTestStrategy) Validate() error {
155162

156163
func (t*LoadTest)Validate()error {
157164
switcht.Type {
165+
caseLoadTestTypeAgentConn:
166+
ift.AgentConn==nil {
167+
returnxerrors.Errorf("agentconn test type must specify agentconn")
168+
}
169+
170+
err:=t.AgentConn.Validate()
171+
iferr!=nil {
172+
returnxerrors.Errorf("validate agentconn: %w",err)
173+
}
158174
caseLoadTestTypePlacebo:
159175
ift.Placebo==nil {
160176
returnxerrors.Errorf("placebo test type must specify placebo")

‎loadtest/agentconn/config.go

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package agentconn
2+
3+
import (
4+
"net/url"
5+
6+
"github.com/google/uuid"
7+
"golang.org/x/xerrors"
8+
9+
"github.com/coder/coder/coderd/httpapi"
10+
)
11+
12+
typeConnectionModestring
13+
14+
const (
15+
ConnectionModeDirectConnectionMode="direct"
16+
ConnectionModeDerpConnectionMode="derp"
17+
)
18+
19+
typeConfigstruct {
20+
// AgentID is the ID of the agent to connect to.
21+
AgentID uuid.UUID`json:"agent_id"`
22+
// ConnectionMode is the strategy to use when connecting to the agent.
23+
ConnectionModeConnectionMode`json:"connection_mode"`
24+
// HoldDuration is the duration to hold the connection open for. If set to
25+
// 0, the connection will be closed immediately after making each request
26+
// once.
27+
HoldDuration httpapi.Duration`json:"hold_duration"`
28+
29+
// Connections is the list of connections to make to services running
30+
// inside the workspace. Only HTTP connections are supported.
31+
Connections []Connection`json:"connections"`
32+
}
33+
34+
typeConnectionstruct {
35+
// URL is the address to connect to (e.g. "http://127.0.0.1:8080/path"). The
36+
// endpoint must respond with a any response within timeout. The IP address
37+
// is ignored and the connection is made to the agent's WireGuard IP
38+
// instead.
39+
URLstring`json:"url"`
40+
// Interval is the duration to wait between connections to this endpoint. If
41+
// set to 0, the connection will only be made once. Must be set to 0 if
42+
// the parent config's hold_duration is set to 0.
43+
Interval httpapi.Duration`json:"interval"`
44+
// Timeout is the duration to wait for a connection to this endpoint to
45+
// succeed. If set to 0, the default timeout will be used.
46+
Timeout httpapi.Duration`json:"timeout"`
47+
}
48+
49+
func (cConfig)Validate()error {
50+
ifc.AgentID==uuid.Nil {
51+
returnxerrors.New("agent_id must be set")
52+
}
53+
ifc.ConnectionMode=="" {
54+
returnxerrors.New("connection_mode must be set")
55+
}
56+
switchc.ConnectionMode {
57+
caseConnectionModeDirect:
58+
caseConnectionModeDerp:
59+
default:
60+
returnxerrors.Errorf("invalid connection_mode: %q",c.ConnectionMode)
61+
}
62+
ifc.HoldDuration<0 {
63+
returnxerrors.New("hold_duration must be a positive value")
64+
}
65+
66+
fori,conn:=rangec.Connections {
67+
ifconn.URL=="" {
68+
returnxerrors.Errorf("connections[%d].url must be set",i)
69+
}
70+
u,err:=url.Parse(conn.URL)
71+
iferr!=nil {
72+
returnxerrors.Errorf("connections[%d].url is not a valid URL: %w",i,err)
73+
}
74+
ifu.Scheme!="http" {
75+
returnxerrors.Errorf("connections[%d].url has an unsupported scheme %q, only http is supported",i,u.Scheme)
76+
}
77+
ifconn.Interval<0 {
78+
returnxerrors.Errorf("connections[%d].interval must be a positive value",i)
79+
}
80+
ifconn.Interval>0&&c.HoldDuration==0 {
81+
returnxerrors.Errorf("connections[%d].interval must be 0 if hold_duration is 0",i)
82+
}
83+
ifconn.Timeout<0 {
84+
returnxerrors.Errorf("connections[%d].timeout must be a positive value",i)
85+
}
86+
}
87+
88+
returnnil
89+
}

‎loadtest/agentconn/config_test.go

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
package agentconn_test
2+
3+
import (
4+
"testing"
5+
"time"
6+
7+
"github.com/google/uuid"
8+
"github.com/stretchr/testify/require"
9+
10+
"github.com/coder/coder/coderd/httpapi"
11+
"github.com/coder/coder/loadtest/agentconn"
12+
)
13+
14+
funcTest_Config(t*testing.T) {
15+
t.Parallel()
16+
17+
id:=uuid.New()
18+
cases:= []struct {
19+
namestring
20+
config agentconn.Config
21+
errContainsstring
22+
}{
23+
{
24+
name:"OK",
25+
config: agentconn.Config{
26+
AgentID:id,
27+
ConnectionMode:agentconn.ConnectionModeDirect,
28+
HoldDuration:httpapi.Duration(time.Minute),
29+
Connections: []agentconn.Connection{
30+
{
31+
URL:"http://localhost:8080/path",
32+
Interval:httpapi.Duration(time.Second),
33+
Timeout:httpapi.Duration(time.Second),
34+
},
35+
{
36+
URL:"http://localhost:8000/differentpath",
37+
Interval:httpapi.Duration(2*time.Second),
38+
Timeout:httpapi.Duration(2*time.Second),
39+
},
40+
},
41+
},
42+
},
43+
{
44+
name:"NoAgentID",
45+
config: agentconn.Config{
46+
AgentID:uuid.Nil,
47+
ConnectionMode:agentconn.ConnectionModeDirect,
48+
HoldDuration:0,
49+
Connections:nil,
50+
},
51+
errContains:"agent_id must be set",
52+
},
53+
{
54+
name:"NoConnectionMode",
55+
config: agentconn.Config{
56+
AgentID:id,
57+
ConnectionMode:"",
58+
HoldDuration:0,
59+
Connections:nil,
60+
},
61+
errContains:"connection_mode must be set",
62+
},
63+
{
64+
name:"InvalidConnectionMode",
65+
config: agentconn.Config{
66+
AgentID:id,
67+
ConnectionMode:"blah",
68+
HoldDuration:0,
69+
Connections:nil,
70+
},
71+
errContains:"invalid connection_mode",
72+
},
73+
{
74+
name:"NegativeHoldDuration",
75+
config: agentconn.Config{
76+
AgentID:id,
77+
ConnectionMode:agentconn.ConnectionModeDerp,
78+
HoldDuration:-1,
79+
Connections:nil,
80+
},
81+
errContains:"hold_duration must be a positive value",
82+
},
83+
{
84+
name:"ConnectionNoURL",
85+
config: agentconn.Config{
86+
AgentID:id,
87+
ConnectionMode:agentconn.ConnectionModeDirect,
88+
HoldDuration:1,
89+
Connections: []agentconn.Connection{{
90+
URL:"",
91+
Interval:0,
92+
Timeout:0,
93+
}},
94+
},
95+
errContains:"connections[0].url must be set",
96+
},
97+
{
98+
name:"ConnectionInvalidURL",
99+
config: agentconn.Config{
100+
AgentID:id,
101+
ConnectionMode:agentconn.ConnectionModeDirect,
102+
HoldDuration:1,
103+
Connections: []agentconn.Connection{{
104+
URL:string([]byte{0x7f}),
105+
Interval:0,
106+
Timeout:0,
107+
}},
108+
},
109+
errContains:"connections[0].url is not a valid URL",
110+
},
111+
{
112+
name:"ConnectionInvalidURLScheme",
113+
config: agentconn.Config{
114+
AgentID:id,
115+
ConnectionMode:agentconn.ConnectionModeDirect,
116+
HoldDuration:1,
117+
Connections: []agentconn.Connection{{
118+
URL:"blah://localhost:8080",
119+
Interval:0,
120+
Timeout:0,
121+
}},
122+
},
123+
errContains:"connections[0].url has an unsupported scheme",
124+
},
125+
{
126+
name:"ConnectionNegativeInterval",
127+
config: agentconn.Config{
128+
AgentID:id,
129+
ConnectionMode:agentconn.ConnectionModeDirect,
130+
HoldDuration:1,
131+
Connections: []agentconn.Connection{{
132+
URL:"http://localhost:8080",
133+
Interval:-1,
134+
Timeout:0,
135+
}},
136+
},
137+
errContains:"connections[0].interval must be a positive value",
138+
},
139+
{
140+
name:"ConnectionIntervalMustBeZero",
141+
config: agentconn.Config{
142+
AgentID:id,
143+
ConnectionMode:agentconn.ConnectionModeDirect,
144+
HoldDuration:0,
145+
Connections: []agentconn.Connection{{
146+
URL:"http://localhost:8080",
147+
Interval:1,
148+
Timeout:0,
149+
}},
150+
},
151+
errContains:"connections[0].interval must be 0 if hold_duration is 0",
152+
},
153+
{
154+
name:"ConnectionNegativeTimeout",
155+
config: agentconn.Config{
156+
AgentID:id,
157+
ConnectionMode:agentconn.ConnectionModeDirect,
158+
HoldDuration:1,
159+
Connections: []agentconn.Connection{{
160+
URL:"http://localhost:8080",
161+
Interval:0,
162+
Timeout:-1,
163+
}},
164+
},
165+
errContains:"connections[0].timeout must be a positive value",
166+
},
167+
}
168+
169+
for_,c:=rangecases {
170+
c:=c
171+
172+
t.Run(c.name,func(t*testing.T) {
173+
t.Parallel()
174+
175+
err:=c.config.Validate()
176+
ifc.errContains!="" {
177+
require.Error(t,err)
178+
require.Contains(t,err.Error(),c.errContains)
179+
}else {
180+
require.NoError(t,err)
181+
}
182+
})
183+
}
184+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp