@opensoha/contracts 0.1.9 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +1 -1
  2. package/auth/catalog_generated.go +3 -3
  3. package/auth/catalog_test.go +35 -0
  4. package/auth/permission-catalog.json +19 -151
  5. package/compat/json-schema-ecosystem-0.1.0.json +1 -1
  6. package/compat/openapi-loose-boundaries-0.1.0.json +1 -5
  7. package/fixtures/openapi/DockerHostAgentCredentialsEnvelope/invalid/missing-runtime-token.json +9 -0
  8. package/fixtures/openapi/DockerHostAgentCredentialsEnvelope/valid/credentials.json +10 -0
  9. package/fixtures/openapi/DockerHostAgentEnrollmentRequest/invalid/short-token.json +4 -0
  10. package/fixtures/openapi/DockerHostAgentEnrollmentRequest/valid/enrollment.json +4 -0
  11. package/fixtures/openapi/DockerHostAgentInstallation/invalid/missing-command.json +6 -0
  12. package/fixtures/openapi/DockerHostAgentInstallation/valid/installation.json +7 -0
  13. package/fixtures/openapi/IdentityProvider/invalid/missing-id.json +9 -0
  14. package/fixtures/openapi/IdentityProvider/valid/current.json +12 -0
  15. package/fixtures/openapi/IdentityProvider/valid/v0.1.9.json +14 -0
  16. package/fixtures/openapi/MenuEnvelope/invalid/missing-data.json +1 -0
  17. package/fixtures/openapi/MenuEnvelope/valid/menu.json +13 -0
  18. package/fixtures/openapi/MenuInput/invalid/missing-icon.json +5 -0
  19. package/fixtures/openapi/MenuInput/valid/top-level.json +12 -0
  20. package/fixtures/openapi/MenuListEnvelope/invalid/items-object.json +3 -0
  21. package/fixtures/openapi/MenuListEnvelope/valid/tree.json +27 -0
  22. package/fixtures/openapi/OIDCClient/invalid/missing-grant-types.json +9 -0
  23. package/fixtures/openapi/OIDCClient/valid/current.json +19 -0
  24. package/fixtures/openapi/OIDCClient/valid/v0.1.9.json +10 -0
  25. package/fixtures/openapi/OIDCClientInput/invalid/empty-rules.json +5 -0
  26. package/fixtures/openapi/OIDCClientInput/valid/regex.json +4 -0
  27. package/fixtures/openapi/OIDCClientInput/valid/strict.json +4 -0
  28. package/fixtures/openapi/OIDCClientInput/valid/v0.1.9.json +7 -0
  29. package/fixtures/openapi/ObservabilityContext/invalid/missing-time-range.json +6 -0
  30. package/fixtures/openapi/ObservabilityContext/valid/scoped.json +27 -0
  31. package/fixtures/openapi/ObservabilityDashboardImportResultEnvelope/valid/imported.json +28 -1
  32. package/fixtures/openapi/ObservabilityDashboardPanelQueryInput/invalid/missing-time-to.json +6 -0
  33. package/fixtures/openapi/ObservabilityDashboardPanelQueryInput/valid/variables.json +8 -0
  34. package/fixtures/openapi/ObservabilityMetricCatalogEnvelope/invalid/missing-availability.json +10 -0
  35. package/fixtures/openapi/ObservabilityMetricCatalogEnvelope/valid/catalog.json +13 -0
  36. package/fixtures/openapi/ObservabilityQueryResultMeta/invalid/missing-state.json +3 -0
  37. package/fixtures/openapi/ObservabilityQueryResultMeta/valid/partial.json +15 -0
  38. package/fixtures/openapi/ObservabilityQuerySnapshot/invalid/missing-context.json +5 -0
  39. package/fixtures/openapi/ObservabilityQuerySnapshot/valid/prometheus.json +22 -0
  40. package/fixtures/openapi/ObservabilityServiceEnvelope/invalid/missing-status.json +12 -0
  41. package/fixtures/openapi/ObservabilityServiceEnvelope/valid/service.json +29 -0
  42. package/fixtures/openapi/ObservabilityServiceListEnvelope/invalid/missing-meta.json +3 -0
  43. package/fixtures/openapi/ObservabilityServiceListEnvelope/valid/services.json +39 -0
  44. package/fixtures/openapi/ObservabilityTopologyEnvelope/invalid/missing-edge-status.json +10 -0
  45. package/fixtures/openapi/ObservabilityTopologyEnvelope/valid/topology.json +22 -0
  46. package/fixtures/openapi/ScopeGrantEnvelope/invalid/missing-id.json +13 -0
  47. package/fixtures/openapi/ScopeGrantEnvelope/valid/platform.json +15 -0
  48. package/fixtures/openapi/ScopeGrantInput/invalid/missing-subject.json +7 -0
  49. package/fixtures/openapi/ScopeGrantInput/valid/delivery.json +11 -0
  50. package/fixtures/openapi/ScopeGrantListEnvelope/invalid/unknown-scope.json +16 -0
  51. package/fixtures/openapi/ScopeGrantListEnvelope/valid/list.json +18 -0
  52. package/gen/go/sohaapi/client.go +10 -1
  53. package/gen/go/sohaapi/client_test.go +47 -0
  54. package/gen/go/sohaapi/types.go +987 -93
  55. package/gen/ts/sohaapi/index.ts +1263 -48
  56. package/go.mod +1 -1
  57. package/openapi/soha-api.json +2501 -50
  58. package/openapi/soha-api.yaml +1398 -57
  59. package/openapi/spec_generated.go +3 -3
  60. package/package.json +1 -1
@@ -0,0 +1,27 @@
1
+ {
2
+ "items": [
3
+ {
4
+ "id": "settings",
5
+ "path": "/settings",
6
+ "labelZh": "设置中心",
7
+ "labelEn": "Settings",
8
+ "iconKey": "setting",
9
+ "section": "",
10
+ "sortOrder": 10,
11
+ "enabled": true,
12
+ "children": [
13
+ {
14
+ "id": "settings-overview",
15
+ "parentId": "settings",
16
+ "path": "/settings/overview",
17
+ "labelZh": "设置总览",
18
+ "labelEn": "Settings Overview",
19
+ "iconKey": "dashboard",
20
+ "section": "",
21
+ "sortOrder": 10,
22
+ "enabled": true
23
+ }
24
+ ]
25
+ }
26
+ ]
27
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "id": "client-1",
3
+ "providerId": "provider-1",
4
+ "clientId": "grafana",
5
+ "redirectUris": ["https://grafana.example.com/login/oauth"],
6
+ "status": "active",
7
+ "createdAt": "2026-08-01T00:00:00Z",
8
+ "updatedAt": "2026-08-01T00:00:00Z"
9
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "id": "client-2",
3
+ "providerId": "provider-1",
4
+ "clientId": "tenant-app",
5
+ "clientType": "public",
6
+ "redirectUris": [],
7
+ "grantTypes": ["authorization_code"],
8
+ "redirectUriRegexes": ["https://tenant-[a-z0-9]+\\.example\\.com/callback"],
9
+ "postLogoutRedirectUris": ["https://app.example.com/logout/callback"],
10
+ "allowedScopes": ["openid", "profile"],
11
+ "allowedGrantTypes": ["authorization_code"],
12
+ "requirePkce": true,
13
+ "accessTokenTtlSeconds": 900,
14
+ "idTokenTtlSeconds": 900,
15
+ "refreshTokenTtlSeconds": 0,
16
+ "status": "active",
17
+ "createdAt": "2026-08-01T00:00:00Z",
18
+ "updatedAt": "2026-08-01T00:00:00Z"
19
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "id": "client-1",
3
+ "providerId": "provider-1",
4
+ "clientId": "grafana",
5
+ "redirectUris": ["https://grafana.example.com/login/oauth"],
6
+ "grantTypes": ["authorization_code", "refresh_token"],
7
+ "status": "active",
8
+ "createdAt": "2026-08-01T00:00:00Z",
9
+ "updatedAt": "2026-08-01T00:00:00Z"
10
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "clientId": "broken-client",
3
+ "redirectUris": [],
4
+ "redirectUriRegexes": []
5
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "clientId": "tenant-app",
3
+ "redirectUriRegexes": ["https://tenant-[a-z0-9]+\\.example\\.com/callback"]
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "clientId": "grafana",
3
+ "redirectUris": ["http://grafana.internal/login/oauth"]
4
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "providerId": "provider-1",
3
+ "clientId": "grafana",
4
+ "redirectUris": ["https://grafana.example.com/login/oauth"],
5
+ "grantTypes": ["authorization_code", "refresh_token"],
6
+ "status": "active"
7
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "version": "v1",
3
+ "scope": {
4
+ "clusterId": "cluster-1"
5
+ }
6
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "version": "v1",
3
+ "scope": {
4
+ "workspaceId": "default",
5
+ "clusterId": "cluster-1",
6
+ "environment": "production",
7
+ "namespace": "payments",
8
+ "service": "checkout-api"
9
+ },
10
+ "resource": {
11
+ "kind": "service",
12
+ "name": "checkout-api"
13
+ },
14
+ "timeRange": {
15
+ "from": "2026-08-13T00:00:00Z",
16
+ "to": "2026-08-13T01:00:00Z",
17
+ "timezone": "Asia/Shanghai"
18
+ },
19
+ "filter": {
20
+ "text": "error",
21
+ "labels": {
22
+ "deployment.environment.name": "production"
23
+ },
24
+ "traceId": "trace-1"
25
+ },
26
+ "scopeRestricted": true
27
+ }
@@ -4,8 +4,32 @@
4
4
  "id": "dashboard:8b9f35ba-6870-4f34-b45f-6f601d8b8c35",
5
5
  "name": "Kubernetes Overview",
6
6
  "source": "grafana",
7
+ "sourceFormat": "classic",
7
8
  "sourceSchemaVersion": 39,
9
+ "rawJson": "{\"title\":\"Kubernetes Overview\"}",
8
10
  "tags": ["kubernetes"],
11
+ "variables": [
12
+ {
13
+ "name": "namespace",
14
+ "label": "Namespace",
15
+ "type": "custom",
16
+ "current": "default",
17
+ "options": ["default", "production"]
18
+ }
19
+ ],
20
+ "dataSourceBindings": [
21
+ {
22
+ "type": "prometheus",
23
+ "uid": "prom",
24
+ "dataSourceId": "prometheus-main"
25
+ }
26
+ ],
27
+ "importWarnings": [
28
+ {
29
+ "code": "datasource_rebound",
30
+ "message": "Grafana data-source prom is mapped to prometheus-main."
31
+ }
32
+ ],
9
33
  "panels": [
10
34
  {
11
35
  "id": "1",
@@ -15,7 +39,10 @@
15
39
  "targets": [
16
40
  {
17
41
  "refId": "A",
18
- "expression": "sum(rate(container_cpu_usage_seconds_total[5m]))"
42
+ "expression": "sum(rate(container_cpu_usage_seconds_total{namespace=\"$namespace\"}[5m]))",
43
+ "dataSourceType": "prometheus",
44
+ "dataSourceUid": "prom",
45
+ "dataSourceId": "prometheus-main"
19
46
  }
20
47
  ],
21
48
  "queryable": true
@@ -0,0 +1,6 @@
1
+ {
2
+ "timeFrom": "2026-08-08T07:00:00Z",
3
+ "variables": {
4
+ "namespace": "production"
5
+ }
6
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "timeFrom": "2026-08-08T07:00:00Z",
3
+ "timeTo": "2026-08-08T08:00:00Z",
4
+ "stepSeconds": 60,
5
+ "variables": {
6
+ "namespace": "production"
7
+ }
8
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "items": [
3
+ {
4
+ "key": "http.server.request.duration",
5
+ "label": "HTTP server request duration",
6
+ "unit": "s",
7
+ "signal": "metrics"
8
+ }
9
+ ]
10
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "items": [
3
+ {
4
+ "key": "http.server.request.duration",
5
+ "label": "HTTP server request duration",
6
+ "description": "Server request duration from OpenTelemetry HTTP semantic conventions.",
7
+ "unit": "s",
8
+ "semanticConvention": "http.server.request.duration",
9
+ "signal": "metrics",
10
+ "available": true
11
+ }
12
+ ]
13
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "state": "partial",
3
+ "scopeRestricted": true,
4
+ "observedAt": "2026-08-13T01:00:02Z",
5
+ "durationMs": 42,
6
+ "warnings": ["One data source timed out."],
7
+ "errors": [
8
+ {
9
+ "code": "query_timeout",
10
+ "message": "The secondary source did not respond before the deadline.",
11
+ "retryable": true,
12
+ "sourceId": "secondary"
13
+ }
14
+ ]
15
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "version": "v1",
3
+ "signal": "traces",
4
+ "queryLanguage": "trace_filter"
5
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "version": "v1",
3
+ "signal": "metrics",
4
+ "dataSourceId": "prometheus-main",
5
+ "backendType": "prometheus",
6
+ "context": {
7
+ "version": "v1",
8
+ "scope": {
9
+ "workspaceId": "default",
10
+ "clusterId": "cluster-1",
11
+ "namespace": "payments",
12
+ "service": "checkout-api"
13
+ },
14
+ "timeRange": {
15
+ "from": "2026-08-13T00:00:00Z",
16
+ "to": "2026-08-13T01:00:00Z"
17
+ }
18
+ },
19
+ "queryLanguage": "promql",
20
+ "query": "rate(http_server_request_duration_seconds_count[5m])",
21
+ "createdAt": "2026-08-13T01:00:01Z"
22
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "data": {
3
+ "id": "checkout-api",
4
+ "name": "checkout-api",
5
+ "clusterIds": [],
6
+ "instances": [],
7
+ "endpoints": []
8
+ },
9
+ "meta": {
10
+ "state": "success"
11
+ }
12
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "data": {
3
+ "id": "checkout-api",
4
+ "name": "checkout-api",
5
+ "environment": "production",
6
+ "namespace": "payments",
7
+ "clusterIds": ["cluster-1"],
8
+ "status": "unknown",
9
+ "instances": [
10
+ {
11
+ "id": "checkout-api-7b8f",
12
+ "name": "checkout-api-7b8f",
13
+ "status": "unknown"
14
+ }
15
+ ],
16
+ "endpoints": [
17
+ {
18
+ "id": "POST /checkout",
19
+ "name": "/checkout",
20
+ "method": "POST",
21
+ "status": "unknown"
22
+ }
23
+ ]
24
+ },
25
+ "meta": {
26
+ "state": "success",
27
+ "observedAt": "2026-08-13T01:00:00Z"
28
+ }
29
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ "items": [
3
+ {
4
+ "id": "checkout-api",
5
+ "name": "checkout-api",
6
+ "environment": "production",
7
+ "namespace": "payments",
8
+ "clusterIds": ["cluster-1"],
9
+ "status": "degraded",
10
+ "requestRate": 125.5,
11
+ "errorRate": 0.023,
12
+ "latencyP95Ms": 412,
13
+ "lastSeenAt": "2026-08-13T01:00:00Z",
14
+ "instances": [
15
+ {
16
+ "id": "checkout-api-7b8f",
17
+ "name": "checkout-api-7b8f",
18
+ "status": "healthy",
19
+ "lastSeenAt": "2026-08-13T01:00:00Z"
20
+ }
21
+ ],
22
+ "endpoints": [
23
+ {
24
+ "id": "POST /checkout",
25
+ "name": "/checkout",
26
+ "method": "POST",
27
+ "status": "degraded",
28
+ "requestRate": 125.5,
29
+ "errorRate": 0.023,
30
+ "latencyP95Ms": 412
31
+ }
32
+ ]
33
+ }
34
+ ],
35
+ "meta": {
36
+ "state": "success",
37
+ "observedAt": "2026-08-13T01:00:00Z"
38
+ }
39
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "data": {
3
+ "nodes": [],
4
+ "edges": [
5
+ {"sourceServiceId": "a", "targetServiceId": "b"}
6
+ ],
7
+ "beta": true,
8
+ "meta": {"state": "success"}
9
+ }
10
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "data": {
3
+ "nodes": [
4
+ {"serviceId": "checkout-api", "name": "checkout-api", "status": "degraded"},
5
+ {"serviceId": "payment-api", "name": "payment-api", "status": "healthy"}
6
+ ],
7
+ "edges": [
8
+ {
9
+ "sourceServiceId": "checkout-api",
10
+ "targetServiceId": "payment-api",
11
+ "status": "degraded",
12
+ "requestRate": 88,
13
+ "errorRate": 0.031,
14
+ "latencyP95Ms": 510
15
+ }
16
+ ],
17
+ "beta": true,
18
+ "meta": {
19
+ "state": "success"
20
+ }
21
+ }
22
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "data": {
3
+ "subjectType": "team",
4
+ "subjectId": "platform-team",
5
+ "businessLineId": "",
6
+ "scopeType": "platform",
7
+ "role": "readonly",
8
+ "effect": "allow",
9
+ "enabled": true,
10
+ "createdAt": "2026-08-13T08:00:00Z",
11
+ "updatedAt": "2026-08-13T08:00:00Z"
12
+ }
13
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "data": {
3
+ "id": "grant-123",
4
+ "subjectType": "team",
5
+ "subjectId": "platform-team",
6
+ "businessLineId": "",
7
+ "scopeType": "platform",
8
+ "clusterIds": ["cluster-prod"],
9
+ "role": "readonly",
10
+ "effect": "allow",
11
+ "enabled": true,
12
+ "createdAt": "2026-08-13T08:00:00Z",
13
+ "updatedAt": "2026-08-13T08:00:00Z"
14
+ }
15
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "subjectType": "user",
3
+ "scopeType": "delivery",
4
+ "businessLineId": "payments",
5
+ "role": "developer",
6
+ "enabled": true
7
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "subjectType": "user",
3
+ "subjectId": "user-123",
4
+ "businessLineId": "payments",
5
+ "environmentIds": ["production"],
6
+ "applicationIds": ["checkout-api"],
7
+ "scopeType": "delivery",
8
+ "role": "developer",
9
+ "effect": "allow",
10
+ "enabled": true
11
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "items": [
3
+ {
4
+ "id": "grant-123",
5
+ "subjectType": "user",
6
+ "subjectId": "user-123",
7
+ "businessLineId": "payments",
8
+ "scopeType": "global",
9
+ "role": "developer",
10
+ "effect": "allow",
11
+ "enabled": true,
12
+ "createdAt": "2026-08-13T08:00:00Z",
13
+ "updatedAt": "2026-08-13T08:00:00Z"
14
+ }
15
+ ]
16
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "items": [
3
+ {
4
+ "id": "grant-123",
5
+ "subjectType": "user",
6
+ "subjectId": "user-123",
7
+ "businessLineId": "payments",
8
+ "environmentIds": [],
9
+ "applicationIds": ["checkout-api"],
10
+ "scopeType": "delivery",
11
+ "role": "developer",
12
+ "effect": "allow",
13
+ "enabled": true,
14
+ "createdAt": "2026-08-13T08:00:00Z",
15
+ "updatedAt": "2026-08-13T08:00:00Z"
16
+ }
17
+ ]
18
+ }
@@ -14,7 +14,7 @@ import (
14
14
  "time"
15
15
  )
16
16
 
17
- const defaultUserAgent = "opensoha-contracts/0.1.9"
17
+ const defaultUserAgent = "opensoha-contracts/0.1.12"
18
18
 
19
19
  type Client struct {
20
20
  BaseURL string
@@ -404,6 +404,15 @@ func (c *Client) ClaimDockerOperation(ctx context.Context, req DockerOperationCl
404
404
  return out.Data, nil
405
405
  }
406
406
 
407
+ func (c *Client) ExchangeDockerHostAgentEnrollment(ctx context.Context, operationID string, req DockerHostAgentEnrollmentRequest) (DockerHostAgentCredentials, error) {
408
+ var out DockerHostAgentCredentialsEnvelope
409
+ path := "/docker/agent-installations/" + url.PathEscape(strings.TrimSpace(operationID)) + "/enroll"
410
+ if err := c.doJSON(ctx, http.MethodPost, path, false, req, &out); err != nil {
411
+ return DockerHostAgentCredentials{}, err
412
+ }
413
+ return out.Data, nil
414
+ }
415
+
407
416
  func (c *Client) GetDockerOperationRunnerStatus(ctx context.Context, operationID string) (DockerOperation, error) {
408
417
  var out DockerOperationEnvelope
409
418
  path := "/docker/operations/" + url.PathEscape(strings.TrimSpace(operationID)) + "/runner-status"
@@ -40,6 +40,24 @@ func TestObservabilityCredentialKeyLegacyTypes(t *testing.T) {
40
40
  }
41
41
  }
42
42
 
43
+ func TestSAMLAttributeMappingLegacyConstants(t *testing.T) {
44
+ targets := map[SAMLAttributeMappingTarget]string{
45
+ Subject: "subject",
46
+ Username: "username",
47
+ Email: "email",
48
+ DisplayName: "displayName",
49
+ Role: "role",
50
+ Organization: "organization",
51
+ Team: "team",
52
+ Project: "project",
53
+ }
54
+ for target, want := range targets {
55
+ if string(target) != want || !target.Valid() {
56
+ t.Fatalf("SAMLAttributeMappingTarget %q is not the compatible value %q", target, want)
57
+ }
58
+ }
59
+ }
60
+
43
61
  func TestSystemHealthAndReadinessUsePublicRequests(t *testing.T) {
44
62
  cases := []struct {
45
63
  name string
@@ -125,6 +143,35 @@ func TestRunnerClaimClientsAcceptNoContent(t *testing.T) {
125
143
  }
126
144
  }
127
145
 
146
+ func TestExchangeDockerHostAgentEnrollmentIsPublicAndReturnsCredentials(t *testing.T) {
147
+ issuedAt := time.Now().UTC().Truncate(time.Second)
148
+ client := newTestClient(t, func(w http.ResponseWriter, r *http.Request) {
149
+ assertPublicRequest(t, r, http.MethodPost, "/api/v1/docker/agent-installations/operation-1/enroll")
150
+ request := decodeJSONRequestBody[DockerHostAgentEnrollmentRequest](t, r)
151
+ if request.AgentID != "host-1" || request.EnrollmentToken != "enrollment-secret-0123456789012345" {
152
+ t.Fatalf("enrollment request = %#v", request)
153
+ }
154
+ w.Header().Set("Cache-Control", "no-store")
155
+ w.WriteHeader(http.StatusCreated)
156
+ writeJSON(t, w, map[string]any{"data": map[string]any{
157
+ "hostId": "host-1", "operationId": "operation-1", "agentId": "host-1",
158
+ "agentBearerToken": "agent-secret-012345678901234567890",
159
+ "runtimeBearerToken": "runtime-secret-012345678901234567",
160
+ "issuedAt": issuedAt,
161
+ }})
162
+ })
163
+
164
+ credentials, err := client.ExchangeDockerHostAgentEnrollment(context.Background(), "operation-1", DockerHostAgentEnrollmentRequest{
165
+ AgentID: "host-1", EnrollmentToken: "enrollment-secret-0123456789012345",
166
+ })
167
+ if err != nil {
168
+ t.Fatalf("exchange enrollment: %v", err)
169
+ }
170
+ if credentials.HostID != "host-1" || credentials.OperationID != "operation-1" || credentials.RuntimeBearerToken == "" || credentials.AgentBearerToken == "" {
171
+ t.Fatalf("credentials = %#v", credentials)
172
+ }
173
+ }
174
+
128
175
  func TestRedeemSecretLeaseSendsRunnerBindingHeaders(t *testing.T) {
129
176
  client := newTestClient(t, func(w http.ResponseWriter, r *http.Request) {
130
177
  assertCommonRequest(t, r, http.MethodPost, "/api/v1/runner/secret-leases/lease%2Fone/redeem")