diff --git a/changes/unreleased/Added-20260905-184000.yaml b/changes/unreleased/Added-20260905-184000.yaml new file mode 100644 index 00000000..f7fcd3a2 --- /dev/null +++ b/changes/unreleased/Added-20260905-184000.yaml @@ -0,0 +1,5 @@ +kind: Added +body: 'The generic CRUD engine now serves `rest-json` services. That protocol carries no `X-Amz-Target` header, so the operation is recovered from the request method and path using the route table the model already declares — the same matcher the generated per-service routers use, now shared in `internal/shared/httproute`. 28 already-registered services stopped being registered-only without any change to their providers: services serving at least one operation went 117 to 145, and `auto-crud` operations 1,415 to 2,200. A path the route table does not know still declines with a clean AWS error rather than a fabricated success' +time: 2026-09-05T18:40:00.000000+09:00 +custom: + Issue: "139" diff --git a/cmd/devcloud/fidelity_test.go b/cmd/devcloud/fidelity_test.go index 9a24e1f2..0e31ce04 100644 --- a/cmd/devcloud/fidelity_test.go +++ b/cmd/devcloud/fidelity_test.go @@ -103,6 +103,16 @@ func TestFidelityManifestCoversRegisteredServices(t *testing.T) { // lists. func TestFidelityManifestCoversCRUDRegistry(t *testing.T) { for _, id := range plugin.DefaultRegistry.RegisteredServices() { + // Registry membership is classifiability, not reachability. The CRUD + // registry is built from the model, so it also holds operations for + // services whose hand-written provider refuses unknown operations + // itself (apigatewayv2, xray) — the engine is never routed to for + // those, so "unimplemented" is the truth and this check would be + // asserting the opposite. TestFidelityManifestCoverage's `served == 0 + // && RegisteredOps > 0` guard is what catches wiring that goes missing. + if !fidelity.Services[id].EngineWired { + continue + } for op := range crud.RegisteredOps(id) { tier, ok := fidelity.Lookup(id, op) if !ok { @@ -129,7 +139,13 @@ func TestAutoCRUDIsServedOverJSON(t *testing.T) { if tier != fidelity.TierAutoCRUD { continue } - if _, err := crud.Handle(id, op, "json-1.1", []byte("{}")); err != nil { + // Asked through the JSON path regardless of the service's real + // protocol: what "auto-crud" claims is that the operation is + // registered and CRUD-classified, which is exactly what this + // exercises. Whether a rest-json request also resolves to it is + // route matching, covered in internal/shared/crud and the compat + // suite. + if _, err := crud.Handle(crud.Call{Service: id, Protocol: "json-1.1", Op: op, Body: []byte("{}")}); err != nil { t.Errorf("%s/%s: declared auto-crud but the engine refused it: %v", id, op, err) } } diff --git a/docs/coverage.md b/docs/coverage.md index 548091eb..009c4b5a 100644 --- a/docs/coverage.md +++ b/docs/coverage.md @@ -10,37 +10,58 @@ things: | Number | What it means | Today | |---|---|---| | **Registered** | The gateway routes the service. A call reaches DevCloud instead of falling through to real AWS. | **148** | -| **Serving ≥1 operation** | At least one operation returns a real, store-backed answer — hand-written or served by the generic CRUD engine. | **117** | -| **Registered-only** | Routed, but every operation declines with a clean AWS error. Nothing is served. | **31** | +| **Serving ≥1 operation** | At least one operation returns a real, store-backed answer — hand-written or served by the generic CRUD engine. | **145** | +| **Registered-only** | Routed, but every operation declines with a clean AWS error. Nothing is served. | **3** | Per operation, from the [fidelity manifest](fidelity-manifest.md): | Tier | Operations | |---|---| | `hand-verified` | 4,496 | -| `auto-crud` | 1,415 | -| `unimplemented` | 3,119 | +| `auto-crud` | 2,200 | +| `unimplemented` | 2,334 | | **total known** | **9,030** | ## Why a registered service can serve nothing -The generic CRUD engine classifies an operation by its name, and only the -`X-Amz-Target` JSON protocols put the operation name where the router can see it -(`internal/shared/crud/crud.go`, `JSONProtocol`). A `rest-json`, `query` or -`rest-xml` service is therefore unreachable by the engine and serves nothing -until somebody writes its provider by hand. +The generic CRUD engine has to know which operation a request is for, and it has +to recognise that operation as CRUD-shaped. Two things can stop it. + +**The protocol does not say which operation.** The `X-Amz-Target` JSON protocols +name the operation in a header. `rest-json` does not, but every one of its +operations is bound to an HTTP method and a URI template in the model, and +`internal/shared/httproute` matches a request back to the operation from that +pair — so the engine serves it too. `query` and `rest-xml` have neither a target +header nor a modelled path the engine can match, so they are unreachable by it +and serve nothing until somebody writes the provider by hand. + +**The operation is not CRUD-shaped.** `GetThing`, `ListThings`, `CreateThing` +and their siblings map onto a generic store. `ExecuteStatement`, `InvokeEndpoint` +and `QueryForecast` do not, and the engine refuses them rather than inventing an +answer. A service whose entire API is that shape serves nothing whatever its +protocol. Registered services by protocol: | Protocol | Services | Engine-servable | |---|---|---| -| `json-1.1` | 49 | yes | -| `json-1.0` | 11 | yes | -| `rest-json` | 59 | no | +| `json-1.1` | 49 | yes — operation from `X-Amz-Target` | +| `json-1.0` | 11 | yes — operation from `X-Amz-Target` | +| `rest-json` | 59 | yes — operation from method + path | | `query` | 14 | no | | `rest-xml` | 3 | no | | no in-tree model | 12 | n/a — hand-written providers | +The three services that are registered and serve nothing are all the second +case, not the first: `forecastquery` (`json-1.1`, only `QueryForecast` and +`QueryWhatIfForecast`) and the two SageMaker Runtime variants (`rest-json`, only +`InvokeEndpoint*`). + +A registered operation is not automatically a reachable one. The engine is +entered only when a provider returns `plugin.ErrUnhandledOp`, so a hand-written +provider that refuses unknown operations itself — `apigatewayv2`, `xray` — never +reaches it, and the manifest records that per service as `EngineWired`. + Registering a service the engine cannot serve is deliberate, not an oversight. The alternative is worse: an unregistered service is not routed, so the SDK call leaves the machine and bills a real AWS account. A registered-only service @@ -56,19 +77,17 @@ The first category taken to completion. All 48 upstream models are registered. | | Count | |---|---| | Registered | 48 | -| Engine-served or hand-written | 17 | -| Registered-only | 31 | -| Operations served across the category | 935 | - -Engine-served: `bedrock`, `bedrock-data-automation-runtime`, `comprehend`, -`comprehendmedical`, `forecast`, `frauddetector`, `healthlake`, `kendra`, -`kendra-ranking`, `lookoutequipment`, `personalize`, `rekognition`, `sagemaker`, -`textract`, `transcribe`, `translate`, `voice-id`. - -Of the 31 registered-only, 30 are `rest-json`. The exception is `forecastquery`, -which is `json-1.1` but whose entire API is `QueryForecast` and -`QueryWhatIfForecast` — neither is CRUD-shaped, so there is nothing for the -engine to serve generically. +| Engine-served or hand-written | 45 | +| Registered-only | 3 | + +When this category was completed, only 17 of its 48 members served anything: 30 +of the other 31 were `rest-json`, which the engine could not read at all. Teaching +it that protocol moved 28 of those 30 into coverage without touching a single one +of their providers. + +The three that remain are the ones no protocol change can help — `forecastquery` +and the two SageMaker Runtime variants, none of which has a CRUD-shaped +operation. See [Why a registered service can serve nothing](#why-a-registered-service-can-serve-nothing). ## What counts as a service diff --git a/internal/codegen/gen_crud_meta.go b/internal/codegen/gen_crud_meta.go index 478058d3..3cb06ccb 100644 --- a/internal/codegen/gen_crud_meta.go +++ b/internal/codegen/gen_crud_meta.go @@ -28,6 +28,12 @@ type crudOpData struct { Resource string ListKey string ItemKey string + // Method and URI are the operation's REST binding, empty for a protocol + // that has none. rest-json names its operation in the method and path + // rather than in a header, so this pair is what lets the engine get back + // from a request to an operation name. + Method string + URI string } // verbPrefixes maps operation-name prefixes to canonical CRUD verbs, longest and @@ -117,21 +123,34 @@ func classifyOps(model *ir.Model) []crudOpData { Resource: resource, ListKey: listKey, ItemKey: itemKey, + Method: op.HTTPMethod, + URI: op.HTTPUri, }) } return ops } -// isJSONProtocol reports whether the engine can serve a service's protocol. -// Only X-Amz-Target JSON protocols carry an operation name at the router. -func isJSONProtocol(protocol string) bool { - return strings.HasPrefix(protocol, "json") +// engineServable reports whether the engine can serve a service's protocol. +// +// The JSON protocols carry the operation name in X-Amz-Target. rest-json does +// not, but every one of its operations is bound to a method and URI template, +// and internal/shared/httproute turns that pair back into an operation name — +// so the engine can classify it too. query and rest-xml have neither, which is +// what PRD Milestone 5 owns; admitting them here would mean guessing. +// +// This is deliberately the same question crud.Servable answers at runtime. The +// two must agree: a protocol classified here but refused there registers +// operations nothing can reach, and the fidelity manifest would call them +// auto-crud. +func engineServable(protocol string) bool { + return strings.HasPrefix(protocol, "json") || protocol == "rest-json" } -// ServiceCRUDData classifies a JSON-protocol model's CRUD operations. It returns -// (data, false) when the service is not engine-servable or has no CRUD ops. +// ServiceCRUDData classifies an engine-servable model's CRUD operations. It +// returns (data, false) when the service's protocol cannot be served or the +// model has no CRUD-shaped operation at all. func ServiceCRUDData(model *ir.Model) (CRUDServiceData, bool) { - if !isJSONProtocol(model.Protocol) { + if !engineServable(model.Protocol) { return CRUDServiceData{}, false } ops := classifyOps(model) diff --git a/internal/codegen/gen_crud_meta_test.go b/internal/codegen/gen_crud_meta_test.go new file mode 100644 index 00000000..932b60df --- /dev/null +++ b/internal/codegen/gen_crud_meta_test.go @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: Apache-2.0 + +// internal/codegen/gen_crud_meta_test.go +package codegen + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/skyoo2003/devcloud/internal/codegen/ir" +) + +// crudModel builds a minimal model with one list-returning and one +// item-returning output shape, so classifyOps has both output keys to find. +func crudModel(protocol string, ops ...ir.Operation) *ir.Model { + return &ir.Model{ + ServiceID: "testsvc", + Protocol: protocol, + Operations: ops, + Shapes: map[string]*ir.Shape{ + "GraphList": {Name: "GraphList", Type: ir.ShapeList}, + "Graph": {Name: "Graph", Type: ir.ShapeStructure}, + "ListGraphsOutput": {Name: "ListGraphsOutput", Type: ir.ShapeStructure, Members: []ir.Member{ + {Name: "Graphs", TargetName: "GraphList"}, + }}, + "GetGraphOutput": {Name: "GetGraphOutput", Type: ir.ShapeStructure, Members: []ir.Member{ + {Name: "Graph", TargetName: "Graph"}, + }}, + }, + } +} + +func opsOf(data CRUDServiceData) map[string]crudOpData { + out := make(map[string]crudOpData, len(data.Ops)) + for _, op := range data.Ops { + out[op.Op] = op + } + return out +} + +// TestServiceCRUDDataAcceptsRESTJSON is the change that makes Milestone 4 +// possible: 33 of the 57 demand-set services are restJson1, and refusing the +// protocol here is what left them registered but serving nothing. +func TestServiceCRUDDataAcceptsRESTJSON(t *testing.T) { + model := crudModel("rest-json", + ir.Operation{Name: "ListGraphs", OutputName: "ListGraphsOutput", + HTTPMethod: "GET", HTTPUri: "/v1/graphs"}, + ir.Operation{Name: "GetGraph", OutputName: "GetGraphOutput", + HTTPMethod: "GET", HTTPUri: "/v1/graphs/{GraphName}"}, + ) + + data, ok := ServiceCRUDData(model) + require.True(t, ok, "rest-json service must be engine-servable") + + ops := opsOf(data) + require.Contains(t, ops, "ListGraphs") + require.Contains(t, ops, "GetGraph") + + // Without the REST binding the engine has no way back from a request to an + // operation name, so carrying it is the whole point. + assert.Equal(t, "GET", ops["ListGraphs"].Method) + assert.Equal(t, "/v1/graphs", ops["ListGraphs"].URI) + assert.Equal(t, "/v1/graphs/{GraphName}", ops["GetGraph"].URI) + + // Classification itself is unchanged: the verb still comes from the name. + assert.Equal(t, "List", ops["ListGraphs"].Verb) + assert.Equal(t, "Graphs", ops["ListGraphs"].ListKey) + assert.Equal(t, "Get", ops["GetGraph"].Verb) + assert.Equal(t, "Graph", ops["GetGraph"].ItemKey) +} + +// TestServiceCRUDDataJSONUnchanged pins that admitting rest-json did not alter +// what the JSON protocols produce. A JSON model has no HTTP binding, and +// emitting an empty URI must not create a route that matches everything. +func TestServiceCRUDDataJSONUnchanged(t *testing.T) { + for _, protocol := range []string{"json-1.0", "json-1.1"} { + t.Run(protocol, func(t *testing.T) { + model := crudModel(protocol, + ir.Operation{Name: "ListGraphs", OutputName: "ListGraphsOutput"}, + ) + + data, ok := ServiceCRUDData(model) + require.True(t, ok) + + ops := opsOf(data) + assert.Equal(t, "List", ops["ListGraphs"].Verb) + assert.Empty(t, ops["ListGraphs"].Method) + assert.Empty(t, ops["ListGraphs"].URI) + }) + } +} + +// TestServiceCRUDDataRejectsUnservableProtocols holds the boundary Milestone 5 +// owns. query and rest-xml put the operation neither in a header nor in a +// modelled path the engine can match, so admitting them would serve fabricated +// answers to callers the engine cannot actually understand. +func TestServiceCRUDDataRejectsUnservableProtocols(t *testing.T) { + for _, protocol := range []string{"query", "rest-xml"} { + t.Run(protocol, func(t *testing.T) { + model := crudModel(protocol, + ir.Operation{Name: "ListGraphs", OutputName: "ListGraphsOutput", + HTTPMethod: "GET", HTTPUri: "/v1/graphs"}, + ) + + _, ok := ServiceCRUDData(model) + assert.False(t, ok, "%s must not be engine-servable", protocol) + }) + } +} + +// TestServiceCRUDDataSkipsUnclassifiableService is the rds-data case: a +// rest-json service whose entire API is ExecuteStatement-shaped classifies +// nothing, so it registers nothing and routes nothing, and every call to it +// gets a clean error instead of an invented success. +func TestServiceCRUDDataSkipsUnclassifiableService(t *testing.T) { + model := crudModel("rest-json", + ir.Operation{Name: "ExecuteStatement", OutputName: "GetGraphOutput", + HTTPMethod: "POST", HTTPUri: "/Execute"}, + ir.Operation{Name: "BeginTransaction", OutputName: "GetGraphOutput", + HTTPMethod: "POST", HTTPUri: "/BeginTransaction"}, + ) + + _, ok := ServiceCRUDData(model) + assert.False(t, ok, "a service with no CRUD-shaped operation must register nothing") +} diff --git a/internal/codegen/gen_fidelity.go b/internal/codegen/gen_fidelity.go index 6400956d..9326e610 100644 --- a/internal/codegen/gen_fidelity.go +++ b/internal/codegen/gen_fidelity.go @@ -24,6 +24,13 @@ type FidelityServiceData struct { // only this field lets a reader tell them apart. Protocol string ModelBacked bool + // EngineWired mirrors ProviderScan.EngineWired: does this provider hand + // unimplemented operations to the CRUD engine? Published because the CRUD + // registry is model-derived and so holds operations for providers the + // engine is never reached from; without this, "registered in the engine" + // reads as "served", which is the overstatement the manifest exists to + // prevent. + EngineWired bool Ops []FidelityOpData } @@ -109,6 +116,7 @@ func BuildFidelityData( ServiceID: serviceID, Protocol: protocols[serviceID], ModelBacked: len(modelOps[serviceID]) > 0, + EngineWired: provider.EngineWired, Ops: ops, }) } diff --git a/internal/codegen/gen_router_test.go b/internal/codegen/gen_router_test.go index 07b74da7..6b5b2349 100644 --- a/internal/codegen/gen_router_test.go +++ b/internal/codegen/gen_router_test.go @@ -15,11 +15,15 @@ func TestGenerateRouter(t *testing.T) { output, err := gen.GenerateRouter("s3", model) require.NoError(t, err) assert.Contains(t, output, "package s3") - assert.Contains(t, output, "type OperationRoute struct") assert.Contains(t, output, "OperationRoutes") assert.Contains(t, output, `"CreateBucket"`) assert.Contains(t, output, `"PUT"`) assert.Contains(t, output, `"/{Bucket}"`) + // The route table is generated per service; the matching is not. Asserting + // the delegation is what stops a future edit from re-inlining the algorithm + // into 148 packages, which is the drift internal/shared/httproute exists to + // prevent. + assert.Contains(t, output, "httproute.Match(OperationRoutes, method, uri)") } func TestGenerateErrors(t *testing.T) { diff --git a/internal/codegen/templates/crud_registry.go.tmpl b/internal/codegen/templates/crud_registry.go.tmpl index 4f96ae67..b1578714 100644 --- a/internal/codegen/templates/crud_registry.go.tmpl +++ b/internal/codegen/templates/crud_registry.go.tmpl @@ -12,7 +12,7 @@ func init() { {{- range .Services }} crud.Register("{{ .ServiceID }}", map[string]crud.OpMeta{ {{- range .Ops }} - "{{ .Op }}": {Verb: "{{ .Verb }}", Resource: "{{ .Resource }}", OutputListKey: "{{ .ListKey }}", OutputItemKey: "{{ .ItemKey }}"}, + "{{ .Op }}": {Verb: "{{ .Verb }}", Resource: "{{ .Resource }}", OutputListKey: "{{ .ListKey }}", OutputItemKey: "{{ .ItemKey }}"{{ if .URI }}, Method: "{{ .Method }}", URI: "{{ .URI }}"{{ end }}}, {{- end }} }) {{- end }} diff --git a/internal/codegen/templates/fidelity_manifest.go.tmpl b/internal/codegen/templates/fidelity_manifest.go.tmpl index ea84c92d..4138008d 100644 --- a/internal/codegen/templates/fidelity_manifest.go.tmpl +++ b/internal/codegen/templates/fidelity_manifest.go.tmpl @@ -46,13 +46,23 @@ type Service struct { // service's API. When false the unimplemented tail is not knowable, so the // manifest lists only what DevCloud serves. ModelBacked bool + // EngineWired reports whether the provider hands the operations it does not + // implement to the generic CRUD engine, by returning plugin.ErrUnhandledOp. + // + // It is the difference between an operation being *classifiable* and being + // *reachable*. The CRUD registry is built from the model, so it holds + // entries for services whose hand-written provider refuses unknown + // operations itself and never routes to the engine — for those, a + // registered operation is genuinely unimplemented, and only this field says + // so without guessing. + EngineWired bool Operations map[string]Tier } // Services maps a registered service ID to its operations. var Services = map[string]Service{ {{- range .Services }} - "{{ .ServiceID }}": {Protocol: "{{ .Protocol }}", ModelBacked: {{ .ModelBacked }}, Operations: map[string]Tier{ + "{{ .ServiceID }}": {Protocol: "{{ .Protocol }}", ModelBacked: {{ .ModelBacked }}, EngineWired: {{ .EngineWired }}, Operations: map[string]Tier{ {{- range .Ops }} "{{ .Name }}": Tier{{ .TierConst }}, {{- end }} diff --git a/internal/codegen/templates/router.go.tmpl b/internal/codegen/templates/router.go.tmpl index 98b9ff66..2ca6c4ee 100644 --- a/internal/codegen/templates/router.go.tmpl +++ b/internal/codegen/templates/router.go.tmpl @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package {{ .PkgName }} -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -31,126 +24,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/gateway/router.go b/internal/gateway/router.go index 78a49f3f..dc3a18e9 100644 --- a/internal/gateway/router.go +++ b/internal/gateway/router.go @@ -54,11 +54,12 @@ func (sr *ServiceRouter) ServeHTTP(w http.ResponseWriter, r *http.Request) { op := extractOperationName(r, protocol) - // Buffer the body for JSON protocols so the CRUD fallback engine can re-read - // it if the provider does not handle the operation. Cheap for JSON payloads; - // skipped for REST-XML (S3) where bodies may be large binary uploads. + // Buffer the body for the protocols the CRUD fallback engine can serve, so + // it can re-read it if the provider does not handle the operation. Cheap for + // JSON and rest-json payloads; skipped for REST-XML (S3), where bodies may + // be large binary uploads and the engine would refuse them anyway. var body []byte - if crud.JSONProtocol(protocol) { + if crud.Servable(protocol) { var rerr error if body, rerr = io.ReadAll(r.Body); rerr != nil { writeAWSError(w, protocol, http.StatusBadRequest, "SerializationException", "failed to read request body") @@ -73,7 +74,14 @@ func (sr *ServiceRouter) ServeHTTP(w http.ResponseWriter, r *http.Request) { // fallback for operations it does not implement. If the engine cannot // classify the operation either, emit the standard "unknown action" error. if errors.Is(err, plugin.ErrUnhandledOp) { - res, cerr := crud.Handle(serviceID, op, protocol, body) + res, cerr := crud.Handle(crud.Call{ + Service: serviceID, + Protocol: protocol, + Op: op, + Method: r.Method, + URI: r.URL.RequestURI(), + Body: body, + }) if cerr != nil { writeAWSError(w, protocol, http.StatusBadRequest, "InvalidAction", "unknown action: "+op) return diff --git a/internal/gateway/router_test.go b/internal/gateway/router_test.go index 022e1115..50e939f0 100644 --- a/internal/gateway/router_test.go +++ b/internal/gateway/router_test.go @@ -4,12 +4,16 @@ package gateway import ( "context" + "encoding/json" + "io" "net/http" "net/http/httptest" + "strings" "testing" "github.com/skyoo2003/devcloud/internal/admin" "github.com/skyoo2003/devcloud/internal/plugin" + "github.com/skyoo2003/devcloud/internal/shared/crud" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -128,3 +132,125 @@ func TestServiceRouter_NilUnroutedCollector(t *testing.T) { assert.NotPanics(t, func() { router.ServeHTTP(w, unroutedJSONRequest("amp")) }) assert.Equal(t, http.StatusBadRequest, w.Code) } + +// --- rest-json reaching the CRUD engine --- + +// decliningPlugin implements nothing and says so, which is what every +// scaffolded service does and what hands the request to the engine. +type decliningPlugin struct { + serviceID string + protocol plugin.ProtocolType +} + +func (d *decliningPlugin) ServiceID() string { return d.serviceID } +func (d *decliningPlugin) ServiceName() string { return d.serviceID } +func (d *decliningPlugin) Protocol() plugin.ProtocolType { return d.protocol } +func (d *decliningPlugin) Init(_ plugin.PluginConfig) error { return nil } +func (d *decliningPlugin) Shutdown(_ context.Context) error { return nil } +func (d *decliningPlugin) HandleRequest(_ context.Context, _ string, _ *http.Request) (*plugin.Response, error) { + return nil, plugin.ErrUnhandledOp +} +func (d *decliningPlugin) ListResources(_ context.Context) ([]plugin.Resource, error) { + return nil, nil +} + +func newDecliningRegistry(serviceID string, protocol plugin.ProtocolType) *plugin.Registry { + reg := plugin.NewRegistry() + p := &decliningPlugin{serviceID: serviceID, protocol: protocol} + reg.Register(serviceID, func() plugin.ServicePlugin { return p }) + _, _ = reg.Init(serviceID, plugin.PluginConfig{}) + return reg +} + +// restJSONRequest builds a SigV4-signed REST call, which is how DetectProtocol +// recognises a rest-json service (step 3, protocol.go). +func restJSONRequest(service, method, uri, body string) *http.Request { + var req *http.Request + if body == "" { + req = httptest.NewRequest(method, uri, nil) + } else { + req = httptest.NewRequest(method, uri, strings.NewReader(body)) + } + req.Header.Set("Authorization", + "AWS4-HMAC-SHA256 Credential=AKIA/20130524/us-east-1/"+service+"/aws4_request, Signature=abc") + return req +} + +// TestServiceRouter_RESTJSONBodyReachesEngine is the gateway half of the +// rest-json change. The engine can classify the operation from the path, but a +// Create takes its parameters from the body — and the body was only buffered +// for the JSON protocols, so it arrived empty and every created resource came +// back with a generated id instead of the caller's name. +func TestServiceRouter_RESTJSONBodyReachesEngine(t *testing.T) { + const svc = "gwrestsvc" + crud.Register(svc, map[string]crud.OpMeta{ + "CreateGadget": {Verb: "Create", Resource: "Gadget", OutputItemKey: "Gadget", + Method: "POST", URI: "/v1/gadgets"}, + }) + router := NewServiceRouter(newDecliningRegistry(svc, plugin.ProtocolRESTJSON), nil) + + w := httptest.NewRecorder() + router.ServeHTTP(w, restJSONRequest(svc, http.MethodPost, "/v1/gadgets", `{"GadgetName":"g1","Colour":"red"}`)) + + require.Equal(t, http.StatusOK, w.Code, "body: %s", w.Body.String()) + var out map[string]any + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &out)) + gadget, ok := out["Gadget"].(map[string]any) + require.True(t, ok, "no Gadget in %v", out) + assert.Equal(t, "g1", gadget["GadgetName"], "request body did not reach the engine") + assert.Equal(t, "red", gadget["Colour"]) +} + +// TestServiceRouter_RESTJSONUnmatchedPathDeclinesCleanly is the guarantee the +// coverage claim rests on: a registered service that cannot serve a request +// must answer with an AWS error, never a fabricated success. +func TestServiceRouter_RESTJSONUnmatchedPathDeclinesCleanly(t *testing.T) { + const svc = "gwmisssvc" + crud.Register(svc, map[string]crud.OpMeta{ + "ListGadgets": {Verb: "List", Resource: "MGadget", OutputListKey: "Gadgets", + Method: "GET", URI: "/v1/gadgets"}, + }) + router := NewServiceRouter(newDecliningRegistry(svc, plugin.ProtocolRESTJSON), nil) + + w := httptest.NewRecorder() + router.ServeHTTP(w, restJSONRequest(svc, http.MethodPost, "/v1/nothing/here", `{}`)) + + assert.Equal(t, http.StatusBadRequest, w.Code) + assert.Contains(t, w.Body.String(), "InvalidAction") +} + +// TestServiceRouter_RESTXMLBodyStillUnbuffered pins the exception. S3 bodies are +// large binary uploads, and reading one into memory to offer it to an engine +// that refuses rest-xml anyway would be a straight regression. +func TestServiceRouter_RESTXMLBodyStillUnbuffered(t *testing.T) { + var seen []byte + reg := plugin.NewRegistry() + p := &bodyCapturingPlugin{serviceID: "s3", seen: &seen} + reg.Register("s3", func() plugin.ServicePlugin { return p }) + _, _ = reg.Init("s3", plugin.PluginConfig{}) + router := NewServiceRouter(reg, nil) + + req := httptest.NewRequest(http.MethodPut, "/bucket/key", strings.NewReader("binary-payload")) + router.ServeHTTP(httptest.NewRecorder(), req) + + // The provider still reads the stream itself; the gateway did not consume it. + assert.Equal(t, "binary-payload", string(seen)) +} + +type bodyCapturingPlugin struct { + serviceID string + seen *[]byte +} + +func (b *bodyCapturingPlugin) ServiceID() string { return b.serviceID } +func (b *bodyCapturingPlugin) ServiceName() string { return b.serviceID } +func (b *bodyCapturingPlugin) Protocol() plugin.ProtocolType { return plugin.ProtocolRESTXML } +func (b *bodyCapturingPlugin) Init(_ plugin.PluginConfig) error { return nil } +func (b *bodyCapturingPlugin) Shutdown(_ context.Context) error { return nil } +func (b *bodyCapturingPlugin) HandleRequest(_ context.Context, _ string, req *http.Request) (*plugin.Response, error) { + *b.seen, _ = io.ReadAll(req.Body) + return &plugin.Response{StatusCode: http.StatusOK, Body: []byte("")}, nil +} +func (b *bodyCapturingPlugin) ListResources(_ context.Context) ([]plugin.Resource, error) { + return nil, nil +} diff --git a/internal/generated/acm/router.go b/internal/generated/acm/router.go index 7496e7c6..7f88bf80 100644 --- a/internal/generated/acm/router.go +++ b/internal/generated/acm/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package acm -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -45,126 +38,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/acmpca/router.go b/internal/generated/acmpca/router.go index ea691b2a..29f84603 100644 --- a/internal/generated/acmpca/router.go +++ b/internal/generated/acmpca/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package acmpca -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -51,126 +44,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/amplify/router.go b/internal/generated/amplify/router.go index 2178650f..f55876ac 100644 --- a/internal/generated/amplify/router.go +++ b/internal/generated/amplify/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package amplify -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -65,126 +58,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/apigatewayv2/router.go b/internal/generated/apigatewayv2/router.go index a8a7bcec..d1b95b85 100644 --- a/internal/generated/apigatewayv2/router.go +++ b/internal/generated/apigatewayv2/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package apigatewayv2 -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -131,126 +124,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/appconfig/router.go b/internal/generated/appconfig/router.go index 015cbef1..8861909b 100644 --- a/internal/generated/appconfig/router.go +++ b/internal/generated/appconfig/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package appconfig -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -73,126 +66,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/applicationautoscaling/router.go b/internal/generated/applicationautoscaling/router.go index a8d4e81f..32ed6c89 100644 --- a/internal/generated/applicationautoscaling/router.go +++ b/internal/generated/applicationautoscaling/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package applicationautoscaling -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -42,126 +35,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/appsync/router.go b/internal/generated/appsync/router.go index 10937d6b..17f47747 100644 --- a/internal/generated/appsync/router.go +++ b/internal/generated/appsync/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package appsync -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -102,126 +95,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/athena/router.go b/internal/generated/athena/router.go index a31c5efe..c0d3c3e7 100644 --- a/internal/generated/athena/router.go +++ b/internal/generated/athena/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package athena -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -98,126 +91,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/autoscaling/router.go b/internal/generated/autoscaling/router.go index 89856216..3faef439 100644 --- a/internal/generated/autoscaling/router.go +++ b/internal/generated/autoscaling/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package autoscaling -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -94,126 +87,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/backup/router.go b/internal/generated/backup/router.go index 3e5c1eb2..900a4c8e 100644 --- a/internal/generated/backup/router.go +++ b/internal/generated/backup/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package backup -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -136,126 +129,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/batch/router.go b/internal/generated/batch/router.go index c758518d..2dbf7f69 100644 --- a/internal/generated/batch/router.go +++ b/internal/generated/batch/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package batch -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -73,126 +66,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/bedrock/router.go b/internal/generated/bedrock/router.go index 2b927b4c..0f81f8a3 100644 --- a/internal/generated/bedrock/router.go +++ b/internal/generated/bedrock/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package bedrock -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -129,126 +122,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/bedrockagent/router.go b/internal/generated/bedrockagent/router.go index 4a185242..90c1463b 100644 --- a/internal/generated/bedrockagent/router.go +++ b/internal/generated/bedrockagent/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package bedrockagent -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -103,126 +96,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/bedrockagentcore/router.go b/internal/generated/bedrockagentcore/router.go index dd229012..0adb8c39 100644 --- a/internal/generated/bedrockagentcore/router.go +++ b/internal/generated/bedrockagentcore/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package bedrockagentcore -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -95,126 +88,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/bedrockagentcorecontrol/router.go b/internal/generated/bedrockagentcorecontrol/router.go index e3136f1f..01ced9b2 100644 --- a/internal/generated/bedrockagentcorecontrol/router.go +++ b/internal/generated/bedrockagentcorecontrol/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package bedrockagentcorecontrol -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -198,126 +191,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/bedrockagentruntime/router.go b/internal/generated/bedrockagentruntime/router.go index 699ba827..09dc8e43 100644 --- a/internal/generated/bedrockagentruntime/router.go +++ b/internal/generated/bedrockagentruntime/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package bedrockagentruntime -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -63,126 +56,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/bedrockdataautomation/router.go b/internal/generated/bedrockdataautomation/router.go index c209311e..a3a39768 100644 --- a/internal/generated/bedrockdataautomation/router.go +++ b/internal/generated/bedrockdataautomation/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package bedrockdataautomation -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -55,126 +48,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/bedrockdataautomationruntime/router.go b/internal/generated/bedrockdataautomationruntime/router.go index 1f7bb83c..60276895 100644 --- a/internal/generated/bedrockdataautomationruntime/router.go +++ b/internal/generated/bedrockdataautomationruntime/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package bedrockdataautomationruntime -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -34,126 +27,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/bedrockruntime/router.go b/internal/generated/bedrockruntime/router.go index 6004e478..4e253b9a 100644 --- a/internal/generated/bedrockruntime/router.go +++ b/internal/generated/bedrockruntime/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package bedrockruntime -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -39,126 +32,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/cloudformation/router.go b/internal/generated/cloudformation/router.go index 91a99f82..b3ea18d9 100644 --- a/internal/generated/cloudformation/router.go +++ b/internal/generated/cloudformation/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package cloudformation -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -118,126 +111,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/cloudfront/router.go b/internal/generated/cloudfront/router.go index a53bc7e8..31879b8a 100644 --- a/internal/generated/cloudfront/router.go +++ b/internal/generated/cloudfront/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package cloudfront -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -195,126 +188,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/cloudsearch/router.go b/internal/generated/cloudsearch/router.go index ba837ff7..3c08ce84 100644 --- a/internal/generated/cloudsearch/router.go +++ b/internal/generated/cloudsearch/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package cloudsearch -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -54,126 +47,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/cloudtrail/router.go b/internal/generated/cloudtrail/router.go index be6fd157..48bac6bd 100644 --- a/internal/generated/cloudtrail/router.go +++ b/internal/generated/cloudtrail/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package cloudtrail -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -88,126 +81,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/cloudwatch/router.go b/internal/generated/cloudwatch/router.go index 7b69d710..c2d6f5a9 100644 --- a/internal/generated/cloudwatch/router.go +++ b/internal/generated/cloudwatch/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package cloudwatch -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -74,126 +67,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/cloudwatchlogs/router.go b/internal/generated/cloudwatchlogs/router.go index 9d2141a9..fbdfaed9 100644 --- a/internal/generated/cloudwatchlogs/router.go +++ b/internal/generated/cloudwatchlogs/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package cloudwatchlogs -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -141,126 +134,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/codeartifact/router.go b/internal/generated/codeartifact/router.go index f87416b3..6c5b17ff 100644 --- a/internal/generated/codeartifact/router.go +++ b/internal/generated/codeartifact/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package codeartifact -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -76,126 +69,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/codebuild/router.go b/internal/generated/codebuild/router.go index a54ada0e..43f88f86 100644 --- a/internal/generated/codebuild/router.go +++ b/internal/generated/codebuild/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package codebuild -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -87,126 +80,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/codecommit/router.go b/internal/generated/codecommit/router.go index 859dc650..6a36ac21 100644 --- a/internal/generated/codecommit/router.go +++ b/internal/generated/codecommit/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package codecommit -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -107,126 +100,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/codedeploy/router.go b/internal/generated/codedeploy/router.go index 8d4d8e5e..54be9a11 100644 --- a/internal/generated/codedeploy/router.go +++ b/internal/generated/codedeploy/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package codedeploy -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -75,126 +68,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/codeguruprofiler/router.go b/internal/generated/codeguruprofiler/router.go index 89d5265c..34cb0df4 100644 --- a/internal/generated/codeguruprofiler/router.go +++ b/internal/generated/codeguruprofiler/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package codeguruprofiler -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -51,126 +44,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/codegurureviewer/router.go b/internal/generated/codegurureviewer/router.go index bb88a934..02f1c1e2 100644 --- a/internal/generated/codegurureviewer/router.go +++ b/internal/generated/codegurureviewer/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package codegurureviewer -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -42,126 +35,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/codegurusecurity/router.go b/internal/generated/codegurusecurity/router.go index de0b5065..a8749014 100644 --- a/internal/generated/codegurusecurity/router.go +++ b/internal/generated/codegurusecurity/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package codegurusecurity -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -41,126 +34,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/codepipeline/router.go b/internal/generated/codepipeline/router.go index ac551024..0c2423cb 100644 --- a/internal/generated/codepipeline/router.go +++ b/internal/generated/codepipeline/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package codepipeline -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -72,126 +65,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/cognitoidentity/router.go b/internal/generated/cognitoidentity/router.go index ac3cbddb..77958cce 100644 --- a/internal/generated/cognitoidentity/router.go +++ b/internal/generated/cognitoidentity/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package cognitoidentity -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -51,126 +44,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/cognitoidentityprovider/router.go b/internal/generated/cognitoidentityprovider/router.go index 395d9fd0..8383e623 100644 --- a/internal/generated/cognitoidentityprovider/router.go +++ b/internal/generated/cognitoidentityprovider/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package cognitoidentityprovider -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -150,126 +143,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/comprehend/router.go b/internal/generated/comprehend/router.go index 0a804368..1a3c598d 100644 --- a/internal/generated/comprehend/router.go +++ b/internal/generated/comprehend/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package comprehend -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -113,126 +106,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/comprehendmedical/router.go b/internal/generated/comprehendmedical/router.go index 84d54ea4..37d03c36 100644 --- a/internal/generated/comprehendmedical/router.go +++ b/internal/generated/comprehendmedical/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package comprehendmedical -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -54,126 +47,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/configservice/router.go b/internal/generated/configservice/router.go index 255d7728..e4fff207 100644 --- a/internal/generated/configservice/router.go +++ b/internal/generated/configservice/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package configservice -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -125,126 +118,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/costexplorer/router.go b/internal/generated/costexplorer/router.go index 6d2973b5..b88e118c 100644 --- a/internal/generated/costexplorer/router.go +++ b/internal/generated/costexplorer/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package costexplorer -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -75,126 +68,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/crudregistry/registry_gen.go b/internal/generated/crudregistry/registry_gen.go index 3de79e91..645f2f47 100644 --- a/internal/generated/crudregistry/registry_gen.go +++ b/internal/generated/crudregistry/registry_gen.go @@ -40,6 +40,183 @@ func init() { "UntagCertificateAuthority": {Verb: "Untag", Resource: "CertificateAuthority", OutputListKey: "", OutputItemKey: ""}, "UpdateCertificateAuthority": {Verb: "Update", Resource: "CertificateAuthority", OutputListKey: "", OutputItemKey: ""}, }) + crud.Register("amplify", map[string]crud.OpMeta{ + "CreateApp": {Verb: "Create", Resource: "App", OutputListKey: "", OutputItemKey: "app", Method: "POST", URI: "/apps"}, + "CreateBackendEnvironment": {Verb: "Create", Resource: "BackendEnvironment", OutputListKey: "", OutputItemKey: "backendEnvironment", Method: "POST", URI: "/apps/{appId}/backendenvironments"}, + "CreateBranch": {Verb: "Create", Resource: "Branch", OutputListKey: "", OutputItemKey: "branch", Method: "POST", URI: "/apps/{appId}/branches"}, + "CreateDeployment": {Verb: "Create", Resource: "Deployment", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/apps/{appId}/branches/{branchName}/deployments"}, + "CreateDomainAssociation": {Verb: "Create", Resource: "DomainAssociation", OutputListKey: "", OutputItemKey: "domainAssociation", Method: "POST", URI: "/apps/{appId}/domains"}, + "CreateWebhook": {Verb: "Create", Resource: "Webhook", OutputListKey: "", OutputItemKey: "webhook", Method: "POST", URI: "/apps/{appId}/webhooks"}, + "DeleteApp": {Verb: "Delete", Resource: "App", OutputListKey: "", OutputItemKey: "app", Method: "DELETE", URI: "/apps/{appId}"}, + "DeleteBackendEnvironment": {Verb: "Delete", Resource: "BackendEnvironment", OutputListKey: "", OutputItemKey: "backendEnvironment", Method: "DELETE", URI: "/apps/{appId}/backendenvironments/{environmentName}"}, + "DeleteBranch": {Verb: "Delete", Resource: "Branch", OutputListKey: "", OutputItemKey: "branch", Method: "DELETE", URI: "/apps/{appId}/branches/{branchName}"}, + "DeleteDomainAssociation": {Verb: "Delete", Resource: "DomainAssociation", OutputListKey: "", OutputItemKey: "domainAssociation", Method: "DELETE", URI: "/apps/{appId}/domains/{domainName}"}, + "DeleteJob": {Verb: "Delete", Resource: "Job", OutputListKey: "", OutputItemKey: "jobSummary", Method: "DELETE", URI: "/apps/{appId}/branches/{branchName}/jobs/{jobId}"}, + "DeleteWebhook": {Verb: "Delete", Resource: "Webhook", OutputListKey: "", OutputItemKey: "webhook", Method: "DELETE", URI: "/webhooks/{webhookId}"}, + "GetApp": {Verb: "Get", Resource: "App", OutputListKey: "", OutputItemKey: "app", Method: "GET", URI: "/apps/{appId}"}, + "GetArtifactUrl": {Verb: "Get", Resource: "ArtifactUrl", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/artifacts/{artifactId}"}, + "GetBackendEnvironment": {Verb: "Get", Resource: "BackendEnvironment", OutputListKey: "", OutputItemKey: "backendEnvironment", Method: "GET", URI: "/apps/{appId}/backendenvironments/{environmentName}"}, + "GetBranch": {Verb: "Get", Resource: "Branch", OutputListKey: "", OutputItemKey: "branch", Method: "GET", URI: "/apps/{appId}/branches/{branchName}"}, + "GetDomainAssociation": {Verb: "Get", Resource: "DomainAssociation", OutputListKey: "", OutputItemKey: "domainAssociation", Method: "GET", URI: "/apps/{appId}/domains/{domainName}"}, + "GetJob": {Verb: "Get", Resource: "Job", OutputListKey: "", OutputItemKey: "job", Method: "GET", URI: "/apps/{appId}/branches/{branchName}/jobs/{jobId}"}, + "GetWebhook": {Verb: "Get", Resource: "Webhook", OutputListKey: "", OutputItemKey: "webhook", Method: "GET", URI: "/webhooks/{webhookId}"}, + "ListApps": {Verb: "List", Resource: "App", OutputListKey: "apps", OutputItemKey: "", Method: "GET", URI: "/apps"}, + "ListArtifacts": {Verb: "List", Resource: "Artifact", OutputListKey: "artifacts", OutputItemKey: "", Method: "GET", URI: "/apps/{appId}/branches/{branchName}/jobs/{jobId}/artifacts"}, + "ListBackendEnvironments": {Verb: "List", Resource: "BackendEnvironment", OutputListKey: "backendEnvironments", OutputItemKey: "", Method: "GET", URI: "/apps/{appId}/backendenvironments"}, + "ListBranches": {Verb: "List", Resource: "Branche", OutputListKey: "branches", OutputItemKey: "", Method: "GET", URI: "/apps/{appId}/branches"}, + "ListDomainAssociations": {Verb: "List", Resource: "DomainAssociation", OutputListKey: "domainAssociations", OutputItemKey: "", Method: "GET", URI: "/apps/{appId}/domains"}, + "ListJobs": {Verb: "List", Resource: "Job", OutputListKey: "jobSummaries", OutputItemKey: "", Method: "GET", URI: "/apps/{appId}/branches/{branchName}/jobs"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/tags/{resourceArn}"}, + "ListWebhooks": {Verb: "List", Resource: "Webhook", OutputListKey: "webhooks", OutputItemKey: "", Method: "GET", URI: "/apps/{appId}/webhooks"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/tags/{resourceArn}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/tags/{resourceArn}"}, + "UpdateApp": {Verb: "Update", Resource: "App", OutputListKey: "", OutputItemKey: "app", Method: "POST", URI: "/apps/{appId}"}, + "UpdateBranch": {Verb: "Update", Resource: "Branch", OutputListKey: "", OutputItemKey: "branch", Method: "POST", URI: "/apps/{appId}/branches/{branchName}"}, + "UpdateDomainAssociation": {Verb: "Update", Resource: "DomainAssociation", OutputListKey: "", OutputItemKey: "domainAssociation", Method: "POST", URI: "/apps/{appId}/domains/{domainName}"}, + "UpdateWebhook": {Verb: "Update", Resource: "Webhook", OutputListKey: "", OutputItemKey: "webhook", Method: "POST", URI: "/webhooks/{webhookId}"}, + }) + crud.Register("apigatewayv2", map[string]crud.OpMeta{ + "CreateApi": {Verb: "Create", Resource: "Api", OutputListKey: "ImportInfo", OutputItemKey: "CorsConfiguration", Method: "POST", URI: "/v2/apis"}, + "CreateApiMapping": {Verb: "Create", Resource: "ApiMapping", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v2/domainnames/{DomainName}/apimappings"}, + "CreateAuthorizer": {Verb: "Create", Resource: "Authorizer", OutputListKey: "IdentitySource", OutputItemKey: "JwtConfiguration", Method: "POST", URI: "/v2/apis/{ApiId}/authorizers"}, + "CreateDeployment": {Verb: "Create", Resource: "Deployment", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v2/apis/{ApiId}/deployments"}, + "CreateDomainName": {Verb: "Create", Resource: "DomainName", OutputListKey: "DomainNameConfigurations", OutputItemKey: "MutualTlsAuthentication", Method: "POST", URI: "/v2/domainnames"}, + "CreateIntegration": {Verb: "Create", Resource: "Integration", OutputListKey: "", OutputItemKey: "TlsConfig", Method: "POST", URI: "/v2/apis/{ApiId}/integrations"}, + "CreateIntegrationResponse": {Verb: "Create", Resource: "IntegrationResponse", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v2/apis/{ApiId}/integrations/{IntegrationId}/integrationresponses"}, + "CreateModel": {Verb: "Create", Resource: "Model", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v2/apis/{ApiId}/models"}, + "CreatePortal": {Verb: "Create", Resource: "Portal", OutputListKey: "IncludedPortalProductArns", OutputItemKey: "Authorization", Method: "POST", URI: "/v2/portals"}, + "CreatePortalProduct": {Verb: "Create", Resource: "PortalProduct", OutputListKey: "", OutputItemKey: "DisplayOrder", Method: "POST", URI: "/v2/portalproducts"}, + "CreateProductPage": {Verb: "Create", Resource: "ProductPage", OutputListKey: "", OutputItemKey: "DisplayContent", Method: "POST", URI: "/v2/portalproducts/{PortalProductId}/productpages"}, + "CreateProductRestEndpointPage": {Verb: "Create", Resource: "ProductRestEndpointPage", OutputListKey: "", OutputItemKey: "DisplayContent", Method: "POST", URI: "/v2/portalproducts/{PortalProductId}/productrestendpointpages"}, + "CreateRoute": {Verb: "Create", Resource: "Route", OutputListKey: "AuthorizationScopes", OutputItemKey: "", Method: "POST", URI: "/v2/apis/{ApiId}/routes"}, + "CreateRouteResponse": {Verb: "Create", Resource: "RouteResponse", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v2/apis/{ApiId}/routes/{RouteId}/routeresponses"}, + "CreateRoutingRule": {Verb: "Create", Resource: "RoutingRule", OutputListKey: "Actions", OutputItemKey: "", Method: "POST", URI: "/v2/domainnames/{DomainName}/routingrules"}, + "CreateStage": {Verb: "Create", Resource: "Stage", OutputListKey: "", OutputItemKey: "AccessLogSettings", Method: "POST", URI: "/v2/apis/{ApiId}/stages"}, + "CreateVpcLink": {Verb: "Create", Resource: "VpcLink", OutputListKey: "SecurityGroupIds", OutputItemKey: "", Method: "POST", URI: "/v2/vpclinks"}, + "DeleteAccessLogSettings": {Verb: "Delete", Resource: "AccessLogSetting", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/apis/{ApiId}/stages/{StageName}/accesslogsettings"}, + "DeleteApi": {Verb: "Delete", Resource: "Api", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/apis/{ApiId}"}, + "DeleteApiMapping": {Verb: "Delete", Resource: "ApiMapping", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/domainnames/{DomainName}/apimappings/{ApiMappingId}"}, + "DeleteAuthorizer": {Verb: "Delete", Resource: "Authorizer", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/apis/{ApiId}/authorizers/{AuthorizerId}"}, + "DeleteCorsConfiguration": {Verb: "Delete", Resource: "CorsConfiguration", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/apis/{ApiId}/cors"}, + "DeleteDeployment": {Verb: "Delete", Resource: "Deployment", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/apis/{ApiId}/deployments/{DeploymentId}"}, + "DeleteDomainName": {Verb: "Delete", Resource: "DomainName", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/domainnames/{DomainName}"}, + "DeleteIntegration": {Verb: "Delete", Resource: "Integration", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/apis/{ApiId}/integrations/{IntegrationId}"}, + "DeleteIntegrationResponse": {Verb: "Delete", Resource: "IntegrationResponse", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/apis/{ApiId}/integrations/{IntegrationId}/integrationresponses/{IntegrationResponseId}"}, + "DeleteModel": {Verb: "Delete", Resource: "Model", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/apis/{ApiId}/models/{ModelId}"}, + "DeletePortal": {Verb: "Delete", Resource: "Portal", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/portals/{PortalId}"}, + "DeletePortalProduct": {Verb: "Delete", Resource: "PortalProduct", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/portalproducts/{PortalProductId}"}, + "DeletePortalProductSharingPolicy": {Verb: "Delete", Resource: "PortalProductSharingPolicy", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/portalproducts/{PortalProductId}/sharingpolicy"}, + "DeleteProductPage": {Verb: "Delete", Resource: "ProductPage", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/portalproducts/{PortalProductId}/productpages/{ProductPageId}"}, + "DeleteProductRestEndpointPage": {Verb: "Delete", Resource: "ProductRestEndpointPage", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/portalproducts/{PortalProductId}/productrestendpointpages/{ProductRestEndpointPageId}"}, + "DeleteRoute": {Verb: "Delete", Resource: "Route", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/apis/{ApiId}/routes/{RouteId}"}, + "DeleteRouteRequestParameter": {Verb: "Delete", Resource: "RouteRequestParameter", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/apis/{ApiId}/routes/{RouteId}/requestparameters/{RequestParameterKey}"}, + "DeleteRouteResponse": {Verb: "Delete", Resource: "RouteResponse", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/apis/{ApiId}/routes/{RouteId}/routeresponses/{RouteResponseId}"}, + "DeleteRouteSettings": {Verb: "Delete", Resource: "RouteSetting", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/apis/{ApiId}/stages/{StageName}/routesettings/{RouteKey}"}, + "DeleteRoutingRule": {Verb: "Delete", Resource: "RoutingRule", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/domainnames/{DomainName}/routingrules/{RoutingRuleId}"}, + "DeleteStage": {Verb: "Delete", Resource: "Stage", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/apis/{ApiId}/stages/{StageName}"}, + "DeleteVpcLink": {Verb: "Delete", Resource: "VpcLink", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/vpclinks/{VpcLinkId}"}, + "GetApi": {Verb: "Get", Resource: "Api", OutputListKey: "ImportInfo", OutputItemKey: "CorsConfiguration", Method: "GET", URI: "/v2/apis/{ApiId}"}, + "GetApiMapping": {Verb: "Get", Resource: "ApiMapping", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v2/domainnames/{DomainName}/apimappings/{ApiMappingId}"}, + "GetApiMappings": {Verb: "Get", Resource: "ApiMapping", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/v2/domainnames/{DomainName}/apimappings"}, + "GetApis": {Verb: "Get", Resource: "Api", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/v2/apis"}, + "GetAuthorizer": {Verb: "Get", Resource: "Authorizer", OutputListKey: "IdentitySource", OutputItemKey: "JwtConfiguration", Method: "GET", URI: "/v2/apis/{ApiId}/authorizers/{AuthorizerId}"}, + "GetAuthorizers": {Verb: "Get", Resource: "Authorizer", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/v2/apis/{ApiId}/authorizers"}, + "GetDeployment": {Verb: "Get", Resource: "Deployment", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v2/apis/{ApiId}/deployments/{DeploymentId}"}, + "GetDeployments": {Verb: "Get", Resource: "Deployment", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/v2/apis/{ApiId}/deployments"}, + "GetDomainName": {Verb: "Get", Resource: "DomainName", OutputListKey: "DomainNameConfigurations", OutputItemKey: "MutualTlsAuthentication", Method: "GET", URI: "/v2/domainnames/{DomainName}"}, + "GetDomainNames": {Verb: "Get", Resource: "DomainName", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/v2/domainnames"}, + "GetIntegration": {Verb: "Get", Resource: "Integration", OutputListKey: "", OutputItemKey: "TlsConfig", Method: "GET", URI: "/v2/apis/{ApiId}/integrations/{IntegrationId}"}, + "GetIntegrationResponse": {Verb: "Get", Resource: "IntegrationResponse", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v2/apis/{ApiId}/integrations/{IntegrationId}/integrationresponses/{IntegrationResponseId}"}, + "GetIntegrationResponses": {Verb: "Get", Resource: "IntegrationResponse", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/v2/apis/{ApiId}/integrations/{IntegrationId}/integrationresponses"}, + "GetIntegrations": {Verb: "Get", Resource: "Integration", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/v2/apis/{ApiId}/integrations"}, + "GetModel": {Verb: "Get", Resource: "Model", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v2/apis/{ApiId}/models/{ModelId}"}, + "GetModelTemplate": {Verb: "Get", Resource: "ModelTemplate", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v2/apis/{ApiId}/models/{ModelId}/template"}, + "GetModels": {Verb: "Get", Resource: "Model", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/v2/apis/{ApiId}/models"}, + "GetPortal": {Verb: "Get", Resource: "Portal", OutputListKey: "IncludedPortalProductArns", OutputItemKey: "Authorization", Method: "GET", URI: "/v2/portals/{PortalId}"}, + "GetPortalProduct": {Verb: "Get", Resource: "PortalProduct", OutputListKey: "", OutputItemKey: "DisplayOrder", Method: "GET", URI: "/v2/portalproducts/{PortalProductId}"}, + "GetPortalProductSharingPolicy": {Verb: "Get", Resource: "PortalProductSharingPolicy", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v2/portalproducts/{PortalProductId}/sharingpolicy"}, + "GetProductPage": {Verb: "Get", Resource: "ProductPage", OutputListKey: "", OutputItemKey: "DisplayContent", Method: "GET", URI: "/v2/portalproducts/{PortalProductId}/productpages/{ProductPageId}"}, + "GetProductRestEndpointPage": {Verb: "Get", Resource: "ProductRestEndpointPage", OutputListKey: "", OutputItemKey: "DisplayContent", Method: "GET", URI: "/v2/portalproducts/{PortalProductId}/productrestendpointpages/{ProductRestEndpointPageId}"}, + "GetRoute": {Verb: "Get", Resource: "Route", OutputListKey: "AuthorizationScopes", OutputItemKey: "", Method: "GET", URI: "/v2/apis/{ApiId}/routes/{RouteId}"}, + "GetRouteResponse": {Verb: "Get", Resource: "RouteResponse", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v2/apis/{ApiId}/routes/{RouteId}/routeresponses/{RouteResponseId}"}, + "GetRouteResponses": {Verb: "Get", Resource: "RouteResponse", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/v2/apis/{ApiId}/routes/{RouteId}/routeresponses"}, + "GetRoutes": {Verb: "Get", Resource: "Route", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/v2/apis/{ApiId}/routes"}, + "GetRoutingRule": {Verb: "Get", Resource: "RoutingRule", OutputListKey: "Actions", OutputItemKey: "", Method: "GET", URI: "/v2/domainnames/{DomainName}/routingrules/{RoutingRuleId}"}, + "GetStage": {Verb: "Get", Resource: "Stage", OutputListKey: "", OutputItemKey: "AccessLogSettings", Method: "GET", URI: "/v2/apis/{ApiId}/stages/{StageName}"}, + "GetStages": {Verb: "Get", Resource: "Stage", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/v2/apis/{ApiId}/stages"}, + "GetTags": {Verb: "Get", Resource: "Tag", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v2/tags/{ResourceArn}"}, + "GetVpcLink": {Verb: "Get", Resource: "VpcLink", OutputListKey: "SecurityGroupIds", OutputItemKey: "", Method: "GET", URI: "/v2/vpclinks/{VpcLinkId}"}, + "GetVpcLinks": {Verb: "Get", Resource: "VpcLink", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/v2/vpclinks"}, + "ListPortalProducts": {Verb: "List", Resource: "PortalProduct", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/v2/portalproducts"}, + "ListPortals": {Verb: "List", Resource: "Portal", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/v2/portals"}, + "ListProductPages": {Verb: "List", Resource: "ProductPage", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/v2/portalproducts/{PortalProductId}/productpages"}, + "ListProductRestEndpointPages": {Verb: "List", Resource: "ProductRestEndpointPage", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/v2/portalproducts/{PortalProductId}/productrestendpointpages"}, + "ListRoutingRules": {Verb: "List", Resource: "RoutingRule", OutputListKey: "RoutingRules", OutputItemKey: "", Method: "GET", URI: "/v2/domainnames/{DomainName}/routingrules"}, + "PutPortalProductSharingPolicy": {Verb: "Update", Resource: "PortalProductSharingPolicy", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/portalproducts/{PortalProductId}/sharingpolicy"}, + "PutRoutingRule": {Verb: "Update", Resource: "RoutingRule", OutputListKey: "Actions", OutputItemKey: "", Method: "PUT", URI: "/v2/domainnames/{DomainName}/routingrules/{RoutingRuleId}"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v2/tags/{ResourceArn}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/tags/{ResourceArn}"}, + "UpdateApi": {Verb: "Update", Resource: "Api", OutputListKey: "ImportInfo", OutputItemKey: "CorsConfiguration", Method: "PATCH", URI: "/v2/apis/{ApiId}"}, + "UpdateApiMapping": {Verb: "Update", Resource: "ApiMapping", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/v2/domainnames/{DomainName}/apimappings/{ApiMappingId}"}, + "UpdateAuthorizer": {Verb: "Update", Resource: "Authorizer", OutputListKey: "IdentitySource", OutputItemKey: "JwtConfiguration", Method: "PATCH", URI: "/v2/apis/{ApiId}/authorizers/{AuthorizerId}"}, + "UpdateDeployment": {Verb: "Update", Resource: "Deployment", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/v2/apis/{ApiId}/deployments/{DeploymentId}"}, + "UpdateDomainName": {Verb: "Update", Resource: "DomainName", OutputListKey: "DomainNameConfigurations", OutputItemKey: "MutualTlsAuthentication", Method: "PATCH", URI: "/v2/domainnames/{DomainName}"}, + "UpdateIntegration": {Verb: "Update", Resource: "Integration", OutputListKey: "", OutputItemKey: "TlsConfig", Method: "PATCH", URI: "/v2/apis/{ApiId}/integrations/{IntegrationId}"}, + "UpdateIntegrationResponse": {Verb: "Update", Resource: "IntegrationResponse", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/v2/apis/{ApiId}/integrations/{IntegrationId}/integrationresponses/{IntegrationResponseId}"}, + "UpdateModel": {Verb: "Update", Resource: "Model", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/v2/apis/{ApiId}/models/{ModelId}"}, + "UpdatePortal": {Verb: "Update", Resource: "Portal", OutputListKey: "IncludedPortalProductArns", OutputItemKey: "Authorization", Method: "PATCH", URI: "/v2/portals/{PortalId}"}, + "UpdatePortalProduct": {Verb: "Update", Resource: "PortalProduct", OutputListKey: "", OutputItemKey: "DisplayOrder", Method: "PATCH", URI: "/v2/portalproducts/{PortalProductId}"}, + "UpdateProductPage": {Verb: "Update", Resource: "ProductPage", OutputListKey: "", OutputItemKey: "DisplayContent", Method: "PATCH", URI: "/v2/portalproducts/{PortalProductId}/productpages/{ProductPageId}"}, + "UpdateProductRestEndpointPage": {Verb: "Update", Resource: "ProductRestEndpointPage", OutputListKey: "", OutputItemKey: "DisplayContent", Method: "PATCH", URI: "/v2/portalproducts/{PortalProductId}/productrestendpointpages/{ProductRestEndpointPageId}"}, + "UpdateRoute": {Verb: "Update", Resource: "Route", OutputListKey: "AuthorizationScopes", OutputItemKey: "", Method: "PATCH", URI: "/v2/apis/{ApiId}/routes/{RouteId}"}, + "UpdateRouteResponse": {Verb: "Update", Resource: "RouteResponse", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/v2/apis/{ApiId}/routes/{RouteId}/routeresponses/{RouteResponseId}"}, + "UpdateStage": {Verb: "Update", Resource: "Stage", OutputListKey: "", OutputItemKey: "AccessLogSettings", Method: "PATCH", URI: "/v2/apis/{ApiId}/stages/{StageName}"}, + "UpdateVpcLink": {Verb: "Update", Resource: "VpcLink", OutputListKey: "SecurityGroupIds", OutputItemKey: "", Method: "PATCH", URI: "/v2/vpclinks/{VpcLinkId}"}, + }) + crud.Register("appconfig", map[string]crud.OpMeta{ + "CreateApplication": {Verb: "Create", Resource: "Application", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/applications"}, + "CreateConfigurationProfile": {Verb: "Create", Resource: "ConfigurationProfile", OutputListKey: "Validators", OutputItemKey: "", Method: "POST", URI: "/applications/{ApplicationId}/configurationprofiles"}, + "CreateDeploymentStrategy": {Verb: "Create", Resource: "DeploymentStrategy", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/deploymentstrategies"}, + "CreateEnvironment": {Verb: "Create", Resource: "Environment", OutputListKey: "Monitors", OutputItemKey: "", Method: "POST", URI: "/applications/{ApplicationId}/environments"}, + "CreateExtension": {Verb: "Create", Resource: "Extension", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/extensions"}, + "CreateExtensionAssociation": {Verb: "Create", Resource: "ExtensionAssociation", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/extensionassociations"}, + "CreateHostedConfigurationVersion": {Verb: "Create", Resource: "HostedConfigurationVersion", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/applications/{ApplicationId}/configurationprofiles/{ConfigurationProfileId}/hostedconfigurationversions"}, + "DeleteApplication": {Verb: "Delete", Resource: "Application", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/applications/{ApplicationId}"}, + "DeleteConfigurationProfile": {Verb: "Delete", Resource: "ConfigurationProfile", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/applications/{ApplicationId}/configurationprofiles/{ConfigurationProfileId}"}, + "DeleteDeploymentStrategy": {Verb: "Delete", Resource: "DeploymentStrategy", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/deployementstrategies/{DeploymentStrategyId}"}, + "DeleteEnvironment": {Verb: "Delete", Resource: "Environment", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/applications/{ApplicationId}/environments/{EnvironmentId}"}, + "DeleteExtension": {Verb: "Delete", Resource: "Extension", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/extensions/{ExtensionIdentifier}"}, + "DeleteExtensionAssociation": {Verb: "Delete", Resource: "ExtensionAssociation", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/extensionassociations/{ExtensionAssociationId}"}, + "DeleteHostedConfigurationVersion": {Verb: "Delete", Resource: "HostedConfigurationVersion", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/applications/{ApplicationId}/configurationprofiles/{ConfigurationProfileId}/hostedconfigurationversions/{VersionNumber}"}, + "GetAccountSettings": {Verb: "Get", Resource: "AccountSetting", OutputListKey: "", OutputItemKey: "DeletionProtection", Method: "GET", URI: "/settings"}, + "GetApplication": {Verb: "Get", Resource: "Application", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/applications/{ApplicationId}"}, + "GetConfiguration": {Verb: "Get", Resource: "Configuration", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/applications/{Application}/environments/{Environment}/configurations/{Configuration}"}, + "GetConfigurationProfile": {Verb: "Get", Resource: "ConfigurationProfile", OutputListKey: "Validators", OutputItemKey: "", Method: "GET", URI: "/applications/{ApplicationId}/configurationprofiles/{ConfigurationProfileId}"}, + "GetDeployment": {Verb: "Get", Resource: "Deployment", OutputListKey: "AppliedExtensions", OutputItemKey: "", Method: "GET", URI: "/applications/{ApplicationId}/environments/{EnvironmentId}/deployments/{DeploymentNumber}"}, + "GetDeploymentStrategy": {Verb: "Get", Resource: "DeploymentStrategy", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/deploymentstrategies/{DeploymentStrategyId}"}, + "GetEnvironment": {Verb: "Get", Resource: "Environment", OutputListKey: "Monitors", OutputItemKey: "", Method: "GET", URI: "/applications/{ApplicationId}/environments/{EnvironmentId}"}, + "GetExtension": {Verb: "Get", Resource: "Extension", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/extensions/{ExtensionIdentifier}"}, + "GetExtensionAssociation": {Verb: "Get", Resource: "ExtensionAssociation", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/extensionassociations/{ExtensionAssociationId}"}, + "GetHostedConfigurationVersion": {Verb: "Get", Resource: "HostedConfigurationVersion", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/applications/{ApplicationId}/configurationprofiles/{ConfigurationProfileId}/hostedconfigurationversions/{VersionNumber}"}, + "ListApplications": {Verb: "List", Resource: "Application", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/applications"}, + "ListConfigurationProfiles": {Verb: "List", Resource: "ConfigurationProfile", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/applications/{ApplicationId}/configurationprofiles"}, + "ListDeploymentStrategies": {Verb: "List", Resource: "DeploymentStrategy", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/deploymentstrategies"}, + "ListDeployments": {Verb: "List", Resource: "Deployment", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/applications/{ApplicationId}/environments/{EnvironmentId}/deployments"}, + "ListEnvironments": {Verb: "List", Resource: "Environment", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/applications/{ApplicationId}/environments"}, + "ListExtensionAssociations": {Verb: "List", Resource: "ExtensionAssociation", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/extensionassociations"}, + "ListExtensions": {Verb: "List", Resource: "Extension", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/extensions"}, + "ListHostedConfigurationVersions": {Verb: "List", Resource: "HostedConfigurationVersion", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/applications/{ApplicationId}/configurationprofiles/{ConfigurationProfileId}/hostedconfigurationversions"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/tags/{ResourceArn}"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/tags/{ResourceArn}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/tags/{ResourceArn}"}, + "UpdateAccountSettings": {Verb: "Update", Resource: "AccountSetting", OutputListKey: "", OutputItemKey: "DeletionProtection", Method: "PATCH", URI: "/settings"}, + "UpdateApplication": {Verb: "Update", Resource: "Application", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/applications/{ApplicationId}"}, + "UpdateConfigurationProfile": {Verb: "Update", Resource: "ConfigurationProfile", OutputListKey: "Validators", OutputItemKey: "", Method: "PATCH", URI: "/applications/{ApplicationId}/configurationprofiles/{ConfigurationProfileId}"}, + "UpdateDeploymentStrategy": {Verb: "Update", Resource: "DeploymentStrategy", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/deploymentstrategies/{DeploymentStrategyId}"}, + "UpdateEnvironment": {Verb: "Update", Resource: "Environment", OutputListKey: "Monitors", OutputItemKey: "", Method: "PATCH", URI: "/applications/{ApplicationId}/environments/{EnvironmentId}"}, + "UpdateExtension": {Verb: "Update", Resource: "Extension", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/extensions/{ExtensionIdentifier}"}, + "UpdateExtensionAssociation": {Verb: "Update", Resource: "ExtensionAssociation", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/extensionassociations/{ExtensionAssociationId}"}, + }) crud.Register("applicationautoscaling", map[string]crud.OpMeta{ "DeleteScalingPolicy": {Verb: "Delete", Resource: "ScalingPolicy", OutputListKey: "", OutputItemKey: ""}, "DeleteScheduledAction": {Verb: "Delete", Resource: "ScheduledAction", OutputListKey: "", OutputItemKey: ""}, @@ -56,6 +233,70 @@ func init() { "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: ""}, "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: ""}, }) + crud.Register("appsync", map[string]crud.OpMeta{ + "CreateApi": {Verb: "Create", Resource: "Api", OutputListKey: "", OutputItemKey: "api", Method: "POST", URI: "/v2/apis"}, + "CreateApiCache": {Verb: "Create", Resource: "ApiCache", OutputListKey: "", OutputItemKey: "apiCache", Method: "POST", URI: "/v1/apis/{apiId}/ApiCaches"}, + "CreateApiKey": {Verb: "Create", Resource: "ApiKey", OutputListKey: "", OutputItemKey: "apiKey", Method: "POST", URI: "/v1/apis/{apiId}/apikeys"}, + "CreateChannelNamespace": {Verb: "Create", Resource: "ChannelNamespace", OutputListKey: "", OutputItemKey: "channelNamespace", Method: "POST", URI: "/v2/apis/{apiId}/channelNamespaces"}, + "CreateDataSource": {Verb: "Create", Resource: "DataSource", OutputListKey: "", OutputItemKey: "dataSource", Method: "POST", URI: "/v1/apis/{apiId}/datasources"}, + "CreateDomainName": {Verb: "Create", Resource: "DomainName", OutputListKey: "", OutputItemKey: "domainNameConfig", Method: "POST", URI: "/v1/domainnames"}, + "CreateFunction": {Verb: "Create", Resource: "Function", OutputListKey: "", OutputItemKey: "functionConfiguration", Method: "POST", URI: "/v1/apis/{apiId}/functions"}, + "CreateGraphqlApi": {Verb: "Create", Resource: "GraphqlApi", OutputListKey: "", OutputItemKey: "graphqlApi", Method: "POST", URI: "/v1/apis"}, + "CreateResolver": {Verb: "Create", Resource: "Resolver", OutputListKey: "", OutputItemKey: "resolver", Method: "POST", URI: "/v1/apis/{apiId}/types/{typeName}/resolvers"}, + "CreateType": {Verb: "Create", Resource: "Type", OutputListKey: "", OutputItemKey: "type", Method: "POST", URI: "/v1/apis/{apiId}/types"}, + "DeleteApi": {Verb: "Delete", Resource: "Api", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/apis/{apiId}"}, + "DeleteApiCache": {Verb: "Delete", Resource: "ApiCache", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v1/apis/{apiId}/ApiCaches"}, + "DeleteApiKey": {Verb: "Delete", Resource: "ApiKey", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v1/apis/{apiId}/apikeys/{id}"}, + "DeleteChannelNamespace": {Verb: "Delete", Resource: "ChannelNamespace", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/apis/{apiId}/channelNamespaces/{name}"}, + "DeleteDataSource": {Verb: "Delete", Resource: "DataSource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v1/apis/{apiId}/datasources/{name}"}, + "DeleteDomainName": {Verb: "Delete", Resource: "DomainName", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v1/domainnames/{domainName}"}, + "DeleteFunction": {Verb: "Delete", Resource: "Function", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v1/apis/{apiId}/functions/{functionId}"}, + "DeleteGraphqlApi": {Verb: "Delete", Resource: "GraphqlApi", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v1/apis/{apiId}"}, + "DeleteResolver": {Verb: "Delete", Resource: "Resolver", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v1/apis/{apiId}/types/{typeName}/resolvers/{fieldName}"}, + "DeleteType": {Verb: "Delete", Resource: "Type", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v1/apis/{apiId}/types/{typeName}"}, + "GetApi": {Verb: "Get", Resource: "Api", OutputListKey: "", OutputItemKey: "api", Method: "GET", URI: "/v2/apis/{apiId}"}, + "GetApiAssociation": {Verb: "Get", Resource: "ApiAssociation", OutputListKey: "", OutputItemKey: "apiAssociation", Method: "GET", URI: "/v1/domainnames/{domainName}/apiassociation"}, + "GetApiCache": {Verb: "Get", Resource: "ApiCache", OutputListKey: "", OutputItemKey: "apiCache", Method: "GET", URI: "/v1/apis/{apiId}/ApiCaches"}, + "GetChannelNamespace": {Verb: "Get", Resource: "ChannelNamespace", OutputListKey: "", OutputItemKey: "channelNamespace", Method: "GET", URI: "/v2/apis/{apiId}/channelNamespaces/{name}"}, + "GetDataSource": {Verb: "Get", Resource: "DataSource", OutputListKey: "", OutputItemKey: "dataSource", Method: "GET", URI: "/v1/apis/{apiId}/datasources/{name}"}, + "GetDataSourceIntrospection": {Verb: "Get", Resource: "DataSourceIntrospection", OutputListKey: "", OutputItemKey: "introspectionResult", Method: "GET", URI: "/v1/datasources/introspections/{introspectionId}"}, + "GetDomainName": {Verb: "Get", Resource: "DomainName", OutputListKey: "", OutputItemKey: "domainNameConfig", Method: "GET", URI: "/v1/domainnames/{domainName}"}, + "GetFunction": {Verb: "Get", Resource: "Function", OutputListKey: "", OutputItemKey: "functionConfiguration", Method: "GET", URI: "/v1/apis/{apiId}/functions/{functionId}"}, + "GetGraphqlApi": {Verb: "Get", Resource: "GraphqlApi", OutputListKey: "", OutputItemKey: "graphqlApi", Method: "GET", URI: "/v1/apis/{apiId}"}, + "GetGraphqlApiEnvironmentVariables": {Verb: "Get", Resource: "GraphqlApiEnvironmentVariable", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v1/apis/{apiId}/environmentVariables"}, + "GetIntrospectionSchema": {Verb: "Get", Resource: "IntrospectionSchema", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v1/apis/{apiId}/schema"}, + "GetResolver": {Verb: "Get", Resource: "Resolver", OutputListKey: "", OutputItemKey: "resolver", Method: "GET", URI: "/v1/apis/{apiId}/types/{typeName}/resolvers/{fieldName}"}, + "GetSchemaCreationStatus": {Verb: "Get", Resource: "SchemaCreationStatu", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v1/apis/{apiId}/schemacreation"}, + "GetSourceApiAssociation": {Verb: "Get", Resource: "SourceApiAssociation", OutputListKey: "", OutputItemKey: "sourceApiAssociation", Method: "GET", URI: "/v1/mergedApis/{mergedApiIdentifier}/sourceApiAssociations/{associationId}"}, + "GetType": {Verb: "Get", Resource: "Type", OutputListKey: "", OutputItemKey: "type", Method: "GET", URI: "/v1/apis/{apiId}/types/{typeName}"}, + "ListApiKeys": {Verb: "List", Resource: "ApiKey", OutputListKey: "apiKeys", OutputItemKey: "", Method: "GET", URI: "/v1/apis/{apiId}/apikeys"}, + "ListApis": {Verb: "List", Resource: "Api", OutputListKey: "apis", OutputItemKey: "", Method: "GET", URI: "/v2/apis"}, + "ListChannelNamespaces": {Verb: "List", Resource: "ChannelNamespace", OutputListKey: "channelNamespaces", OutputItemKey: "", Method: "GET", URI: "/v2/apis/{apiId}/channelNamespaces"}, + "ListDataSources": {Verb: "List", Resource: "DataSource", OutputListKey: "dataSources", OutputItemKey: "", Method: "GET", URI: "/v1/apis/{apiId}/datasources"}, + "ListDomainNames": {Verb: "List", Resource: "DomainName", OutputListKey: "domainNameConfigs", OutputItemKey: "", Method: "GET", URI: "/v1/domainnames"}, + "ListFunctions": {Verb: "List", Resource: "Function", OutputListKey: "functions", OutputItemKey: "", Method: "GET", URI: "/v1/apis/{apiId}/functions"}, + "ListGraphqlApis": {Verb: "List", Resource: "GraphqlApi", OutputListKey: "graphqlApis", OutputItemKey: "", Method: "GET", URI: "/v1/apis"}, + "ListResolvers": {Verb: "List", Resource: "Resolver", OutputListKey: "resolvers", OutputItemKey: "", Method: "GET", URI: "/v1/apis/{apiId}/types/{typeName}/resolvers"}, + "ListResolversByFunction": {Verb: "List", Resource: "ResolversByFunction", OutputListKey: "resolvers", OutputItemKey: "", Method: "GET", URI: "/v1/apis/{apiId}/functions/{functionId}/resolvers"}, + "ListSourceApiAssociations": {Verb: "List", Resource: "SourceApiAssociation", OutputListKey: "sourceApiAssociationSummaries", OutputItemKey: "", Method: "GET", URI: "/v1/apis/{apiId}/sourceApiAssociations"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v1/tags/{resourceArn}"}, + "ListTypes": {Verb: "List", Resource: "Type", OutputListKey: "types", OutputItemKey: "", Method: "GET", URI: "/v1/apis/{apiId}/types"}, + "ListTypesByAssociation": {Verb: "List", Resource: "TypesByAssociation", OutputListKey: "types", OutputItemKey: "", Method: "GET", URI: "/v1/mergedApis/{mergedApiIdentifier}/sourceApiAssociations/{associationId}/types"}, + "PutGraphqlApiEnvironmentVariables": {Verb: "Update", Resource: "GraphqlApiEnvironmentVariable", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v1/apis/{apiId}/environmentVariables"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/tags/{resourceArn}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v1/tags/{resourceArn}"}, + "UpdateApi": {Verb: "Update", Resource: "Api", OutputListKey: "", OutputItemKey: "api", Method: "POST", URI: "/v2/apis/{apiId}"}, + "UpdateApiCache": {Verb: "Update", Resource: "ApiCache", OutputListKey: "", OutputItemKey: "apiCache", Method: "POST", URI: "/v1/apis/{apiId}/ApiCaches/update"}, + "UpdateApiKey": {Verb: "Update", Resource: "ApiKey", OutputListKey: "", OutputItemKey: "apiKey", Method: "POST", URI: "/v1/apis/{apiId}/apikeys/{id}"}, + "UpdateChannelNamespace": {Verb: "Update", Resource: "ChannelNamespace", OutputListKey: "", OutputItemKey: "channelNamespace", Method: "POST", URI: "/v2/apis/{apiId}/channelNamespaces/{name}"}, + "UpdateDataSource": {Verb: "Update", Resource: "DataSource", OutputListKey: "", OutputItemKey: "dataSource", Method: "POST", URI: "/v1/apis/{apiId}/datasources/{name}"}, + "UpdateDomainName": {Verb: "Update", Resource: "DomainName", OutputListKey: "", OutputItemKey: "domainNameConfig", Method: "POST", URI: "/v1/domainnames/{domainName}"}, + "UpdateFunction": {Verb: "Update", Resource: "Function", OutputListKey: "", OutputItemKey: "functionConfiguration", Method: "POST", URI: "/v1/apis/{apiId}/functions/{functionId}"}, + "UpdateGraphqlApi": {Verb: "Update", Resource: "GraphqlApi", OutputListKey: "", OutputItemKey: "graphqlApi", Method: "POST", URI: "/v1/apis/{apiId}"}, + "UpdateResolver": {Verb: "Update", Resource: "Resolver", OutputListKey: "", OutputItemKey: "resolver", Method: "POST", URI: "/v1/apis/{apiId}/types/{typeName}/resolvers/{fieldName}"}, + "UpdateSourceApiAssociation": {Verb: "Update", Resource: "SourceApiAssociation", OutputListKey: "", OutputItemKey: "sourceApiAssociation", Method: "POST", URI: "/v1/mergedApis/{mergedApiIdentifier}/sourceApiAssociations/{associationId}"}, + "UpdateType": {Verb: "Update", Resource: "Type", OutputListKey: "", OutputItemKey: "type", Method: "POST", URI: "/v1/apis/{apiId}/types/{typeName}"}, + }) crud.Register("athena", map[string]crud.OpMeta{ "BatchGetNamedQuery": {Verb: "List", Resource: "NamedQuery", OutputListKey: "NamedQueries", OutputItemKey: ""}, "BatchGetPreparedStatement": {Verb: "List", Resource: "PreparedStatement", OutputListKey: "PreparedStatements", OutputItemKey: ""}, @@ -119,12 +360,577 @@ func init() { "UpdatePreparedStatement": {Verb: "Update", Resource: "PreparedStatement", OutputListKey: "", OutputItemKey: ""}, "UpdateWorkGroup": {Verb: "Update", Resource: "WorkGroup", OutputListKey: "", OutputItemKey: ""}, }) + crud.Register("backup", map[string]crud.OpMeta{ + "CreateBackupPlan": {Verb: "Create", Resource: "BackupPlan", OutputListKey: "AdvancedBackupSettings", OutputItemKey: "", Method: "PUT", URI: "/backup/plans"}, + "CreateBackupSelection": {Verb: "Create", Resource: "BackupSelection", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/backup/plans/{BackupPlanId}/selections"}, + "CreateBackupVault": {Verb: "Create", Resource: "BackupVault", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/backup-vaults/{BackupVaultName}"}, + "CreateFramework": {Verb: "Create", Resource: "Framework", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/audit/frameworks"}, + "CreateLegalHold": {Verb: "Create", Resource: "LegalHold", OutputListKey: "", OutputItemKey: "RecoveryPointSelection", Method: "POST", URI: "/legal-holds"}, + "CreateLogicallyAirGappedBackupVault": {Verb: "Create", Resource: "LogicallyAirGappedBackupVault", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/logically-air-gapped-backup-vaults/{BackupVaultName}"}, + "CreateReportPlan": {Verb: "Create", Resource: "ReportPlan", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/audit/report-plans"}, + "CreateRestoreAccessBackupVault": {Verb: "Create", Resource: "RestoreAccessBackupVault", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/restore-access-backup-vaults"}, + "CreateRestoreTestingPlan": {Verb: "Create", Resource: "RestoreTestingPlan", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/restore-testing/plans"}, + "CreateRestoreTestingSelection": {Verb: "Create", Resource: "RestoreTestingSelection", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/restore-testing/plans/{RestoreTestingPlanName}/selections"}, + "CreateTieringConfiguration": {Verb: "Create", Resource: "TieringConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/tiering-configurations"}, + "DeleteBackupPlan": {Verb: "Delete", Resource: "BackupPlan", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/backup/plans/{BackupPlanId}"}, + "DeleteBackupSelection": {Verb: "Delete", Resource: "BackupSelection", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/backup/plans/{BackupPlanId}/selections/{SelectionId}"}, + "DeleteBackupVault": {Verb: "Delete", Resource: "BackupVault", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/backup-vaults/{BackupVaultName}"}, + "DeleteBackupVaultAccessPolicy": {Verb: "Delete", Resource: "BackupVaultAccessPolicy", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/backup-vaults/{BackupVaultName}/access-policy"}, + "DeleteBackupVaultLockConfiguration": {Verb: "Delete", Resource: "BackupVaultLockConfiguration", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/backup-vaults/{BackupVaultName}/vault-lock"}, + "DeleteBackupVaultNotifications": {Verb: "Delete", Resource: "BackupVaultNotification", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/backup-vaults/{BackupVaultName}/notification-configuration"}, + "DeleteFramework": {Verb: "Delete", Resource: "Framework", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/audit/frameworks/{FrameworkName}"}, + "DeleteRecoveryPoint": {Verb: "Delete", Resource: "RecoveryPoint", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/backup-vaults/{BackupVaultName}/recovery-points/{RecoveryPointArn}"}, + "DeleteReportPlan": {Verb: "Delete", Resource: "ReportPlan", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/audit/report-plans/{ReportPlanName}"}, + "DeleteRestoreTestingPlan": {Verb: "Delete", Resource: "RestoreTestingPlan", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/restore-testing/plans/{RestoreTestingPlanName}"}, + "DeleteRestoreTestingSelection": {Verb: "Delete", Resource: "RestoreTestingSelection", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/restore-testing/plans/{RestoreTestingPlanName}/selections/{RestoreTestingSelectionName}"}, + "DeleteTieringConfiguration": {Verb: "Delete", Resource: "TieringConfiguration", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/tiering-configurations/{TieringConfigurationName}"}, + "DescribeBackupJob": {Verb: "Get", Resource: "BackupJob", OutputListKey: "", OutputItemKey: "CreatedBy", Method: "GET", URI: "/backup-jobs/{BackupJobId}"}, + "DescribeBackupVault": {Verb: "Get", Resource: "BackupVault", OutputListKey: "", OutputItemKey: "LatestMpaApprovalTeamUpdate", Method: "GET", URI: "/backup-vaults/{BackupVaultName}"}, + "DescribeCopyJob": {Verb: "Get", Resource: "CopyJob", OutputListKey: "", OutputItemKey: "CopyJob", Method: "GET", URI: "/copy-jobs/{CopyJobId}"}, + "DescribeFramework": {Verb: "Get", Resource: "Framework", OutputListKey: "FrameworkControls", OutputItemKey: "", Method: "GET", URI: "/audit/frameworks/{FrameworkName}"}, + "DescribeGlobalSettings": {Verb: "Get", Resource: "GlobalSetting", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/global-settings"}, + "DescribeProtectedResource": {Verb: "Get", Resource: "ProtectedResource", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/resources/{ResourceArn}"}, + "DescribeRecoveryPoint": {Verb: "Get", Resource: "RecoveryPoint", OutputListKey: "ScanResults", OutputItemKey: "CalculatedLifecycle", Method: "GET", URI: "/backup-vaults/{BackupVaultName}/recovery-points/{RecoveryPointArn}"}, + "DescribeRegionSettings": {Verb: "Get", Resource: "RegionSetting", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/account-settings"}, + "DescribeReportJob": {Verb: "Get", Resource: "ReportJob", OutputListKey: "", OutputItemKey: "ReportJob", Method: "GET", URI: "/audit/report-jobs/{ReportJobId}"}, + "DescribeReportPlan": {Verb: "Get", Resource: "ReportPlan", OutputListKey: "", OutputItemKey: "ReportPlan", Method: "GET", URI: "/audit/report-plans/{ReportPlanName}"}, + "DescribeRestoreJob": {Verb: "Get", Resource: "RestoreJob", OutputListKey: "", OutputItemKey: "CreatedBy", Method: "GET", URI: "/restore-jobs/{RestoreJobId}"}, + "DescribeScanJob": {Verb: "Get", Resource: "ScanJob", OutputListKey: "", OutputItemKey: "CreatedBy", Method: "GET", URI: "/scan/jobs/{ScanJobId}"}, + "GetBackupPlan": {Verb: "Get", Resource: "BackupPlan", OutputListKey: "AdvancedBackupSettings", OutputItemKey: "BackupPlan", Method: "GET", URI: "/backup/plans/{BackupPlanId}"}, + "GetBackupPlanFromJSON": {Verb: "Get", Resource: "BackupPlanFromJSON", OutputListKey: "", OutputItemKey: "BackupPlan", Method: "POST", URI: "/backup/template/json/toPlan"}, + "GetBackupPlanFromTemplate": {Verb: "Get", Resource: "BackupPlanFromTemplate", OutputListKey: "", OutputItemKey: "BackupPlanDocument", Method: "GET", URI: "/backup/template/plans/{BackupPlanTemplateId}/toPlan"}, + "GetBackupSelection": {Verb: "Get", Resource: "BackupSelection", OutputListKey: "", OutputItemKey: "BackupSelection", Method: "GET", URI: "/backup/plans/{BackupPlanId}/selections/{SelectionId}"}, + "GetBackupVaultAccessPolicy": {Verb: "Get", Resource: "BackupVaultAccessPolicy", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/backup-vaults/{BackupVaultName}/access-policy"}, + "GetBackupVaultNotifications": {Verb: "Get", Resource: "BackupVaultNotification", OutputListKey: "BackupVaultEvents", OutputItemKey: "", Method: "GET", URI: "/backup-vaults/{BackupVaultName}/notification-configuration"}, + "GetLegalHold": {Verb: "Get", Resource: "LegalHold", OutputListKey: "", OutputItemKey: "RecoveryPointSelection", Method: "GET", URI: "/legal-holds/{LegalHoldId}"}, + "GetRecoveryPointIndexDetails": {Verb: "Get", Resource: "RecoveryPointIndexDetail", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/backup-vaults/{BackupVaultName}/recovery-points/{RecoveryPointArn}/index"}, + "GetRecoveryPointRestoreMetadata": {Verb: "Get", Resource: "RecoveryPointRestoreMetadata", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/backup-vaults/{BackupVaultName}/recovery-points/{RecoveryPointArn}/restore-metadata"}, + "GetRestoreJobMetadata": {Verb: "Get", Resource: "RestoreJobMetadata", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/restore-jobs/{RestoreJobId}/metadata"}, + "GetRestoreTestingInferredMetadata": {Verb: "Get", Resource: "RestoreTestingInferredMetadata", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/restore-testing/inferred-metadata"}, + "GetRestoreTestingPlan": {Verb: "Get", Resource: "RestoreTestingPlan", OutputListKey: "", OutputItemKey: "RestoreTestingPlan", Method: "GET", URI: "/restore-testing/plans/{RestoreTestingPlanName}"}, + "GetRestoreTestingSelection": {Verb: "Get", Resource: "RestoreTestingSelection", OutputListKey: "", OutputItemKey: "RestoreTestingSelection", Method: "GET", URI: "/restore-testing/plans/{RestoreTestingPlanName}/selections/{RestoreTestingSelectionName}"}, + "GetSupportedResourceTypes": {Verb: "Get", Resource: "SupportedResourceType", OutputListKey: "ResourceTypes", OutputItemKey: "", Method: "GET", URI: "/supported-resource-types"}, + "GetTieringConfiguration": {Verb: "Get", Resource: "TieringConfiguration", OutputListKey: "", OutputItemKey: "TieringConfiguration", Method: "GET", URI: "/tiering-configurations/{TieringConfigurationName}"}, + "ListBackupJobSummaries": {Verb: "List", Resource: "BackupJobSummary", OutputListKey: "BackupJobSummaries", OutputItemKey: "", Method: "GET", URI: "/audit/backup-job-summaries"}, + "ListBackupJobs": {Verb: "List", Resource: "BackupJob", OutputListKey: "BackupJobs", OutputItemKey: "", Method: "GET", URI: "/backup-jobs"}, + "ListBackupPlanTemplates": {Verb: "List", Resource: "BackupPlanTemplate", OutputListKey: "BackupPlanTemplatesList", OutputItemKey: "", Method: "GET", URI: "/backup/template/plans"}, + "ListBackupPlanVersions": {Verb: "List", Resource: "BackupPlanVersion", OutputListKey: "BackupPlanVersionsList", OutputItemKey: "", Method: "GET", URI: "/backup/plans/{BackupPlanId}/versions"}, + "ListBackupPlans": {Verb: "List", Resource: "BackupPlan", OutputListKey: "BackupPlansList", OutputItemKey: "", Method: "GET", URI: "/backup/plans"}, + "ListBackupSelections": {Verb: "List", Resource: "BackupSelection", OutputListKey: "BackupSelectionsList", OutputItemKey: "", Method: "GET", URI: "/backup/plans/{BackupPlanId}/selections"}, + "ListBackupVaults": {Verb: "List", Resource: "BackupVault", OutputListKey: "BackupVaultList", OutputItemKey: "", Method: "GET", URI: "/backup-vaults"}, + "ListCopyJobSummaries": {Verb: "List", Resource: "CopyJobSummary", OutputListKey: "CopyJobSummaries", OutputItemKey: "", Method: "GET", URI: "/audit/copy-job-summaries"}, + "ListCopyJobs": {Verb: "List", Resource: "CopyJob", OutputListKey: "CopyJobs", OutputItemKey: "", Method: "GET", URI: "/copy-jobs"}, + "ListFrameworks": {Verb: "List", Resource: "Framework", OutputListKey: "Frameworks", OutputItemKey: "", Method: "GET", URI: "/audit/frameworks"}, + "ListIndexedRecoveryPoints": {Verb: "List", Resource: "IndexedRecoveryPoint", OutputListKey: "IndexedRecoveryPoints", OutputItemKey: "", Method: "GET", URI: "/indexes/recovery-point"}, + "ListLegalHolds": {Verb: "List", Resource: "LegalHold", OutputListKey: "LegalHolds", OutputItemKey: "", Method: "GET", URI: "/legal-holds"}, + "ListProtectedResources": {Verb: "List", Resource: "ProtectedResource", OutputListKey: "Results", OutputItemKey: "", Method: "GET", URI: "/resources"}, + "ListProtectedResourcesByBackupVault": {Verb: "List", Resource: "ProtectedResourcesByBackupVault", OutputListKey: "Results", OutputItemKey: "", Method: "GET", URI: "/backup-vaults/{BackupVaultName}/resources"}, + "ListRecoveryPointsByBackupVault": {Verb: "List", Resource: "RecoveryPointsByBackupVault", OutputListKey: "RecoveryPoints", OutputItemKey: "", Method: "GET", URI: "/backup-vaults/{BackupVaultName}/recovery-points"}, + "ListRecoveryPointsByLegalHold": {Verb: "List", Resource: "RecoveryPointsByLegalHold", OutputListKey: "RecoveryPoints", OutputItemKey: "", Method: "GET", URI: "/legal-holds/{LegalHoldId}/recovery-points"}, + "ListRecoveryPointsByResource": {Verb: "List", Resource: "RecoveryPointsByResource", OutputListKey: "RecoveryPoints", OutputItemKey: "", Method: "GET", URI: "/resources/{ResourceArn}/recovery-points"}, + "ListReportJobs": {Verb: "List", Resource: "ReportJob", OutputListKey: "ReportJobs", OutputItemKey: "", Method: "GET", URI: "/audit/report-jobs"}, + "ListReportPlans": {Verb: "List", Resource: "ReportPlan", OutputListKey: "ReportPlans", OutputItemKey: "", Method: "GET", URI: "/audit/report-plans"}, + "ListRestoreAccessBackupVaults": {Verb: "List", Resource: "RestoreAccessBackupVault", OutputListKey: "RestoreAccessBackupVaults", OutputItemKey: "", Method: "GET", URI: "/logically-air-gapped-backup-vaults/{BackupVaultName}/restore-access-backup-vaults"}, + "ListRestoreJobSummaries": {Verb: "List", Resource: "RestoreJobSummary", OutputListKey: "RestoreJobSummaries", OutputItemKey: "", Method: "GET", URI: "/audit/restore-job-summaries"}, + "ListRestoreJobs": {Verb: "List", Resource: "RestoreJob", OutputListKey: "RestoreJobs", OutputItemKey: "", Method: "GET", URI: "/restore-jobs"}, + "ListRestoreJobsByProtectedResource": {Verb: "List", Resource: "RestoreJobsByProtectedResource", OutputListKey: "RestoreJobs", OutputItemKey: "", Method: "GET", URI: "/resources/{ResourceArn}/restore-jobs"}, + "ListRestoreTestingPlans": {Verb: "List", Resource: "RestoreTestingPlan", OutputListKey: "RestoreTestingPlans", OutputItemKey: "", Method: "GET", URI: "/restore-testing/plans"}, + "ListRestoreTestingSelections": {Verb: "List", Resource: "RestoreTestingSelection", OutputListKey: "RestoreTestingSelections", OutputItemKey: "", Method: "GET", URI: "/restore-testing/plans/{RestoreTestingPlanName}/selections"}, + "ListScanJobSummaries": {Verb: "List", Resource: "ScanJobSummary", OutputListKey: "ScanJobSummaries", OutputItemKey: "", Method: "GET", URI: "/audit/scan-job-summaries"}, + "ListScanJobs": {Verb: "List", Resource: "ScanJob", OutputListKey: "ScanJobs", OutputItemKey: "", Method: "GET", URI: "/scan/jobs"}, + "ListTags": {Verb: "List", Resource: "Tag", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/tags/{ResourceArn}"}, + "ListTieringConfigurations": {Verb: "List", Resource: "TieringConfiguration", OutputListKey: "TieringConfigurations", OutputItemKey: "", Method: "GET", URI: "/tiering-configurations"}, + "PutBackupVaultAccessPolicy": {Verb: "Update", Resource: "BackupVaultAccessPolicy", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/backup-vaults/{BackupVaultName}/access-policy"}, + "PutBackupVaultLockConfiguration": {Verb: "Update", Resource: "BackupVaultLockConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/backup-vaults/{BackupVaultName}/vault-lock"}, + "PutBackupVaultNotifications": {Verb: "Update", Resource: "BackupVaultNotification", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/backup-vaults/{BackupVaultName}/notification-configuration"}, + "PutRestoreValidationResult": {Verb: "Update", Resource: "RestoreValidationResult", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/restore-jobs/{RestoreJobId}/validations"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/tags/{ResourceArn}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/untag/{ResourceArn}"}, + "UpdateBackupPlan": {Verb: "Update", Resource: "BackupPlan", OutputListKey: "AdvancedBackupSettings", OutputItemKey: "", Method: "POST", URI: "/backup/plans/{BackupPlanId}"}, + "UpdateFramework": {Verb: "Update", Resource: "Framework", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/audit/frameworks/{FrameworkName}"}, + "UpdateGlobalSettings": {Verb: "Update", Resource: "GlobalSetting", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/global-settings"}, + "UpdateRecoveryPointIndexSettings": {Verb: "Update", Resource: "RecoveryPointIndexSetting", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/backup-vaults/{BackupVaultName}/recovery-points/{RecoveryPointArn}/index"}, + "UpdateRecoveryPointLifecycle": {Verb: "Update", Resource: "RecoveryPointLifecycle", OutputListKey: "", OutputItemKey: "CalculatedLifecycle", Method: "POST", URI: "/backup-vaults/{BackupVaultName}/recovery-points/{RecoveryPointArn}"}, + "UpdateRegionSettings": {Verb: "Update", Resource: "RegionSetting", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/account-settings"}, + "UpdateReportPlan": {Verb: "Update", Resource: "ReportPlan", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/audit/report-plans/{ReportPlanName}"}, + "UpdateRestoreTestingPlan": {Verb: "Update", Resource: "RestoreTestingPlan", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/restore-testing/plans/{RestoreTestingPlanName}"}, + "UpdateRestoreTestingSelection": {Verb: "Update", Resource: "RestoreTestingSelection", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/restore-testing/plans/{RestoreTestingPlanName}/selections/{RestoreTestingSelectionName}"}, + "UpdateTieringConfiguration": {Verb: "Update", Resource: "TieringConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/tiering-configurations/{TieringConfigurationName}"}, + }) + crud.Register("batch", map[string]crud.OpMeta{ + "CreateComputeEnvironment": {Verb: "Create", Resource: "ComputeEnvironment", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/createcomputeenvironment"}, + "CreateConsumableResource": {Verb: "Create", Resource: "ConsumableResource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/createconsumableresource"}, + "CreateJobQueue": {Verb: "Create", Resource: "JobQueue", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/createjobqueue"}, + "CreateQuotaShare": {Verb: "Create", Resource: "QuotaShare", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/createquotashare"}, + "CreateSchedulingPolicy": {Verb: "Create", Resource: "SchedulingPolicy", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/createschedulingpolicy"}, + "CreateServiceEnvironment": {Verb: "Create", Resource: "ServiceEnvironment", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/createserviceenvironment"}, + "DeleteComputeEnvironment": {Verb: "Delete", Resource: "ComputeEnvironment", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/deletecomputeenvironment"}, + "DeleteConsumableResource": {Verb: "Delete", Resource: "ConsumableResource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/deleteconsumableresource"}, + "DeleteJobQueue": {Verb: "Delete", Resource: "JobQueue", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/deletejobqueue"}, + "DeleteQuotaShare": {Verb: "Delete", Resource: "QuotaShare", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/deletequotashare"}, + "DeleteSchedulingPolicy": {Verb: "Delete", Resource: "SchedulingPolicy", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/deleteschedulingpolicy"}, + "DeleteServiceEnvironment": {Verb: "Delete", Resource: "ServiceEnvironment", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/deleteserviceenvironment"}, + "DeregisterJobDefinition": {Verb: "Delete", Resource: "JobDefinition", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/deregisterjobdefinition"}, + "DescribeComputeEnvironments": {Verb: "Get", Resource: "ComputeEnvironment", OutputListKey: "computeEnvironments", OutputItemKey: "", Method: "POST", URI: "/v1/describecomputeenvironments"}, + "DescribeConsumableResource": {Verb: "Get", Resource: "ConsumableResource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/describeconsumableresource"}, + "DescribeJobDefinitions": {Verb: "Get", Resource: "JobDefinition", OutputListKey: "jobDefinitions", OutputItemKey: "", Method: "POST", URI: "/v1/describejobdefinitions"}, + "DescribeJobQueues": {Verb: "Get", Resource: "JobQueue", OutputListKey: "jobQueues", OutputItemKey: "", Method: "POST", URI: "/v1/describejobqueues"}, + "DescribeJobs": {Verb: "Get", Resource: "Job", OutputListKey: "jobs", OutputItemKey: "", Method: "POST", URI: "/v1/describejobs"}, + "DescribeQuotaShare": {Verb: "Get", Resource: "QuotaShare", OutputListKey: "capacityLimits", OutputItemKey: "preemptionConfiguration", Method: "POST", URI: "/v1/describequotashare"}, + "DescribeSchedulingPolicies": {Verb: "Get", Resource: "SchedulingPolicy", OutputListKey: "schedulingPolicies", OutputItemKey: "", Method: "POST", URI: "/v1/describeschedulingpolicies"}, + "DescribeServiceEnvironments": {Verb: "Get", Resource: "ServiceEnvironment", OutputListKey: "serviceEnvironments", OutputItemKey: "", Method: "POST", URI: "/v1/describeserviceenvironments"}, + "DescribeServiceJob": {Verb: "Get", Resource: "ServiceJob", OutputListKey: "attempts", OutputItemKey: "latestAttempt", Method: "POST", URI: "/v1/describeservicejob"}, + "GetJobQueueSnapshot": {Verb: "Get", Resource: "JobQueueSnapshot", OutputListKey: "", OutputItemKey: "frontOfQueue", Method: "POST", URI: "/v1/getjobqueuesnapshot"}, + "ListConsumableResources": {Verb: "List", Resource: "ConsumableResource", OutputListKey: "consumableResources", OutputItemKey: "", Method: "POST", URI: "/v1/listconsumableresources"}, + "ListJobs": {Verb: "List", Resource: "Job", OutputListKey: "jobSummaryList", OutputItemKey: "", Method: "POST", URI: "/v1/listjobs"}, + "ListJobsByConsumableResource": {Verb: "List", Resource: "JobsByConsumableResource", OutputListKey: "jobs", OutputItemKey: "", Method: "POST", URI: "/v1/listjobsbyconsumableresource"}, + "ListQuotaShares": {Verb: "List", Resource: "QuotaShare", OutputListKey: "quotaShares", OutputItemKey: "", Method: "POST", URI: "/v1/listquotashares"}, + "ListSchedulingPolicies": {Verb: "List", Resource: "SchedulingPolicy", OutputListKey: "schedulingPolicies", OutputItemKey: "", Method: "POST", URI: "/v1/listschedulingpolicies"}, + "ListServiceJobs": {Verb: "List", Resource: "ServiceJob", OutputListKey: "jobSummaryList", OutputItemKey: "", Method: "POST", URI: "/v1/listservicejobs"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v1/tags/{resourceArn}"}, + "RegisterJobDefinition": {Verb: "Create", Resource: "JobDefinition", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/registerjobdefinition"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/tags/{resourceArn}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v1/tags/{resourceArn}"}, + "UpdateComputeEnvironment": {Verb: "Update", Resource: "ComputeEnvironment", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/updatecomputeenvironment"}, + "UpdateConsumableResource": {Verb: "Update", Resource: "ConsumableResource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/updateconsumableresource"}, + "UpdateJobQueue": {Verb: "Update", Resource: "JobQueue", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/updatejobqueue"}, + "UpdateQuotaShare": {Verb: "Update", Resource: "QuotaShare", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/updatequotashare"}, + "UpdateSchedulingPolicy": {Verb: "Update", Resource: "SchedulingPolicy", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/updateschedulingpolicy"}, + "UpdateServiceEnvironment": {Verb: "Update", Resource: "ServiceEnvironment", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/updateserviceenvironment"}, + "UpdateServiceJob": {Verb: "Update", Resource: "ServiceJob", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/updateservicejob"}, + }) + crud.Register("bedrock", map[string]crud.OpMeta{ + "CreateAutomatedReasoningPolicy": {Verb: "Create", Resource: "AutomatedReasoningPolicy", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/automated-reasoning-policies"}, + "CreateAutomatedReasoningPolicyTestCase": {Verb: "Create", Resource: "AutomatedReasoningPolicyTestCase", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/automated-reasoning-policies/{policyArn}/test-cases"}, + "CreateAutomatedReasoningPolicyVersion": {Verb: "Create", Resource: "AutomatedReasoningPolicyVersion", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/automated-reasoning-policies/{policyArn}/versions"}, + "CreateCustomModel": {Verb: "Create", Resource: "CustomModel", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/custom-models/create-custom-model"}, + "CreateCustomModelDeployment": {Verb: "Create", Resource: "CustomModelDeployment", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/model-customization/custom-model-deployments"}, + "CreateEvaluationJob": {Verb: "Create", Resource: "EvaluationJob", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/evaluation-jobs"}, + "CreateFoundationModelAgreement": {Verb: "Create", Resource: "FoundationModelAgreement", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/create-foundation-model-agreement"}, + "CreateGuardrail": {Verb: "Create", Resource: "Guardrail", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/guardrails"}, + "CreateGuardrailVersion": {Verb: "Create", Resource: "GuardrailVersion", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/guardrails/{guardrailIdentifier}"}, + "CreateInferenceProfile": {Verb: "Create", Resource: "InferenceProfile", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/inference-profiles"}, + "CreateMarketplaceModelEndpoint": {Verb: "Create", Resource: "MarketplaceModelEndpoint", OutputListKey: "", OutputItemKey: "marketplaceModelEndpoint", Method: "POST", URI: "/marketplace-model/endpoints"}, + "CreateModelCopyJob": {Verb: "Create", Resource: "ModelCopyJob", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/model-copy-jobs"}, + "CreateModelCustomizationJob": {Verb: "Create", Resource: "ModelCustomizationJob", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/model-customization-jobs"}, + "CreateModelImportJob": {Verb: "Create", Resource: "ModelImportJob", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/model-import-jobs"}, + "CreateModelInvocationJob": {Verb: "Create", Resource: "ModelInvocationJob", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/model-invocation-job"}, + "CreatePromptRouter": {Verb: "Create", Resource: "PromptRouter", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/prompt-routers"}, + "CreateProvisionedModelThroughput": {Verb: "Create", Resource: "ProvisionedModelThroughput", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/provisioned-model-throughput"}, + "DeleteAutomatedReasoningPolicy": {Verb: "Delete", Resource: "AutomatedReasoningPolicy", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/automated-reasoning-policies/{policyArn}"}, + "DeleteAutomatedReasoningPolicyBuildWorkflow": {Verb: "Delete", Resource: "AutomatedReasoningPolicyBuildWorkflow", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/automated-reasoning-policies/{policyArn}/build-workflows/{buildWorkflowId}"}, + "DeleteAutomatedReasoningPolicyTestCase": {Verb: "Delete", Resource: "AutomatedReasoningPolicyTestCase", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/automated-reasoning-policies/{policyArn}/test-cases/{testCaseId}"}, + "DeleteCustomModel": {Verb: "Delete", Resource: "CustomModel", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/custom-models/{modelIdentifier}"}, + "DeleteCustomModelDeployment": {Verb: "Delete", Resource: "CustomModelDeployment", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/model-customization/custom-model-deployments/{customModelDeploymentIdentifier}"}, + "DeleteEnforcedGuardrailConfiguration": {Verb: "Delete", Resource: "EnforcedGuardrailConfiguration", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/enforcedGuardrailsConfiguration/{configId}"}, + "DeleteFoundationModelAgreement": {Verb: "Delete", Resource: "FoundationModelAgreement", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/delete-foundation-model-agreement"}, + "DeleteGuardrail": {Verb: "Delete", Resource: "Guardrail", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/guardrails/{guardrailIdentifier}"}, + "DeleteImportedModel": {Verb: "Delete", Resource: "ImportedModel", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/imported-models/{modelIdentifier}"}, + "DeleteInferenceProfile": {Verb: "Delete", Resource: "InferenceProfile", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/inference-profiles/{inferenceProfileIdentifier}"}, + "DeleteMarketplaceModelEndpoint": {Verb: "Delete", Resource: "MarketplaceModelEndpoint", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/marketplace-model/endpoints/{endpointArn}"}, + "DeleteModelInvocationLoggingConfiguration": {Verb: "Delete", Resource: "ModelInvocationLoggingConfiguration", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/logging/modelinvocations"}, + "DeletePromptRouter": {Verb: "Delete", Resource: "PromptRouter", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/prompt-routers/{promptRouterArn}"}, + "DeleteProvisionedModelThroughput": {Verb: "Delete", Resource: "ProvisionedModelThroughput", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/provisioned-model-throughput/{provisionedModelId}"}, + "DeleteResourcePolicy": {Verb: "Delete", Resource: "ResourcePolicy", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/resource-policy/{resourceArn}"}, + "DeregisterMarketplaceModelEndpoint": {Verb: "Delete", Resource: "MarketplaceModelEndpoint", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/marketplace-model/endpoints/{endpointArn}/registration"}, + "GetAutomatedReasoningPolicy": {Verb: "Get", Resource: "AutomatedReasoningPolicy", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/automated-reasoning-policies/{policyArn}"}, + "GetAutomatedReasoningPolicyAnnotations": {Verb: "Get", Resource: "AutomatedReasoningPolicyAnnotation", OutputListKey: "annotations", OutputItemKey: "", Method: "GET", URI: "/automated-reasoning-policies/{policyArn}/build-workflows/{buildWorkflowId}/annotations"}, + "GetAutomatedReasoningPolicyBuildWorkflow": {Verb: "Get", Resource: "AutomatedReasoningPolicyBuildWorkflow", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/automated-reasoning-policies/{policyArn}/build-workflows/{buildWorkflowId}"}, + "GetAutomatedReasoningPolicyBuildWorkflowResultAssets": {Verb: "Get", Resource: "AutomatedReasoningPolicyBuildWorkflowResultAsset", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/automated-reasoning-policies/{policyArn}/build-workflows/{buildWorkflowId}/result-assets"}, + "GetAutomatedReasoningPolicyNextScenario": {Verb: "Get", Resource: "AutomatedReasoningPolicyNextScenario", OutputListKey: "", OutputItemKey: "scenario", Method: "GET", URI: "/automated-reasoning-policies/{policyArn}/build-workflows/{buildWorkflowId}/scenarios"}, + "GetAutomatedReasoningPolicyTestCase": {Verb: "Get", Resource: "AutomatedReasoningPolicyTestCase", OutputListKey: "", OutputItemKey: "testCase", Method: "GET", URI: "/automated-reasoning-policies/{policyArn}/test-cases/{testCaseId}"}, + "GetAutomatedReasoningPolicyTestResult": {Verb: "Get", Resource: "AutomatedReasoningPolicyTestResult", OutputListKey: "", OutputItemKey: "testResult", Method: "GET", URI: "/automated-reasoning-policies/{policyArn}/build-workflows/{buildWorkflowId}/test-cases/{testCaseId}/test-results"}, + "GetCustomModel": {Verb: "Get", Resource: "CustomModel", OutputListKey: "validationMetrics", OutputItemKey: "outputDataConfig", Method: "GET", URI: "/custom-models/{modelIdentifier}"}, + "GetCustomModelDeployment": {Verb: "Get", Resource: "CustomModelDeployment", OutputListKey: "", OutputItemKey: "updateDetails", Method: "GET", URI: "/model-customization/custom-model-deployments/{customModelDeploymentIdentifier}"}, + "GetEvaluationJob": {Verb: "Get", Resource: "EvaluationJob", OutputListKey: "failureMessages", OutputItemKey: "outputDataConfig", Method: "GET", URI: "/evaluation-jobs/{jobIdentifier}"}, + "GetFoundationModel": {Verb: "Get", Resource: "FoundationModel", OutputListKey: "", OutputItemKey: "modelDetails", Method: "GET", URI: "/foundation-models/{modelIdentifier}"}, + "GetFoundationModelAvailability": {Verb: "Get", Resource: "FoundationModelAvailability", OutputListKey: "", OutputItemKey: "agreementAvailability", Method: "GET", URI: "/foundation-model-availability/{modelId}"}, + "GetGuardrail": {Verb: "Get", Resource: "Guardrail", OutputListKey: "failureRecommendations", OutputItemKey: "automatedReasoningPolicy", Method: "GET", URI: "/guardrails/{guardrailIdentifier}"}, + "GetImportedModel": {Verb: "Get", Resource: "ImportedModel", OutputListKey: "", OutputItemKey: "customModelUnits", Method: "GET", URI: "/imported-models/{modelIdentifier}"}, + "GetInferenceProfile": {Verb: "Get", Resource: "InferenceProfile", OutputListKey: "models", OutputItemKey: "", Method: "GET", URI: "/inference-profiles/{inferenceProfileIdentifier}"}, + "GetMarketplaceModelEndpoint": {Verb: "Get", Resource: "MarketplaceModelEndpoint", OutputListKey: "", OutputItemKey: "marketplaceModelEndpoint", Method: "GET", URI: "/marketplace-model/endpoints/{endpointArn}"}, + "GetModelCopyJob": {Verb: "Get", Resource: "ModelCopyJob", OutputListKey: "targetModelTags", OutputItemKey: "", Method: "GET", URI: "/model-copy-jobs/{jobArn}"}, + "GetModelCustomizationJob": {Verb: "Get", Resource: "ModelCustomizationJob", OutputListKey: "validationMetrics", OutputItemKey: "outputDataConfig", Method: "GET", URI: "/model-customization-jobs/{jobIdentifier}"}, + "GetModelImportJob": {Verb: "Get", Resource: "ModelImportJob", OutputListKey: "", OutputItemKey: "vpcConfig", Method: "GET", URI: "/model-import-jobs/{jobIdentifier}"}, + "GetModelInvocationJob": {Verb: "Get", Resource: "ModelInvocationJob", OutputListKey: "", OutputItemKey: "vpcConfig", Method: "GET", URI: "/model-invocation-job/{jobIdentifier}"}, + "GetModelInvocationLoggingConfiguration": {Verb: "Get", Resource: "ModelInvocationLoggingConfiguration", OutputListKey: "", OutputItemKey: "loggingConfig", Method: "GET", URI: "/logging/modelinvocations"}, + "GetPromptRouter": {Verb: "Get", Resource: "PromptRouter", OutputListKey: "models", OutputItemKey: "fallbackModel", Method: "GET", URI: "/prompt-routers/{promptRouterArn}"}, + "GetProvisionedModelThroughput": {Verb: "Get", Resource: "ProvisionedModelThroughput", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/provisioned-model-throughput/{provisionedModelId}"}, + "GetResourcePolicy": {Verb: "Get", Resource: "ResourcePolicy", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/resource-policy/{resourceArn}"}, + "GetUseCaseForModelAccess": {Verb: "Get", Resource: "UseCaseForModelAccess", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/use-case-for-model-access"}, + "ListAutomatedReasoningPolicies": {Verb: "List", Resource: "AutomatedReasoningPolicy", OutputListKey: "automatedReasoningPolicySummaries", OutputItemKey: "", Method: "GET", URI: "/automated-reasoning-policies"}, + "ListAutomatedReasoningPolicyBuildWorkflows": {Verb: "List", Resource: "AutomatedReasoningPolicyBuildWorkflow", OutputListKey: "automatedReasoningPolicyBuildWorkflowSummaries", OutputItemKey: "", Method: "GET", URI: "/automated-reasoning-policies/{policyArn}/build-workflows"}, + "ListAutomatedReasoningPolicyTestCases": {Verb: "List", Resource: "AutomatedReasoningPolicyTestCase", OutputListKey: "testCases", OutputItemKey: "", Method: "GET", URI: "/automated-reasoning-policies/{policyArn}/test-cases"}, + "ListAutomatedReasoningPolicyTestResults": {Verb: "List", Resource: "AutomatedReasoningPolicyTestResult", OutputListKey: "testResults", OutputItemKey: "", Method: "GET", URI: "/automated-reasoning-policies/{policyArn}/build-workflows/{buildWorkflowId}/test-results"}, + "ListCustomModelDeployments": {Verb: "List", Resource: "CustomModelDeployment", OutputListKey: "modelDeploymentSummaries", OutputItemKey: "", Method: "GET", URI: "/model-customization/custom-model-deployments"}, + "ListCustomModels": {Verb: "List", Resource: "CustomModel", OutputListKey: "modelSummaries", OutputItemKey: "", Method: "GET", URI: "/custom-models"}, + "ListEnforcedGuardrailsConfiguration": {Verb: "List", Resource: "EnforcedGuardrailsConfiguration", OutputListKey: "guardrailsConfig", OutputItemKey: "", Method: "GET", URI: "/enforcedGuardrailsConfiguration"}, + "ListEvaluationJobs": {Verb: "List", Resource: "EvaluationJob", OutputListKey: "jobSummaries", OutputItemKey: "", Method: "GET", URI: "/evaluation-jobs"}, + "ListFoundationModelAgreementOffers": {Verb: "List", Resource: "FoundationModelAgreementOffer", OutputListKey: "offers", OutputItemKey: "", Method: "GET", URI: "/list-foundation-model-agreement-offers/{modelId}"}, + "ListFoundationModels": {Verb: "List", Resource: "FoundationModel", OutputListKey: "modelSummaries", OutputItemKey: "", Method: "GET", URI: "/foundation-models"}, + "ListGuardrails": {Verb: "List", Resource: "Guardrail", OutputListKey: "guardrails", OutputItemKey: "", Method: "GET", URI: "/guardrails"}, + "ListImportedModels": {Verb: "List", Resource: "ImportedModel", OutputListKey: "modelSummaries", OutputItemKey: "", Method: "GET", URI: "/imported-models"}, + "ListInferenceProfiles": {Verb: "List", Resource: "InferenceProfile", OutputListKey: "inferenceProfileSummaries", OutputItemKey: "", Method: "GET", URI: "/inference-profiles"}, + "ListMarketplaceModelEndpoints": {Verb: "List", Resource: "MarketplaceModelEndpoint", OutputListKey: "marketplaceModelEndpoints", OutputItemKey: "", Method: "GET", URI: "/marketplace-model/endpoints"}, + "ListModelCopyJobs": {Verb: "List", Resource: "ModelCopyJob", OutputListKey: "modelCopyJobSummaries", OutputItemKey: "", Method: "GET", URI: "/model-copy-jobs"}, + "ListModelCustomizationJobs": {Verb: "List", Resource: "ModelCustomizationJob", OutputListKey: "modelCustomizationJobSummaries", OutputItemKey: "", Method: "GET", URI: "/model-customization-jobs"}, + "ListModelImportJobs": {Verb: "List", Resource: "ModelImportJob", OutputListKey: "modelImportJobSummaries", OutputItemKey: "", Method: "GET", URI: "/model-import-jobs"}, + "ListModelInvocationJobs": {Verb: "List", Resource: "ModelInvocationJob", OutputListKey: "invocationJobSummaries", OutputItemKey: "", Method: "GET", URI: "/model-invocation-jobs"}, + "ListPromptRouters": {Verb: "List", Resource: "PromptRouter", OutputListKey: "promptRouterSummaries", OutputItemKey: "", Method: "GET", URI: "/prompt-routers"}, + "ListProvisionedModelThroughputs": {Verb: "List", Resource: "ProvisionedModelThroughput", OutputListKey: "provisionedModelSummaries", OutputItemKey: "", Method: "GET", URI: "/provisioned-model-throughputs"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "tags", OutputItemKey: "", Method: "POST", URI: "/listTagsForResource"}, + "PutEnforcedGuardrailConfiguration": {Verb: "Update", Resource: "EnforcedGuardrailConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/enforcedGuardrailsConfiguration"}, + "PutModelInvocationLoggingConfiguration": {Verb: "Update", Resource: "ModelInvocationLoggingConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/logging/modelinvocations"}, + "PutResourcePolicy": {Verb: "Update", Resource: "ResourcePolicy", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/resource-policy"}, + "PutUseCaseForModelAccess": {Verb: "Update", Resource: "UseCaseForModelAccess", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/use-case-for-model-access"}, + "RegisterMarketplaceModelEndpoint": {Verb: "Create", Resource: "MarketplaceModelEndpoint", OutputListKey: "", OutputItemKey: "marketplaceModelEndpoint", Method: "POST", URI: "/marketplace-model/endpoints/{endpointIdentifier}/registration"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/tagResource"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/untagResource"}, + "UpdateAutomatedReasoningPolicy": {Verb: "Update", Resource: "AutomatedReasoningPolicy", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/automated-reasoning-policies/{policyArn}"}, + "UpdateAutomatedReasoningPolicyAnnotations": {Verb: "Update", Resource: "AutomatedReasoningPolicyAnnotation", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/automated-reasoning-policies/{policyArn}/build-workflows/{buildWorkflowId}/annotations"}, + "UpdateAutomatedReasoningPolicyTestCase": {Verb: "Update", Resource: "AutomatedReasoningPolicyTestCase", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/automated-reasoning-policies/{policyArn}/test-cases/{testCaseId}"}, + "UpdateCustomModelDeployment": {Verb: "Update", Resource: "CustomModelDeployment", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/model-customization/custom-model-deployments/{customModelDeploymentIdentifier}"}, + "UpdateGuardrail": {Verb: "Update", Resource: "Guardrail", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/guardrails/{guardrailIdentifier}"}, + "UpdateMarketplaceModelEndpoint": {Verb: "Update", Resource: "MarketplaceModelEndpoint", OutputListKey: "", OutputItemKey: "marketplaceModelEndpoint", Method: "PATCH", URI: "/marketplace-model/endpoints/{endpointArn}"}, + "UpdateProvisionedModelThroughput": {Verb: "Update", Resource: "ProvisionedModelThroughput", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/provisioned-model-throughput/{provisionedModelId}"}, + }) + crud.Register("bedrockagent", map[string]crud.OpMeta{ + "CreateAgent": {Verb: "Create", Resource: "Agent", OutputListKey: "", OutputItemKey: "agent", Method: "PUT", URI: "/agents/"}, + "CreateAgentActionGroup": {Verb: "Create", Resource: "AgentActionGroup", OutputListKey: "", OutputItemKey: "agentActionGroup", Method: "PUT", URI: "/agents/{agentId}/agentversions/{agentVersion}/actiongroups/"}, + "CreateAgentAlias": {Verb: "Create", Resource: "AgentAlia", OutputListKey: "", OutputItemKey: "agentAlias", Method: "PUT", URI: "/agents/{agentId}/agentaliases/"}, + "CreateDataSource": {Verb: "Create", Resource: "DataSource", OutputListKey: "", OutputItemKey: "dataSource", Method: "PUT", URI: "/knowledgebases/{knowledgeBaseId}/datasources/"}, + "CreateFlow": {Verb: "Create", Resource: "Flow", OutputListKey: "", OutputItemKey: "definition", Method: "POST", URI: "/flows/"}, + "CreateFlowAlias": {Verb: "Create", Resource: "FlowAlia", OutputListKey: "routingConfiguration", OutputItemKey: "concurrencyConfiguration", Method: "POST", URI: "/flows/{flowIdentifier}/aliases"}, + "CreateFlowVersion": {Verb: "Create", Resource: "FlowVersion", OutputListKey: "", OutputItemKey: "definition", Method: "POST", URI: "/flows/{flowIdentifier}/versions"}, + "CreateKnowledgeBase": {Verb: "Create", Resource: "KnowledgeBase", OutputListKey: "", OutputItemKey: "knowledgeBase", Method: "PUT", URI: "/knowledgebases/"}, + "CreatePrompt": {Verb: "Create", Resource: "Prompt", OutputListKey: "variants", OutputItemKey: "", Method: "POST", URI: "/prompts/"}, + "CreatePromptVersion": {Verb: "Create", Resource: "PromptVersion", OutputListKey: "variants", OutputItemKey: "", Method: "POST", URI: "/prompts/{promptIdentifier}/versions"}, + "DeleteAgent": {Verb: "Delete", Resource: "Agent", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/agents/{agentId}/"}, + "DeleteAgentActionGroup": {Verb: "Delete", Resource: "AgentActionGroup", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/agents/{agentId}/agentversions/{agentVersion}/actiongroups/{actionGroupId}/"}, + "DeleteAgentAlias": {Verb: "Delete", Resource: "AgentAlia", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/agents/{agentId}/agentaliases/{agentAliasId}/"}, + "DeleteAgentVersion": {Verb: "Delete", Resource: "AgentVersion", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/agents/{agentId}/agentversions/{agentVersion}/"}, + "DeleteDataSource": {Verb: "Delete", Resource: "DataSource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/knowledgebases/{knowledgeBaseId}/datasources/{dataSourceId}"}, + "DeleteFlow": {Verb: "Delete", Resource: "Flow", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/flows/{flowIdentifier}/"}, + "DeleteFlowAlias": {Verb: "Delete", Resource: "FlowAlia", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/flows/{flowIdentifier}/aliases/{aliasIdentifier}"}, + "DeleteFlowVersion": {Verb: "Delete", Resource: "FlowVersion", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/flows/{flowIdentifier}/versions/{flowVersion}/"}, + "DeleteKnowledgeBase": {Verb: "Delete", Resource: "KnowledgeBase", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/knowledgebases/{knowledgeBaseId}"}, + "DeleteKnowledgeBaseDocuments": {Verb: "Delete", Resource: "KnowledgeBaseDocument", OutputListKey: "documentDetails", OutputItemKey: "", Method: "POST", URI: "/knowledgebases/{knowledgeBaseId}/datasources/{dataSourceId}/documents/deleteDocuments"}, + "DeletePrompt": {Verb: "Delete", Resource: "Prompt", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/prompts/{promptIdentifier}/"}, + "DeleteResourcePolicy": {Verb: "Delete", Resource: "ResourcePolicy", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/resourcepolicy/{resourceArn}"}, + "GetAgent": {Verb: "Get", Resource: "Agent", OutputListKey: "", OutputItemKey: "agent", Method: "GET", URI: "/agents/{agentId}/"}, + "GetAgentActionGroup": {Verb: "Get", Resource: "AgentActionGroup", OutputListKey: "", OutputItemKey: "agentActionGroup", Method: "GET", URI: "/agents/{agentId}/agentversions/{agentVersion}/actiongroups/{actionGroupId}/"}, + "GetAgentAlias": {Verb: "Get", Resource: "AgentAlia", OutputListKey: "", OutputItemKey: "agentAlias", Method: "GET", URI: "/agents/{agentId}/agentaliases/{agentAliasId}/"}, + "GetAgentCollaborator": {Verb: "Get", Resource: "AgentCollaborator", OutputListKey: "", OutputItemKey: "agentCollaborator", Method: "GET", URI: "/agents/{agentId}/agentversions/{agentVersion}/agentcollaborators/{collaboratorId}/"}, + "GetAgentKnowledgeBase": {Verb: "Get", Resource: "AgentKnowledgeBase", OutputListKey: "", OutputItemKey: "agentKnowledgeBase", Method: "GET", URI: "/agents/{agentId}/agentversions/{agentVersion}/knowledgebases/{knowledgeBaseId}/"}, + "GetAgentVersion": {Verb: "Get", Resource: "AgentVersion", OutputListKey: "", OutputItemKey: "agentVersion", Method: "GET", URI: "/agents/{agentId}/agentversions/{agentVersion}/"}, + "GetDataSource": {Verb: "Get", Resource: "DataSource", OutputListKey: "", OutputItemKey: "dataSource", Method: "GET", URI: "/knowledgebases/{knowledgeBaseId}/datasources/{dataSourceId}"}, + "GetFlow": {Verb: "Get", Resource: "Flow", OutputListKey: "validations", OutputItemKey: "definition", Method: "GET", URI: "/flows/{flowIdentifier}/"}, + "GetFlowAlias": {Verb: "Get", Resource: "FlowAlia", OutputListKey: "routingConfiguration", OutputItemKey: "concurrencyConfiguration", Method: "GET", URI: "/flows/{flowIdentifier}/aliases/{aliasIdentifier}"}, + "GetFlowVersion": {Verb: "Get", Resource: "FlowVersion", OutputListKey: "", OutputItemKey: "definition", Method: "GET", URI: "/flows/{flowIdentifier}/versions/{flowVersion}/"}, + "GetIngestionJob": {Verb: "Get", Resource: "IngestionJob", OutputListKey: "", OutputItemKey: "ingestionJob", Method: "GET", URI: "/knowledgebases/{knowledgeBaseId}/datasources/{dataSourceId}/ingestionjobs/{ingestionJobId}"}, + "GetKnowledgeBase": {Verb: "Get", Resource: "KnowledgeBase", OutputListKey: "", OutputItemKey: "knowledgeBase", Method: "GET", URI: "/knowledgebases/{knowledgeBaseId}"}, + "GetKnowledgeBaseDocuments": {Verb: "Get", Resource: "KnowledgeBaseDocument", OutputListKey: "documentDetails", OutputItemKey: "", Method: "POST", URI: "/knowledgebases/{knowledgeBaseId}/datasources/{dataSourceId}/documents/getDocuments"}, + "GetPrompt": {Verb: "Get", Resource: "Prompt", OutputListKey: "variants", OutputItemKey: "", Method: "GET", URI: "/prompts/{promptIdentifier}/"}, + "GetResourcePolicy": {Verb: "Get", Resource: "ResourcePolicy", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/resourcepolicy/{resourceArn}"}, + "ListAgentActionGroups": {Verb: "List", Resource: "AgentActionGroup", OutputListKey: "actionGroupSummaries", OutputItemKey: "", Method: "POST", URI: "/agents/{agentId}/agentversions/{agentVersion}/actiongroups/"}, + "ListAgentAliases": {Verb: "List", Resource: "AgentAliase", OutputListKey: "agentAliasSummaries", OutputItemKey: "", Method: "POST", URI: "/agents/{agentId}/agentaliases/"}, + "ListAgentCollaborators": {Verb: "List", Resource: "AgentCollaborator", OutputListKey: "agentCollaboratorSummaries", OutputItemKey: "", Method: "POST", URI: "/agents/{agentId}/agentversions/{agentVersion}/agentcollaborators/"}, + "ListAgentKnowledgeBases": {Verb: "List", Resource: "AgentKnowledgeBase", OutputListKey: "agentKnowledgeBaseSummaries", OutputItemKey: "", Method: "POST", URI: "/agents/{agentId}/agentversions/{agentVersion}/knowledgebases/"}, + "ListAgentVersions": {Verb: "List", Resource: "AgentVersion", OutputListKey: "agentVersionSummaries", OutputItemKey: "", Method: "POST", URI: "/agents/{agentId}/agentversions/"}, + "ListAgents": {Verb: "List", Resource: "Agent", OutputListKey: "agentSummaries", OutputItemKey: "", Method: "POST", URI: "/agents/"}, + "ListDataSources": {Verb: "List", Resource: "DataSource", OutputListKey: "dataSourceSummaries", OutputItemKey: "", Method: "POST", URI: "/knowledgebases/{knowledgeBaseId}/datasources/"}, + "ListFlowAliases": {Verb: "List", Resource: "FlowAliase", OutputListKey: "flowAliasSummaries", OutputItemKey: "", Method: "GET", URI: "/flows/{flowIdentifier}/aliases"}, + "ListFlowVersions": {Verb: "List", Resource: "FlowVersion", OutputListKey: "flowVersionSummaries", OutputItemKey: "", Method: "GET", URI: "/flows/{flowIdentifier}/versions"}, + "ListFlows": {Verb: "List", Resource: "Flow", OutputListKey: "flowSummaries", OutputItemKey: "", Method: "GET", URI: "/flows/"}, + "ListIngestionJobs": {Verb: "List", Resource: "IngestionJob", OutputListKey: "ingestionJobSummaries", OutputItemKey: "", Method: "POST", URI: "/knowledgebases/{knowledgeBaseId}/datasources/{dataSourceId}/ingestionjobs/"}, + "ListKnowledgeBaseDocuments": {Verb: "List", Resource: "KnowledgeBaseDocument", OutputListKey: "documentDetails", OutputItemKey: "", Method: "POST", URI: "/knowledgebases/{knowledgeBaseId}/datasources/{dataSourceId}/documents"}, + "ListKnowledgeBases": {Verb: "List", Resource: "KnowledgeBase", OutputListKey: "knowledgeBaseSummaries", OutputItemKey: "", Method: "POST", URI: "/knowledgebases/"}, + "ListPrompts": {Verb: "List", Resource: "Prompt", OutputListKey: "promptSummaries", OutputItemKey: "", Method: "GET", URI: "/prompts/"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/tags/{resourceArn}"}, + "PutResourcePolicy": {Verb: "Update", Resource: "ResourcePolicy", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/resourcepolicy/{resourceArn}"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/tags/{resourceArn}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/tags/{resourceArn}"}, + "UpdateAgent": {Verb: "Update", Resource: "Agent", OutputListKey: "", OutputItemKey: "agent", Method: "PUT", URI: "/agents/{agentId}/"}, + "UpdateAgentActionGroup": {Verb: "Update", Resource: "AgentActionGroup", OutputListKey: "", OutputItemKey: "agentActionGroup", Method: "PUT", URI: "/agents/{agentId}/agentversions/{agentVersion}/actiongroups/{actionGroupId}/"}, + "UpdateAgentAlias": {Verb: "Update", Resource: "AgentAlia", OutputListKey: "", OutputItemKey: "agentAlias", Method: "PUT", URI: "/agents/{agentId}/agentaliases/{agentAliasId}/"}, + "UpdateAgentCollaborator": {Verb: "Update", Resource: "AgentCollaborator", OutputListKey: "", OutputItemKey: "agentCollaborator", Method: "PUT", URI: "/agents/{agentId}/agentversions/{agentVersion}/agentcollaborators/{collaboratorId}/"}, + "UpdateAgentKnowledgeBase": {Verb: "Update", Resource: "AgentKnowledgeBase", OutputListKey: "", OutputItemKey: "agentKnowledgeBase", Method: "PUT", URI: "/agents/{agentId}/agentversions/{agentVersion}/knowledgebases/{knowledgeBaseId}/"}, + "UpdateDataSource": {Verb: "Update", Resource: "DataSource", OutputListKey: "", OutputItemKey: "dataSource", Method: "PUT", URI: "/knowledgebases/{knowledgeBaseId}/datasources/{dataSourceId}"}, + "UpdateFlow": {Verb: "Update", Resource: "Flow", OutputListKey: "", OutputItemKey: "definition", Method: "PUT", URI: "/flows/{flowIdentifier}/"}, + "UpdateFlowAlias": {Verb: "Update", Resource: "FlowAlia", OutputListKey: "routingConfiguration", OutputItemKey: "concurrencyConfiguration", Method: "PUT", URI: "/flows/{flowIdentifier}/aliases/{aliasIdentifier}"}, + "UpdateKnowledgeBase": {Verb: "Update", Resource: "KnowledgeBase", OutputListKey: "", OutputItemKey: "knowledgeBase", Method: "PUT", URI: "/knowledgebases/{knowledgeBaseId}"}, + "UpdatePrompt": {Verb: "Update", Resource: "Prompt", OutputListKey: "variants", OutputItemKey: "", Method: "PUT", URI: "/prompts/{promptIdentifier}/"}, + }) + crud.Register("bedrockagentcore", map[string]crud.OpMeta{ + "CreateABTest": {Verb: "Create", Resource: "ABTest", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/ab-tests"}, + "CreateEvent": {Verb: "Create", Resource: "Event", OutputListKey: "", OutputItemKey: "event", Method: "POST", URI: "/memories/{memoryId}/events"}, + "CreatePaymentInstrument": {Verb: "Create", Resource: "PaymentInstrument", OutputListKey: "", OutputItemKey: "paymentInstrument", Method: "POST", URI: "/payments/createPaymentInstrument"}, + "CreatePaymentSession": {Verb: "Create", Resource: "PaymentSession", OutputListKey: "", OutputItemKey: "paymentSession", Method: "POST", URI: "/payments/createPaymentSession"}, + "DeleteABTest": {Verb: "Delete", Resource: "ABTest", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/ab-tests/{abTestId}"}, + "DeleteBatchEvaluation": {Verb: "Delete", Resource: "BatchEvaluation", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/evaluations/batch-evaluate/{batchEvaluationId}"}, + "DeleteCapacityProviderSession": {Verb: "Delete", Resource: "CapacityProviderSession", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/capacity-providers/{capacityProviderId}/sessions/{sessionId}"}, + "DeleteEvent": {Verb: "Delete", Resource: "Event", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/memories/{memoryId}/actor/{actorId}/sessions/{sessionId}/events/{eventId}"}, + "DeleteMemoryRecord": {Verb: "Delete", Resource: "MemoryRecord", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/memories/{memoryId}/memoryRecords/{memoryRecordId}"}, + "DeletePaymentInstrument": {Verb: "Delete", Resource: "PaymentInstrument", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/payments/deletePaymentInstrument"}, + "DeletePaymentSession": {Verb: "Delete", Resource: "PaymentSession", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/payments/deletePaymentSession"}, + "DeleteRecommendation": {Verb: "Delete", Resource: "Recommendation", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/recommendations/{recommendationId}"}, + "GetABTest": {Verb: "Get", Resource: "ABTest", OutputListKey: "errorDetails", OutputItemKey: "gatewayFilter", Method: "GET", URI: "/ab-tests/{abTestId}"}, + "GetAgentCard": {Verb: "Get", Resource: "AgentCard", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/runtimes/{agentRuntimeArn}/invocations/.well-known/agent-card.json"}, + "GetBatchEvaluation": {Verb: "Get", Resource: "BatchEvaluation", OutputListKey: "errorDetails", OutputItemKey: "evaluationResults", Method: "GET", URI: "/evaluations/batch-evaluate/{batchEvaluationId}"}, + "GetBrowserSession": {Verb: "Get", Resource: "BrowserSession", OutputListKey: "certificates", OutputItemKey: "profileConfiguration", Method: "GET", URI: "/browsers/{browserIdentifier}/sessions/get"}, + "GetCodeInterpreterSession": {Verb: "Get", Resource: "CodeInterpreterSession", OutputListKey: "certificates", OutputItemKey: "", Method: "GET", URI: "/code-interpreters/{codeInterpreterIdentifier}/sessions/get"}, + "GetEvent": {Verb: "Get", Resource: "Event", OutputListKey: "", OutputItemKey: "event", Method: "GET", URI: "/memories/{memoryId}/actor/{actorId}/sessions/{sessionId}/events/{eventId}"}, + "GetMemoryRecord": {Verb: "Get", Resource: "MemoryRecord", OutputListKey: "", OutputItemKey: "memoryRecord", Method: "GET", URI: "/memories/{memoryId}/memoryRecord/{memoryRecordId}"}, + "GetPaymentInstrument": {Verb: "Get", Resource: "PaymentInstrument", OutputListKey: "", OutputItemKey: "paymentInstrument", Method: "POST", URI: "/payments/getPaymentInstrument"}, + "GetPaymentInstrumentBalance": {Verb: "Get", Resource: "PaymentInstrumentBalance", OutputListKey: "", OutputItemKey: "tokenBalance", Method: "POST", URI: "/payments/getPaymentInstrumentBalance"}, + "GetPaymentSession": {Verb: "Get", Resource: "PaymentSession", OutputListKey: "", OutputItemKey: "paymentSession", Method: "POST", URI: "/payments/getPaymentSession"}, + "GetRecommendation": {Verb: "Get", Resource: "Recommendation", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/recommendations/{recommendationId}"}, + "GetResourceApiKey": {Verb: "Get", Resource: "ResourceApiKey", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/identities/api-key"}, + "GetResourceOauth2Token": {Verb: "Get", Resource: "ResourceOauth2Token", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/identities/oauth2/token"}, + "GetResourcePaymentToken": {Verb: "Get", Resource: "ResourcePaymentToken", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/identities/payment/token"}, + "GetWorkloadAccessToken": {Verb: "Get", Resource: "WorkloadAccessToken", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/identities/GetWorkloadAccessToken"}, + "GetWorkloadAccessTokenForJWT": {Verb: "Get", Resource: "WorkloadAccessTokenForJWT", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/identities/GetWorkloadAccessTokenForJWT"}, + "GetWorkloadAccessTokenForUserId": {Verb: "Get", Resource: "WorkloadAccessTokenForUserId", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/identities/GetWorkloadAccessTokenForUserId"}, + "ListABTests": {Verb: "List", Resource: "ABTest", OutputListKey: "abTests", OutputItemKey: "", Method: "GET", URI: "/ab-tests"}, + "ListActors": {Verb: "List", Resource: "Actor", OutputListKey: "actorSummaries", OutputItemKey: "", Method: "POST", URI: "/memories/{memoryId}/actors"}, + "ListBatchEvaluations": {Verb: "List", Resource: "BatchEvaluation", OutputListKey: "batchEvaluations", OutputItemKey: "", Method: "GET", URI: "/evaluations/batch-evaluate"}, + "ListBrowserSessions": {Verb: "List", Resource: "BrowserSession", OutputListKey: "items", OutputItemKey: "", Method: "POST", URI: "/browsers/{browserIdentifier}/sessions/list"}, + "ListCodeInterpreterSessions": {Verb: "List", Resource: "CodeInterpreterSession", OutputListKey: "items", OutputItemKey: "", Method: "POST", URI: "/code-interpreters/{codeInterpreterIdentifier}/sessions/list"}, + "ListEvents": {Verb: "List", Resource: "Event", OutputListKey: "events", OutputItemKey: "", Method: "POST", URI: "/memories/{memoryId}/actor/{actorId}/sessions/{sessionId}"}, + "ListMemoryExtractionJobs": {Verb: "List", Resource: "MemoryExtractionJob", OutputListKey: "jobs", OutputItemKey: "", Method: "POST", URI: "/memories/{memoryId}/extractionJobs"}, + "ListMemoryRecords": {Verb: "List", Resource: "MemoryRecord", OutputListKey: "memoryRecordSummaries", OutputItemKey: "", Method: "POST", URI: "/memories/{memoryId}/memoryRecords"}, + "ListPaymentInstruments": {Verb: "List", Resource: "PaymentInstrument", OutputListKey: "paymentInstruments", OutputItemKey: "", Method: "POST", URI: "/payments/listPaymentInstruments"}, + "ListPaymentSessions": {Verb: "List", Resource: "PaymentSession", OutputListKey: "paymentSessions", OutputItemKey: "", Method: "POST", URI: "/payments/listPaymentSessions"}, + "ListRecommendations": {Verb: "List", Resource: "Recommendation", OutputListKey: "recommendationSummaries", OutputItemKey: "", Method: "GET", URI: "/recommendations"}, + "ListSessions": {Verb: "List", Resource: "Session", OutputListKey: "sessionSummaries", OutputItemKey: "", Method: "POST", URI: "/memories/{memoryId}/actor/{actorId}/sessions"}, + "UpdateABTest": {Verb: "Update", Resource: "ABTest", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/ab-tests/{abTestId}"}, + "UpdateBrowserStream": {Verb: "Update", Resource: "BrowserStream", OutputListKey: "", OutputItemKey: "streams", Method: "PUT", URI: "/browsers/{browserIdentifier}/sessions/streams/update"}, + }) + crud.Register("bedrockagentcorecontrol", map[string]crud.OpMeta{ + "CreateAgentRuntime": {Verb: "Create", Resource: "AgentRuntime", OutputListKey: "", OutputItemKey: "workloadIdentityDetails", Method: "PUT", URI: "/runtimes/"}, + "CreateAgentRuntimeEndpoint": {Verb: "Create", Resource: "AgentRuntimeEndpoint", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/runtimes/{agentRuntimeId}/runtime-endpoints/"}, + "CreateApiKeyCredentialProvider": {Verb: "Create", Resource: "ApiKeyCredentialProvider", OutputListKey: "", OutputItemKey: "apiKeySecretArn", Method: "POST", URI: "/identities/CreateApiKeyCredentialProvider"}, + "CreateBrowser": {Verb: "Create", Resource: "Browser", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/browsers"}, + "CreateBrowserProfile": {Verb: "Create", Resource: "BrowserProfile", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/browser-profiles"}, + "CreateCapacityProvider": {Verb: "Create", Resource: "CapacityProvider", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/capacity-providers"}, + "CreateCodeInterpreter": {Verb: "Create", Resource: "CodeInterpreter", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/code-interpreters"}, + "CreateConfigurationBundle": {Verb: "Create", Resource: "ConfigurationBundle", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/configuration-bundles/create"}, + "CreateConsentPortal": {Verb: "Create", Resource: "ConsentPortal", OutputListKey: "sources", OutputItemKey: "idpConfig", Method: "POST", URI: "/identities/CreateConsentPortal"}, + "CreateDataset": {Verb: "Create", Resource: "Dataset", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/datasets"}, + "CreateDatasetVersion": {Verb: "Create", Resource: "DatasetVersion", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/datasets/{datasetId}/versions"}, + "CreateEvaluator": {Verb: "Create", Resource: "Evaluator", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/evaluators/create"}, + "CreateGateway": {Verb: "Create", Resource: "Gateway", OutputListKey: "interceptorConfigurations", OutputItemKey: "customTransformConfiguration", Method: "POST", URI: "/gateways/"}, + "CreateGatewayRateLimit": {Verb: "Create", Resource: "GatewayRateLimit", OutputListKey: "dimensionKeys", OutputItemKey: "", Method: "POST", URI: "/gateways/{gatewayIdentifier}/rate-limits"}, + "CreateGatewayRule": {Verb: "Create", Resource: "GatewayRule", OutputListKey: "actions", OutputItemKey: "system", Method: "POST", URI: "/gateways/{gatewayIdentifier}/rules"}, + "CreateGatewayTarget": {Verb: "Create", Resource: "GatewayTarget", OutputListKey: "credentialProviderConfigurations", OutputItemKey: "metadataConfiguration", Method: "POST", URI: "/gateways/{gatewayIdentifier}/targets/"}, + "CreateHarness": {Verb: "Create", Resource: "Harness", OutputListKey: "", OutputItemKey: "harness", Method: "POST", URI: "/harnesses"}, + "CreateHarnessEndpoint": {Verb: "Create", Resource: "HarnessEndpoint", OutputListKey: "", OutputItemKey: "endpoint", Method: "POST", URI: "/harnesses/{harnessId}/endpoints"}, + "CreateMemory": {Verb: "Create", Resource: "Memory", OutputListKey: "", OutputItemKey: "memory", Method: "POST", URI: "/memories/create"}, + "CreateOauth2CredentialProvider": {Verb: "Create", Resource: "Oauth2CredentialProvider", OutputListKey: "", OutputItemKey: "clientSecretArn", Method: "POST", URI: "/identities/CreateOauth2CredentialProvider"}, + "CreateOnlineEvaluationConfig": {Verb: "Create", Resource: "OnlineEvaluationConfig", OutputListKey: "", OutputItemKey: "outputConfig", Method: "POST", URI: "/online-evaluation-configs/create"}, + "CreatePaymentConnector": {Verb: "Create", Resource: "PaymentConnector", OutputListKey: "credentialProviderConfigurations", OutputItemKey: "", Method: "POST", URI: "/payments/managers/{paymentManagerId}/connectors"}, + "CreatePaymentCredentialProvider": {Verb: "Create", Resource: "PaymentCredentialProvider", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/identities/CreatePaymentCredentialProvider"}, + "CreatePaymentManager": {Verb: "Create", Resource: "PaymentManager", OutputListKey: "", OutputItemKey: "workloadIdentityDetails", Method: "POST", URI: "/payments/managers"}, + "CreatePolicy": {Verb: "Create", Resource: "Policy", OutputListKey: "statusReasons", OutputItemKey: "", Method: "POST", URI: "/policy-engines/{policyEngineId}/policies"}, + "CreatePolicyEngine": {Verb: "Create", Resource: "PolicyEngine", OutputListKey: "statusReasons", OutputItemKey: "", Method: "POST", URI: "/policy-engines"}, + "CreateRegistry": {Verb: "Create", Resource: "Registry", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/registries"}, + "CreateRegistryRecord": {Verb: "Create", Resource: "RegistryRecord", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/registries/{registryId}/records"}, + "CreateWorkloadIdentity": {Verb: "Create", Resource: "WorkloadIdentity", OutputListKey: "allowedResourceOauth2ReturnUrls", OutputItemKey: "", Method: "POST", URI: "/identities/CreateWorkloadIdentity"}, + "DeleteAgentRuntime": {Verb: "Delete", Resource: "AgentRuntime", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/runtimes/{agentRuntimeId}/"}, + "DeleteAgentRuntimeEndpoint": {Verb: "Delete", Resource: "AgentRuntimeEndpoint", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/runtimes/{agentRuntimeId}/runtime-endpoints/{endpointName}/"}, + "DeleteApiKeyCredentialProvider": {Verb: "Delete", Resource: "ApiKeyCredentialProvider", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/identities/DeleteApiKeyCredentialProvider"}, + "DeleteBrowser": {Verb: "Delete", Resource: "Browser", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/browsers/{browserId}"}, + "DeleteBrowserProfile": {Verb: "Delete", Resource: "BrowserProfile", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/browser-profiles/{profileId}"}, + "DeleteCapacityProvider": {Verb: "Delete", Resource: "CapacityProvider", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/capacity-providers/{capacityProviderId}"}, + "DeleteCodeInterpreter": {Verb: "Delete", Resource: "CodeInterpreter", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/code-interpreters/{codeInterpreterId}"}, + "DeleteConfigurationBundle": {Verb: "Delete", Resource: "ConfigurationBundle", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/configuration-bundles/{bundleId}"}, + "DeleteConsentPortal": {Verb: "Delete", Resource: "ConsentPortal", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/identities/DeleteConsentPortal"}, + "DeleteDataset": {Verb: "Delete", Resource: "Dataset", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/datasets/{datasetId}"}, + "DeleteDatasetExamples": {Verb: "Delete", Resource: "DatasetExample", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/datasets/{datasetId}/examples/delete"}, + "DeleteEvaluator": {Verb: "Delete", Resource: "Evaluator", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/evaluators/{evaluatorId}"}, + "DeleteGateway": {Verb: "Delete", Resource: "Gateway", OutputListKey: "statusReasons", OutputItemKey: "", Method: "DELETE", URI: "/gateways/{gatewayIdentifier}/"}, + "DeleteGatewayRateLimit": {Verb: "Delete", Resource: "GatewayRateLimit", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/gateways/{gatewayIdentifier}/rate-limits/{rateLimitId}"}, + "DeleteGatewayRule": {Verb: "Delete", Resource: "GatewayRule", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/gateways/{gatewayIdentifier}/rules/{ruleId}"}, + "DeleteGatewayTarget": {Verb: "Delete", Resource: "GatewayTarget", OutputListKey: "statusReasons", OutputItemKey: "", Method: "DELETE", URI: "/gateways/{gatewayIdentifier}/targets/{targetId}/"}, + "DeleteHarness": {Verb: "Delete", Resource: "Harness", OutputListKey: "", OutputItemKey: "harness", Method: "DELETE", URI: "/harnesses/{harnessId}"}, + "DeleteHarnessEndpoint": {Verb: "Delete", Resource: "HarnessEndpoint", OutputListKey: "", OutputItemKey: "endpoint", Method: "DELETE", URI: "/harnesses/{harnessId}/endpoints/{endpointName}"}, + "DeleteMemory": {Verb: "Delete", Resource: "Memory", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/memories/{memoryId}/delete"}, + "DeleteOauth2CredentialProvider": {Verb: "Delete", Resource: "Oauth2CredentialProvider", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/identities/DeleteOauth2CredentialProvider"}, + "DeleteOnlineEvaluationConfig": {Verb: "Delete", Resource: "OnlineEvaluationConfig", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/online-evaluation-configs/{onlineEvaluationConfigId}"}, + "DeletePaymentConnector": {Verb: "Delete", Resource: "PaymentConnector", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/payments/managers/{paymentManagerId}/connectors/{paymentConnectorId}"}, + "DeletePaymentCredentialProvider": {Verb: "Delete", Resource: "PaymentCredentialProvider", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/identities/DeletePaymentCredentialProvider"}, + "DeletePaymentManager": {Verb: "Delete", Resource: "PaymentManager", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/payments/managers/{paymentManagerId}"}, + "DeletePolicy": {Verb: "Delete", Resource: "Policy", OutputListKey: "statusReasons", OutputItemKey: "", Method: "DELETE", URI: "/policy-engines/{policyEngineId}/policies/{policyId}"}, + "DeletePolicyEngine": {Verb: "Delete", Resource: "PolicyEngine", OutputListKey: "statusReasons", OutputItemKey: "", Method: "DELETE", URI: "/policy-engines/{policyEngineId}"}, + "DeleteRegistry": {Verb: "Delete", Resource: "Registry", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/registries/{registryId}"}, + "DeleteRegistryRecord": {Verb: "Delete", Resource: "RegistryRecord", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/registries/{registryId}/records/{recordId}"}, + "DeleteResourcePolicy": {Verb: "Delete", Resource: "ResourcePolicy", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/resourcepolicy/{resourceArn}"}, + "DeleteWorkloadIdentity": {Verb: "Delete", Resource: "WorkloadIdentity", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/identities/DeleteWorkloadIdentity"}, + "GetAgentRuntime": {Verb: "Get", Resource: "AgentRuntime", OutputListKey: "filesystemConfigurations", OutputItemKey: "capacityProviderConfiguration", Method: "GET", URI: "/runtimes/{agentRuntimeId}/"}, + "GetAgentRuntimeEndpoint": {Verb: "Get", Resource: "AgentRuntimeEndpoint", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/runtimes/{agentRuntimeId}/runtime-endpoints/{endpointName}/"}, + "GetApiKeyCredentialProvider": {Verb: "Get", Resource: "ApiKeyCredentialProvider", OutputListKey: "", OutputItemKey: "apiKeySecretArn", Method: "POST", URI: "/identities/GetApiKeyCredentialProvider"}, + "GetBrowser": {Verb: "Get", Resource: "Browser", OutputListKey: "certificates", OutputItemKey: "browserSigning", Method: "GET", URI: "/browsers/{browserId}"}, + "GetBrowserProfile": {Verb: "Get", Resource: "BrowserProfile", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/browser-profiles/{profileId}"}, + "GetCapacityProvider": {Verb: "Get", Resource: "CapacityProvider", OutputListKey: "", OutputItemKey: "permissionsConfiguration", Method: "GET", URI: "/capacity-providers/{capacityProviderId}"}, + "GetCodeInterpreter": {Verb: "Get", Resource: "CodeInterpreter", OutputListKey: "certificates", OutputItemKey: "networkConfiguration", Method: "GET", URI: "/code-interpreters/{codeInterpreterId}"}, + "GetConfigurationBundle": {Verb: "Get", Resource: "ConfigurationBundle", OutputListKey: "", OutputItemKey: "lineageMetadata", Method: "GET", URI: "/configuration-bundles/{bundleId}"}, + "GetConfigurationBundleVersion": {Verb: "Get", Resource: "ConfigurationBundleVersion", OutputListKey: "", OutputItemKey: "lineageMetadata", Method: "GET", URI: "/configuration-bundles/{bundleId}/versions/{versionId}"}, + "GetConsentPortal": {Verb: "Get", Resource: "ConsentPortal", OutputListKey: "sources", OutputItemKey: "idpConfig", Method: "POST", URI: "/identities/GetConsentPortal"}, + "GetDataset": {Verb: "Get", Resource: "Dataset", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/datasets/{datasetId}"}, + "GetEvaluator": {Verb: "Get", Resource: "Evaluator", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/evaluators/{evaluatorId}"}, + "GetGateway": {Verb: "Get", Resource: "Gateway", OutputListKey: "interceptorConfigurations", OutputItemKey: "customTransformConfiguration", Method: "GET", URI: "/gateways/{gatewayIdentifier}/"}, + "GetGatewayRateLimit": {Verb: "Get", Resource: "GatewayRateLimit", OutputListKey: "dimensionKeys", OutputItemKey: "", Method: "GET", URI: "/gateways/{gatewayIdentifier}/rate-limits/{rateLimitId}"}, + "GetGatewayRule": {Verb: "Get", Resource: "GatewayRule", OutputListKey: "actions", OutputItemKey: "system", Method: "GET", URI: "/gateways/{gatewayIdentifier}/rules/{ruleId}"}, + "GetGatewayTarget": {Verb: "Get", Resource: "GatewayTarget", OutputListKey: "credentialProviderConfigurations", OutputItemKey: "metadataConfiguration", Method: "GET", URI: "/gateways/{gatewayIdentifier}/targets/{targetId}/"}, + "GetHarness": {Verb: "Get", Resource: "Harness", OutputListKey: "", OutputItemKey: "harness", Method: "GET", URI: "/harnesses/{harnessId}"}, + "GetHarnessEndpoint": {Verb: "Get", Resource: "HarnessEndpoint", OutputListKey: "", OutputItemKey: "endpoint", Method: "GET", URI: "/harnesses/{harnessId}/endpoints/{endpointName}"}, + "GetMemory": {Verb: "Get", Resource: "Memory", OutputListKey: "", OutputItemKey: "memory", Method: "GET", URI: "/memories/{memoryId}/details"}, + "GetOauth2CredentialProvider": {Verb: "Get", Resource: "Oauth2CredentialProvider", OutputListKey: "", OutputItemKey: "clientSecretArn", Method: "POST", URI: "/identities/GetOauth2CredentialProvider"}, + "GetOnlineEvaluationConfig": {Verb: "Get", Resource: "OnlineEvaluationConfig", OutputListKey: "evaluators", OutputItemKey: "clusteringConfig", Method: "GET", URI: "/online-evaluation-configs/{onlineEvaluationConfigId}"}, + "GetPaymentConnector": {Verb: "Get", Resource: "PaymentConnector", OutputListKey: "credentialProviderConfigurations", OutputItemKey: "", Method: "GET", URI: "/payments/managers/{paymentManagerId}/connectors/{paymentConnectorId}"}, + "GetPaymentCredentialProvider": {Verb: "Get", Resource: "PaymentCredentialProvider", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/identities/GetPaymentCredentialProvider"}, + "GetPaymentManager": {Verb: "Get", Resource: "PaymentManager", OutputListKey: "", OutputItemKey: "workloadIdentityDetails", Method: "GET", URI: "/payments/managers/{paymentManagerId}"}, + "GetPolicy": {Verb: "Get", Resource: "Policy", OutputListKey: "statusReasons", OutputItemKey: "", Method: "GET", URI: "/policy-engines/{policyEngineId}/policies/{policyId}"}, + "GetPolicyEngine": {Verb: "Get", Resource: "PolicyEngine", OutputListKey: "statusReasons", OutputItemKey: "", Method: "GET", URI: "/policy-engines/{policyEngineId}"}, + "GetPolicyEngineSummary": {Verb: "Get", Resource: "PolicyEngineSummary", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/policy-engine-summaries/{policyEngineId}"}, + "GetPolicyGeneration": {Verb: "Get", Resource: "PolicyGeneration", OutputListKey: "statusReasons", OutputItemKey: "", Method: "GET", URI: "/policy-engines/{policyEngineId}/policy-generations/{policyGenerationId}"}, + "GetPolicyGenerationSummary": {Verb: "Get", Resource: "PolicyGenerationSummary", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/policy-engines/{policyEngineId}/policy-generation-summaries/{policyGenerationId}"}, + "GetPolicySummary": {Verb: "Get", Resource: "PolicySummary", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/policy-engines/{policyEngineId}/policy-summaries/{policyId}"}, + "GetRegistry": {Verb: "Get", Resource: "Registry", OutputListKey: "", OutputItemKey: "approvalConfiguration", Method: "GET", URI: "/registries/{registryId}"}, + "GetRegistryRecord": {Verb: "Get", Resource: "RegistryRecord", OutputListKey: "", OutputItemKey: "descriptors", Method: "GET", URI: "/registries/{registryId}/records/{recordId}"}, + "GetResourcePolicy": {Verb: "Get", Resource: "ResourcePolicy", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/resourcepolicy/{resourceArn}"}, + "GetTokenVault": {Verb: "Get", Resource: "TokenVault", OutputListKey: "", OutputItemKey: "kmsConfiguration", Method: "POST", URI: "/identities/get-token-vault"}, + "GetWorkloadIdentity": {Verb: "Get", Resource: "WorkloadIdentity", OutputListKey: "allowedResourceOauth2ReturnUrls", OutputItemKey: "", Method: "POST", URI: "/identities/GetWorkloadIdentity"}, + "ListAgentRuntimeEndpoints": {Verb: "List", Resource: "AgentRuntimeEndpoint", OutputListKey: "runtimeEndpoints", OutputItemKey: "", Method: "POST", URI: "/runtimes/{agentRuntimeId}/runtime-endpoints/"}, + "ListAgentRuntimeVersions": {Verb: "List", Resource: "AgentRuntimeVersion", OutputListKey: "agentRuntimes", OutputItemKey: "", Method: "POST", URI: "/runtimes/{agentRuntimeId}/versions/"}, + "ListAgentRuntimeVersionsByCapacityProvider": {Verb: "List", Resource: "AgentRuntimeVersionsByCapacityProvider", OutputListKey: "agentRuntimes", OutputItemKey: "", Method: "POST", URI: "/capacity-providers/{capacityProviderId}/runtime-versions"}, + "ListAgentRuntimes": {Verb: "List", Resource: "AgentRuntime", OutputListKey: "agentRuntimes", OutputItemKey: "", Method: "POST", URI: "/runtimes/"}, + "ListApiKeyCredentialProviders": {Verb: "List", Resource: "ApiKeyCredentialProvider", OutputListKey: "credentialProviders", OutputItemKey: "", Method: "POST", URI: "/identities/ListApiKeyCredentialProviders"}, + "ListBrowserProfiles": {Verb: "List", Resource: "BrowserProfile", OutputListKey: "profileSummaries", OutputItemKey: "", Method: "POST", URI: "/browser-profiles"}, + "ListBrowsers": {Verb: "List", Resource: "Browser", OutputListKey: "browserSummaries", OutputItemKey: "", Method: "POST", URI: "/browsers"}, + "ListCapacityProviders": {Verb: "List", Resource: "CapacityProvider", OutputListKey: "capacityProviders", OutputItemKey: "", Method: "POST", URI: "/capacity-providers"}, + "ListCodeInterpreters": {Verb: "List", Resource: "CodeInterpreter", OutputListKey: "codeInterpreterSummaries", OutputItemKey: "", Method: "POST", URI: "/code-interpreters"}, + "ListConfigurationBundleVersions": {Verb: "List", Resource: "ConfigurationBundleVersion", OutputListKey: "versions", OutputItemKey: "", Method: "POST", URI: "/configuration-bundles/{bundleId}/versions"}, + "ListConfigurationBundles": {Verb: "List", Resource: "ConfigurationBundle", OutputListKey: "bundles", OutputItemKey: "", Method: "POST", URI: "/configuration-bundles"}, + "ListConsentPortals": {Verb: "List", Resource: "ConsentPortal", OutputListKey: "consentPortals", OutputItemKey: "", Method: "POST", URI: "/identities/ListConsentPortals"}, + "ListDatasetExamples": {Verb: "List", Resource: "DatasetExample", OutputListKey: "examples", OutputItemKey: "", Method: "GET", URI: "/datasets/{datasetId}/examples"}, + "ListDatasetVersions": {Verb: "List", Resource: "DatasetVersion", OutputListKey: "versions", OutputItemKey: "", Method: "GET", URI: "/datasets/{datasetId}/versions"}, + "ListDatasets": {Verb: "List", Resource: "Dataset", OutputListKey: "datasets", OutputItemKey: "", Method: "GET", URI: "/datasets"}, + "ListEvaluators": {Verb: "List", Resource: "Evaluator", OutputListKey: "evaluators", OutputItemKey: "", Method: "POST", URI: "/evaluators"}, + "ListGatewayRateLimits": {Verb: "List", Resource: "GatewayRateLimit", OutputListKey: "rateLimits", OutputItemKey: "", Method: "GET", URI: "/gateways/{gatewayIdentifier}/rate-limits"}, + "ListGatewayRules": {Verb: "List", Resource: "GatewayRule", OutputListKey: "gatewayRules", OutputItemKey: "", Method: "GET", URI: "/gateways/{gatewayIdentifier}/rules"}, + "ListGatewayTargets": {Verb: "List", Resource: "GatewayTarget", OutputListKey: "items", OutputItemKey: "", Method: "GET", URI: "/gateways/{gatewayIdentifier}/targets/"}, + "ListGateways": {Verb: "List", Resource: "Gateway", OutputListKey: "items", OutputItemKey: "", Method: "GET", URI: "/gateways/"}, + "ListHarnessEndpoints": {Verb: "List", Resource: "HarnessEndpoint", OutputListKey: "endpoints", OutputItemKey: "", Method: "GET", URI: "/harnesses/{harnessId}/endpoints"}, + "ListHarnessVersions": {Verb: "List", Resource: "HarnessVersion", OutputListKey: "harnessVersions", OutputItemKey: "", Method: "GET", URI: "/harnesses/{harnessId}/versions"}, + "ListHarnesses": {Verb: "List", Resource: "Harness", OutputListKey: "harnesses", OutputItemKey: "", Method: "GET", URI: "/harnesses"}, + "ListMemories": {Verb: "List", Resource: "Memory", OutputListKey: "memories", OutputItemKey: "", Method: "POST", URI: "/memories/"}, + "ListOauth2CredentialProviders": {Verb: "List", Resource: "Oauth2CredentialProvider", OutputListKey: "credentialProviders", OutputItemKey: "", Method: "POST", URI: "/identities/ListOauth2CredentialProviders"}, + "ListOnlineEvaluationConfigs": {Verb: "List", Resource: "OnlineEvaluationConfig", OutputListKey: "onlineEvaluationConfigs", OutputItemKey: "", Method: "POST", URI: "/online-evaluation-configs"}, + "ListPaymentConnectors": {Verb: "List", Resource: "PaymentConnector", OutputListKey: "paymentConnectors", OutputItemKey: "", Method: "POST", URI: "/payments/managers/{paymentManagerId}/connectors-list"}, + "ListPaymentCredentialProviders": {Verb: "List", Resource: "PaymentCredentialProvider", OutputListKey: "credentialProviders", OutputItemKey: "", Method: "POST", URI: "/identities/ListPaymentCredentialProviders"}, + "ListPaymentManagers": {Verb: "List", Resource: "PaymentManager", OutputListKey: "paymentManagers", OutputItemKey: "", Method: "POST", URI: "/payments/managers-list"}, + "ListPolicies": {Verb: "List", Resource: "Policy", OutputListKey: "policies", OutputItemKey: "", Method: "GET", URI: "/policy-engines/{policyEngineId}/policies"}, + "ListPolicyEngineSummaries": {Verb: "List", Resource: "PolicyEngineSummary", OutputListKey: "policyEngines", OutputItemKey: "", Method: "GET", URI: "/policy-engine-summaries"}, + "ListPolicyEngines": {Verb: "List", Resource: "PolicyEngine", OutputListKey: "policyEngines", OutputItemKey: "", Method: "GET", URI: "/policy-engines"}, + "ListPolicyGenerationAssets": {Verb: "List", Resource: "PolicyGenerationAsset", OutputListKey: "policyGenerationAssets", OutputItemKey: "", Method: "GET", URI: "/policy-engines/{policyEngineId}/policy-generations/{policyGenerationId}/assets"}, + "ListPolicyGenerationSummaries": {Verb: "List", Resource: "PolicyGenerationSummary", OutputListKey: "policyGenerations", OutputItemKey: "", Method: "GET", URI: "/policy-engines/{policyEngineId}/policy-generation-summaries"}, + "ListPolicyGenerations": {Verb: "List", Resource: "PolicyGeneration", OutputListKey: "policyGenerations", OutputItemKey: "", Method: "GET", URI: "/policy-engines/{policyEngineId}/policy-generations"}, + "ListPolicySummaries": {Verb: "List", Resource: "PolicySummary", OutputListKey: "policies", OutputItemKey: "", Method: "GET", URI: "/policy-engines/{policyEngineId}/policy-summaries"}, + "ListRegistries": {Verb: "List", Resource: "Registry", OutputListKey: "registries", OutputItemKey: "", Method: "GET", URI: "/registries"}, + "ListRegistryRecords": {Verb: "List", Resource: "RegistryRecord", OutputListKey: "registryRecords", OutputItemKey: "", Method: "GET", URI: "/registries/{registryId}/records"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/tags/{resourceArn}"}, + "ListWorkloadIdentities": {Verb: "List", Resource: "WorkloadIdentity", OutputListKey: "workloadIdentities", OutputItemKey: "", Method: "POST", URI: "/identities/ListWorkloadIdentities"}, + "PutResourcePolicy": {Verb: "Update", Resource: "ResourcePolicy", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/resourcepolicy/{resourceArn}"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/tags/{resourceArn}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/tags/{resourceArn}"}, + "UpdateAgentRuntime": {Verb: "Update", Resource: "AgentRuntime", OutputListKey: "", OutputItemKey: "workloadIdentityDetails", Method: "PUT", URI: "/runtimes/{agentRuntimeId}/"}, + "UpdateAgentRuntimeEndpoint": {Verb: "Update", Resource: "AgentRuntimeEndpoint", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/runtimes/{agentRuntimeId}/runtime-endpoints/{endpointName}/"}, + "UpdateApiKeyCredentialProvider": {Verb: "Update", Resource: "ApiKeyCredentialProvider", OutputListKey: "", OutputItemKey: "apiKeySecretArn", Method: "POST", URI: "/identities/UpdateApiKeyCredentialProvider"}, + "UpdateCapacityProvider": {Verb: "Update", Resource: "CapacityProvider", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/capacity-providers/{capacityProviderId}"}, + "UpdateConfigurationBundle": {Verb: "Update", Resource: "ConfigurationBundle", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/configuration-bundles/{bundleId}"}, + "UpdateConsentPortal": {Verb: "Update", Resource: "ConsentPortal", OutputListKey: "sources", OutputItemKey: "idpConfig", Method: "POST", URI: "/identities/UpdateConsentPortal"}, + "UpdateDataset": {Verb: "Update", Resource: "Dataset", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/datasets/{datasetId}"}, + "UpdateDatasetExamples": {Verb: "Update", Resource: "DatasetExample", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/datasets/{datasetId}/examples/update"}, + "UpdateEvaluator": {Verb: "Update", Resource: "Evaluator", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/evaluators/{evaluatorId}"}, + "UpdateGateway": {Verb: "Update", Resource: "Gateway", OutputListKey: "interceptorConfigurations", OutputItemKey: "customTransformConfiguration", Method: "PUT", URI: "/gateways/{gatewayIdentifier}/"}, + "UpdateGatewayRateLimit": {Verb: "Update", Resource: "GatewayRateLimit", OutputListKey: "dimensionKeys", OutputItemKey: "", Method: "PATCH", URI: "/gateways/{gatewayIdentifier}/rate-limits/{rateLimitId}"}, + "UpdateGatewayRule": {Verb: "Update", Resource: "GatewayRule", OutputListKey: "actions", OutputItemKey: "system", Method: "PATCH", URI: "/gateways/{gatewayIdentifier}/rules/{ruleId}"}, + "UpdateGatewayTarget": {Verb: "Update", Resource: "GatewayTarget", OutputListKey: "credentialProviderConfigurations", OutputItemKey: "metadataConfiguration", Method: "PUT", URI: "/gateways/{gatewayIdentifier}/targets/{targetId}/"}, + "UpdateHarness": {Verb: "Update", Resource: "Harness", OutputListKey: "", OutputItemKey: "harness", Method: "PATCH", URI: "/harnesses/{harnessId}"}, + "UpdateHarnessEndpoint": {Verb: "Update", Resource: "HarnessEndpoint", OutputListKey: "", OutputItemKey: "endpoint", Method: "PATCH", URI: "/harnesses/{harnessId}/endpoints/{endpointName}"}, + "UpdateMemory": {Verb: "Update", Resource: "Memory", OutputListKey: "", OutputItemKey: "memory", Method: "PUT", URI: "/memories/{memoryId}/update"}, + "UpdateOauth2CredentialProvider": {Verb: "Update", Resource: "Oauth2CredentialProvider", OutputListKey: "", OutputItemKey: "clientSecretArn", Method: "POST", URI: "/identities/UpdateOauth2CredentialProvider"}, + "UpdateOnlineEvaluationConfig": {Verb: "Update", Resource: "OnlineEvaluationConfig", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/online-evaluation-configs/{onlineEvaluationConfigId}"}, + "UpdatePaymentConnector": {Verb: "Update", Resource: "PaymentConnector", OutputListKey: "credentialProviderConfigurations", OutputItemKey: "", Method: "PATCH", URI: "/payments/managers/{paymentManagerId}/connectors/{paymentConnectorId}"}, + "UpdatePaymentCredentialProvider": {Verb: "Update", Resource: "PaymentCredentialProvider", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/identities/UpdatePaymentCredentialProvider"}, + "UpdatePaymentManager": {Verb: "Update", Resource: "PaymentManager", OutputListKey: "", OutputItemKey: "workloadIdentityDetails", Method: "PATCH", URI: "/payments/managers/{paymentManagerId}"}, + "UpdatePolicy": {Verb: "Update", Resource: "Policy", OutputListKey: "statusReasons", OutputItemKey: "", Method: "PATCH", URI: "/policy-engines/{policyEngineId}/policies/{policyId}"}, + "UpdatePolicyEngine": {Verb: "Update", Resource: "PolicyEngine", OutputListKey: "statusReasons", OutputItemKey: "", Method: "PATCH", URI: "/policy-engines/{policyEngineId}"}, + "UpdateRegistry": {Verb: "Update", Resource: "Registry", OutputListKey: "", OutputItemKey: "approvalConfiguration", Method: "PATCH", URI: "/registries/{registryId}"}, + "UpdateRegistryRecord": {Verb: "Update", Resource: "RegistryRecord", OutputListKey: "", OutputItemKey: "descriptors", Method: "PATCH", URI: "/registries/{registryId}/records/{recordId}"}, + "UpdateRegistryRecordStatus": {Verb: "Update", Resource: "RegistryRecordStatu", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/registries/{registryId}/records/{recordId}/status"}, + "UpdateWorkloadIdentity": {Verb: "Update", Resource: "WorkloadIdentity", OutputListKey: "allowedResourceOauth2ReturnUrls", OutputItemKey: "", Method: "POST", URI: "/identities/UpdateWorkloadIdentity"}, + }) + crud.Register("bedrockagentruntime", map[string]crud.OpMeta{ + "CreateInvocation": {Verb: "Create", Resource: "Invocation", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/sessions/{sessionIdentifier}/invocations/"}, + "CreateSession": {Verb: "Create", Resource: "Session", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/sessions/"}, + "DeleteAgentMemory": {Verb: "Delete", Resource: "AgentMemory", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/agents/{agentId}/agentAliases/{agentAliasId}/memories"}, + "DeleteSession": {Verb: "Delete", Resource: "Session", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/sessions/{sessionIdentifier}/"}, + "GetAgentMemory": {Verb: "Get", Resource: "AgentMemory", OutputListKey: "memoryContents", OutputItemKey: "", Method: "GET", URI: "/agents/{agentId}/agentAliases/{agentAliasId}/memories"}, + "GetDocumentContent": {Verb: "Get", Resource: "DocumentContent", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/knowledgebases/{knowledgeBaseId}/datasources/{dataSourceId}/documents/{documentId}/content"}, + "GetExecutionFlowSnapshot": {Verb: "Get", Resource: "ExecutionFlowSnapshot", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/flows/{flowIdentifier}/aliases/{flowAliasIdentifier}/executions/{executionIdentifier}/flowsnapshot"}, + "GetFlowExecution": {Verb: "Get", Resource: "FlowExecution", OutputListKey: "errors", OutputItemKey: "", Method: "GET", URI: "/flows/{flowIdentifier}/aliases/{flowAliasIdentifier}/executions/{executionIdentifier}"}, + "GetIngestedDocumentAcl": {Verb: "Get", Resource: "IngestedDocumentAcl", OutputListKey: "", OutputItemKey: "documentAcl", Method: "POST", URI: "/knowledgebases/{knowledgeBaseId}/datasources/{dataSourceId}/get-ingested-document-acl"}, + "GetInvocationStep": {Verb: "Get", Resource: "InvocationStep", OutputListKey: "", OutputItemKey: "invocationStep", Method: "POST", URI: "/sessions/{sessionIdentifier}/invocationSteps/{invocationStepId}"}, + "GetSession": {Verb: "Get", Resource: "Session", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/sessions/{sessionIdentifier}/"}, + "ListFlowExecutionEvents": {Verb: "List", Resource: "FlowExecutionEvent", OutputListKey: "flowExecutionEvents", OutputItemKey: "", Method: "GET", URI: "/flows/{flowIdentifier}/aliases/{flowAliasIdentifier}/executions/{executionIdentifier}/events"}, + "ListFlowExecutions": {Verb: "List", Resource: "FlowExecution", OutputListKey: "flowExecutionSummaries", OutputItemKey: "", Method: "GET", URI: "/flows/{flowIdentifier}/executions"}, + "ListInvocationSteps": {Verb: "List", Resource: "InvocationStep", OutputListKey: "invocationStepSummaries", OutputItemKey: "", Method: "POST", URI: "/sessions/{sessionIdentifier}/invocationSteps/"}, + "ListInvocations": {Verb: "List", Resource: "Invocation", OutputListKey: "invocationSummaries", OutputItemKey: "", Method: "POST", URI: "/sessions/{sessionIdentifier}/invocations/"}, + "ListSessions": {Verb: "List", Resource: "Session", OutputListKey: "sessionSummaries", OutputItemKey: "", Method: "POST", URI: "/sessions/"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/tags/{resourceArn}"}, + "PutInvocationStep": {Verb: "Update", Resource: "InvocationStep", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/sessions/{sessionIdentifier}/invocationSteps/"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/tags/{resourceArn}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/tags/{resourceArn}"}, + "UpdateSession": {Verb: "Update", Resource: "Session", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/sessions/{sessionIdentifier}/"}, + }) + crud.Register("bedrockdataautomation", map[string]crud.OpMeta{ + "CreateBlueprint": {Verb: "Create", Resource: "Blueprint", OutputListKey: "", OutputItemKey: "blueprint", Method: "PUT", URI: "/blueprints/"}, + "CreateBlueprintVersion": {Verb: "Create", Resource: "BlueprintVersion", OutputListKey: "", OutputItemKey: "blueprint", Method: "POST", URI: "/blueprints/{blueprintArn}/versions/"}, + "CreateDataAutomationLibrary": {Verb: "Create", Resource: "DataAutomationLibrary", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/data-automation-libraries/"}, + "CreateDataAutomationProject": {Verb: "Create", Resource: "DataAutomationProject", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/data-automation-projects/"}, + "DeleteBlueprint": {Verb: "Delete", Resource: "Blueprint", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/blueprints/{blueprintArn}/"}, + "DeleteDataAutomationLibrary": {Verb: "Delete", Resource: "DataAutomationLibrary", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/data-automation-libraries/{libraryArn}/"}, + "DeleteDataAutomationProject": {Verb: "Delete", Resource: "DataAutomationProject", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/data-automation-projects/{projectArn}/"}, + "GetBlueprint": {Verb: "Get", Resource: "Blueprint", OutputListKey: "", OutputItemKey: "blueprint", Method: "POST", URI: "/blueprints/{blueprintArn}/"}, + "GetBlueprintOptimizationStatus": {Verb: "Get", Resource: "BlueprintOptimizationStatu", OutputListKey: "", OutputItemKey: "outputConfiguration", Method: "POST", URI: "/getBlueprintOptimizationStatus/{invocationArn}"}, + "GetDataAutomationLibrary": {Verb: "Get", Resource: "DataAutomationLibrary", OutputListKey: "", OutputItemKey: "library", Method: "POST", URI: "/data-automation-libraries/{libraryArn}/"}, + "GetDataAutomationLibraryEntity": {Verb: "Get", Resource: "DataAutomationLibraryEntity", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/data-automation-libraries/{libraryArn}/entityType/{entityType}/entities/{entityId}"}, + "GetDataAutomationLibraryIngestionJob": {Verb: "Get", Resource: "DataAutomationLibraryIngestionJob", OutputListKey: "", OutputItemKey: "job", Method: "POST", URI: "/data-automation-libraries/{libraryArn}/library-ingestion-jobs/{jobArn}"}, + "GetDataAutomationProject": {Verb: "Get", Resource: "DataAutomationProject", OutputListKey: "", OutputItemKey: "project", Method: "POST", URI: "/data-automation-projects/{projectArn}/"}, + "ListBlueprints": {Verb: "List", Resource: "Blueprint", OutputListKey: "blueprints", OutputItemKey: "", Method: "POST", URI: "/blueprints/"}, + "ListDataAutomationLibraries": {Verb: "List", Resource: "DataAutomationLibrary", OutputListKey: "libraries", OutputItemKey: "", Method: "POST", URI: "/data-automation-libraries/"}, + "ListDataAutomationLibraryEntities": {Verb: "List", Resource: "DataAutomationLibraryEntity", OutputListKey: "entities", OutputItemKey: "", Method: "POST", URI: "/data-automation-libraries/{libraryArn}/entityType/{entityType}/entities/"}, + "ListDataAutomationLibraryIngestionJobs": {Verb: "List", Resource: "DataAutomationLibraryIngestionJob", OutputListKey: "jobs", OutputItemKey: "", Method: "POST", URI: "/data-automation-libraries/{libraryArn}/library-ingestion-jobs/"}, + "ListDataAutomationProjects": {Verb: "List", Resource: "DataAutomationProject", OutputListKey: "projects", OutputItemKey: "", Method: "POST", URI: "/data-automation-projects/"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "tags", OutputItemKey: "", Method: "POST", URI: "/listTagsForResource"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/tagResource"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/untagResource"}, + "UpdateBlueprint": {Verb: "Update", Resource: "Blueprint", OutputListKey: "", OutputItemKey: "blueprint", Method: "PUT", URI: "/blueprints/{blueprintArn}/"}, + "UpdateDataAutomationLibrary": {Verb: "Update", Resource: "DataAutomationLibrary", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/data-automation-libraries/{libraryArn}/"}, + "UpdateDataAutomationProject": {Verb: "Update", Resource: "DataAutomationProject", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/data-automation-projects/{projectArn}/"}, + }) crud.Register("bedrockdataautomationruntime", map[string]crud.OpMeta{ "GetDataAutomationStatus": {Verb: "Get", Resource: "DataAutomationStatu", OutputListKey: "", OutputItemKey: "outputConfiguration"}, "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "tags", OutputItemKey: ""}, "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: ""}, "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: ""}, }) + crud.Register("bedrockruntime", map[string]crud.OpMeta{ + "GetAsyncInvoke": {Verb: "Get", Resource: "AsyncInvoke", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/async-invoke/{invocationArn}"}, + "ListAsyncInvokes": {Verb: "List", Resource: "AsyncInvoke", OutputListKey: "asyncInvokeSummaries", OutputItemKey: "", Method: "GET", URI: "/async-invoke"}, + }) crud.Register("cloudtrail", map[string]crud.OpMeta{ "CreateChannel": {Verb: "Create", Resource: "Channel", OutputListKey: "Destinations", OutputItemKey: ""}, "CreateDashboard": {Verb: "Create", Resource: "Dashboard", OutputListKey: "TagsList", OutputItemKey: "RefreshSchedule"}, @@ -312,6 +1118,51 @@ func init() { "UpdateLookupTable": {Verb: "Update", Resource: "LookupTable", OutputListKey: "", OutputItemKey: ""}, "UpdateScheduledQuery": {Verb: "Update", Resource: "ScheduledQuery", OutputListKey: "logGroupIdentifiers", OutputItemKey: "destinationConfiguration"}, }) + crud.Register("codeartifact", map[string]crud.OpMeta{ + "CreateDomain": {Verb: "Create", Resource: "Domain", OutputListKey: "", OutputItemKey: "domain", Method: "POST", URI: "/v1/domain"}, + "CreatePackageGroup": {Verb: "Create", Resource: "PackageGroup", OutputListKey: "", OutputItemKey: "packageGroup", Method: "POST", URI: "/v1/package-group"}, + "CreateRepository": {Verb: "Create", Resource: "Repository", OutputListKey: "", OutputItemKey: "repository", Method: "POST", URI: "/v1/repository"}, + "DeleteDomain": {Verb: "Delete", Resource: "Domain", OutputListKey: "", OutputItemKey: "domain", Method: "DELETE", URI: "/v1/domain"}, + "DeleteDomainPermissionsPolicy": {Verb: "Delete", Resource: "DomainPermissionsPolicy", OutputListKey: "", OutputItemKey: "policy", Method: "DELETE", URI: "/v1/domain/permissions/policy"}, + "DeletePackage": {Verb: "Delete", Resource: "Package", OutputListKey: "", OutputItemKey: "deletedPackage", Method: "DELETE", URI: "/v1/package"}, + "DeletePackageGroup": {Verb: "Delete", Resource: "PackageGroup", OutputListKey: "", OutputItemKey: "packageGroup", Method: "DELETE", URI: "/v1/package-group"}, + "DeletePackageVersions": {Verb: "Delete", Resource: "PackageVersion", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/package/versions/delete"}, + "DeleteRepository": {Verb: "Delete", Resource: "Repository", OutputListKey: "", OutputItemKey: "repository", Method: "DELETE", URI: "/v1/repository"}, + "DeleteRepositoryPermissionsPolicy": {Verb: "Delete", Resource: "RepositoryPermissionsPolicy", OutputListKey: "", OutputItemKey: "policy", Method: "DELETE", URI: "/v1/repository/permissions/policies"}, + "DescribeDomain": {Verb: "Get", Resource: "Domain", OutputListKey: "", OutputItemKey: "domain", Method: "GET", URI: "/v1/domain"}, + "DescribePackage": {Verb: "Get", Resource: "Package", OutputListKey: "", OutputItemKey: "package", Method: "GET", URI: "/v1/package"}, + "DescribePackageGroup": {Verb: "Get", Resource: "PackageGroup", OutputListKey: "", OutputItemKey: "packageGroup", Method: "GET", URI: "/v1/package-group"}, + "DescribePackageVersion": {Verb: "Get", Resource: "PackageVersion", OutputListKey: "", OutputItemKey: "packageVersion", Method: "GET", URI: "/v1/package/version"}, + "DescribeRepository": {Verb: "Get", Resource: "Repository", OutputListKey: "", OutputItemKey: "repository", Method: "GET", URI: "/v1/repository"}, + "GetAssociatedPackageGroup": {Verb: "Get", Resource: "AssociatedPackageGroup", OutputListKey: "", OutputItemKey: "packageGroup", Method: "GET", URI: "/v1/get-associated-package-group"}, + "GetAuthorizationToken": {Verb: "Get", Resource: "AuthorizationToken", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/authorization-token"}, + "GetDomainPermissionsPolicy": {Verb: "Get", Resource: "DomainPermissionsPolicy", OutputListKey: "", OutputItemKey: "policy", Method: "GET", URI: "/v1/domain/permissions/policy"}, + "GetPackageVersionAsset": {Verb: "Get", Resource: "PackageVersionAsset", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v1/package/version/asset"}, + "GetPackageVersionReadme": {Verb: "Get", Resource: "PackageVersionReadme", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v1/package/version/readme"}, + "GetRepositoryEndpoint": {Verb: "Get", Resource: "RepositoryEndpoint", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v1/repository/endpoint"}, + "GetRepositoryPermissionsPolicy": {Verb: "Get", Resource: "RepositoryPermissionsPolicy", OutputListKey: "", OutputItemKey: "policy", Method: "GET", URI: "/v1/repository/permissions/policy"}, + "ListAllowedRepositoriesForGroup": {Verb: "List", Resource: "AllowedRepositoriesForGroup", OutputListKey: "allowedRepositories", OutputItemKey: "", Method: "GET", URI: "/v1/package-group-allowed-repositories"}, + "ListAssociatedPackages": {Verb: "List", Resource: "AssociatedPackage", OutputListKey: "packages", OutputItemKey: "", Method: "GET", URI: "/v1/list-associated-packages"}, + "ListDomains": {Verb: "List", Resource: "Domain", OutputListKey: "domains", OutputItemKey: "", Method: "POST", URI: "/v1/domains"}, + "ListPackageGroups": {Verb: "List", Resource: "PackageGroup", OutputListKey: "packageGroups", OutputItemKey: "", Method: "POST", URI: "/v1/package-groups"}, + "ListPackageVersionAssets": {Verb: "List", Resource: "PackageVersionAsset", OutputListKey: "assets", OutputItemKey: "", Method: "POST", URI: "/v1/package/version/assets"}, + "ListPackageVersionDependencies": {Verb: "List", Resource: "PackageVersionDependency", OutputListKey: "dependencies", OutputItemKey: "", Method: "POST", URI: "/v1/package/version/dependencies"}, + "ListPackageVersions": {Verb: "List", Resource: "PackageVersion", OutputListKey: "versions", OutputItemKey: "", Method: "POST", URI: "/v1/package/versions"}, + "ListPackages": {Verb: "List", Resource: "Package", OutputListKey: "packages", OutputItemKey: "", Method: "POST", URI: "/v1/packages"}, + "ListRepositories": {Verb: "List", Resource: "Repository", OutputListKey: "repositories", OutputItemKey: "", Method: "POST", URI: "/v1/repositories"}, + "ListRepositoriesInDomain": {Verb: "List", Resource: "RepositoriesInDomain", OutputListKey: "repositories", OutputItemKey: "", Method: "POST", URI: "/v1/domain/repositories"}, + "ListSubPackageGroups": {Verb: "List", Resource: "SubPackageGroup", OutputListKey: "packageGroups", OutputItemKey: "", Method: "POST", URI: "/v1/package-groups/sub-groups"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "tags", OutputItemKey: "", Method: "POST", URI: "/v1/tags"}, + "PutDomainPermissionsPolicy": {Verb: "Update", Resource: "DomainPermissionsPolicy", OutputListKey: "", OutputItemKey: "policy", Method: "PUT", URI: "/v1/domain/permissions/policy"}, + "PutPackageOriginConfiguration": {Verb: "Update", Resource: "PackageOriginConfiguration", OutputListKey: "", OutputItemKey: "originConfiguration", Method: "POST", URI: "/v1/package"}, + "PutRepositoryPermissionsPolicy": {Verb: "Update", Resource: "RepositoryPermissionsPolicy", OutputListKey: "", OutputItemKey: "policy", Method: "PUT", URI: "/v1/repository/permissions/policy"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/tag"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/untag"}, + "UpdatePackageGroup": {Verb: "Update", Resource: "PackageGroup", OutputListKey: "", OutputItemKey: "packageGroup", Method: "PUT", URI: "/v1/package-group"}, + "UpdatePackageGroupOriginConfiguration": {Verb: "Update", Resource: "PackageGroupOriginConfiguration", OutputListKey: "", OutputItemKey: "packageGroup", Method: "PUT", URI: "/v1/package-group-origin-configuration"}, + "UpdatePackageVersionsStatus": {Verb: "Update", Resource: "PackageVersionsStatu", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/package/versions/update_status"}, + "UpdateRepository": {Verb: "Update", Resource: "Repository", OutputListKey: "", OutputItemKey: "repository", Method: "PUT", URI: "/v1/repository"}, + }) crud.Register("codebuild", map[string]crud.OpMeta{ "BatchGetBuildBatches": {Verb: "List", Resource: "BuildBatche", OutputListKey: "buildBatches", OutputItemKey: ""}, "BatchGetBuilds": {Verb: "List", Resource: "Build", OutputListKey: "builds", OutputItemKey: ""}, @@ -468,6 +1319,54 @@ func init() { "UpdateApplication": {Verb: "Update", Resource: "Application", OutputListKey: "", OutputItemKey: ""}, "UpdateDeploymentGroup": {Verb: "Update", Resource: "DeploymentGroup", OutputListKey: "hooksNotCleanedUp", OutputItemKey: ""}, }) + crud.Register("codeguruprofiler", map[string]crud.OpMeta{ + "BatchGetFrameMetricData": {Verb: "List", Resource: "FrameMetricData", OutputListKey: "endTimes", OutputItemKey: "", Method: "POST", URI: "/profilingGroups/{profilingGroupName}/frames/-/metrics"}, + "CreateProfilingGroup": {Verb: "Create", Resource: "ProfilingGroup", OutputListKey: "", OutputItemKey: "profilingGroup", Method: "POST", URI: "/profilingGroups"}, + "DeleteProfilingGroup": {Verb: "Delete", Resource: "ProfilingGroup", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/profilingGroups/{profilingGroupName}"}, + "DescribeProfilingGroup": {Verb: "Get", Resource: "ProfilingGroup", OutputListKey: "", OutputItemKey: "profilingGroup", Method: "GET", URI: "/profilingGroups/{profilingGroupName}"}, + "GetFindingsReportAccountSummary": {Verb: "Get", Resource: "FindingsReportAccountSummary", OutputListKey: "reportSummaries", OutputItemKey: "", Method: "GET", URI: "/internal/findingsReports"}, + "GetNotificationConfiguration": {Verb: "Get", Resource: "NotificationConfiguration", OutputListKey: "", OutputItemKey: "notificationConfiguration", Method: "GET", URI: "/profilingGroups/{profilingGroupName}/notificationConfiguration"}, + "GetPolicy": {Verb: "Get", Resource: "Policy", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/profilingGroups/{profilingGroupName}/policy"}, + "GetProfile": {Verb: "Get", Resource: "Profile", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/profilingGroups/{profilingGroupName}/profile"}, + "GetRecommendations": {Verb: "Get", Resource: "Recommendation", OutputListKey: "anomalies", OutputItemKey: "", Method: "GET", URI: "/internal/profilingGroups/{profilingGroupName}/recommendations"}, + "ListFindingsReports": {Verb: "List", Resource: "FindingsReport", OutputListKey: "findingsReportSummaries", OutputItemKey: "", Method: "GET", URI: "/internal/profilingGroups/{profilingGroupName}/findingsReports"}, + "ListProfileTimes": {Verb: "List", Resource: "ProfileTime", OutputListKey: "profileTimes", OutputItemKey: "", Method: "GET", URI: "/profilingGroups/{profilingGroupName}/profileTimes"}, + "ListProfilingGroups": {Verb: "List", Resource: "ProfilingGroup", OutputListKey: "profilingGroupNames", OutputItemKey: "", Method: "GET", URI: "/profilingGroups"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/tags/{resourceArn}"}, + "PutPermission": {Verb: "Update", Resource: "Permission", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/profilingGroups/{profilingGroupName}/policy/{actionGroup}"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/tags/{resourceArn}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/tags/{resourceArn}"}, + "UpdateProfilingGroup": {Verb: "Update", Resource: "ProfilingGroup", OutputListKey: "", OutputItemKey: "profilingGroup", Method: "PUT", URI: "/profilingGroups/{profilingGroupName}"}, + }) + crud.Register("codegurureviewer", map[string]crud.OpMeta{ + "CreateCodeReview": {Verb: "Create", Resource: "CodeReview", OutputListKey: "", OutputItemKey: "CodeReview", Method: "POST", URI: "/codereviews"}, + "DescribeCodeReview": {Verb: "Get", Resource: "CodeReview", OutputListKey: "", OutputItemKey: "CodeReview", Method: "GET", URI: "/codereviews/{CodeReviewArn}"}, + "DescribeRecommendationFeedback": {Verb: "Get", Resource: "RecommendationFeedback", OutputListKey: "", OutputItemKey: "RecommendationFeedback", Method: "GET", URI: "/feedback/{CodeReviewArn}"}, + "DescribeRepositoryAssociation": {Verb: "Get", Resource: "RepositoryAssociation", OutputListKey: "", OutputItemKey: "RepositoryAssociation", Method: "GET", URI: "/associations/{AssociationArn}"}, + "ListCodeReviews": {Verb: "List", Resource: "CodeReview", OutputListKey: "CodeReviewSummaries", OutputItemKey: "", Method: "GET", URI: "/codereviews"}, + "ListRecommendationFeedback": {Verb: "List", Resource: "RecommendationFeedback", OutputListKey: "RecommendationFeedbackSummaries", OutputItemKey: "", Method: "GET", URI: "/feedback/{CodeReviewArn}/RecommendationFeedback"}, + "ListRecommendations": {Verb: "List", Resource: "Recommendation", OutputListKey: "RecommendationSummaries", OutputItemKey: "", Method: "GET", URI: "/codereviews/{CodeReviewArn}/Recommendations"}, + "ListRepositoryAssociations": {Verb: "List", Resource: "RepositoryAssociation", OutputListKey: "RepositoryAssociationSummaries", OutputItemKey: "", Method: "GET", URI: "/associations"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/tags/{resourceArn}"}, + "PutRecommendationFeedback": {Verb: "Update", Resource: "RecommendationFeedback", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/feedback"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/tags/{resourceArn}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/tags/{resourceArn}"}, + }) + crud.Register("codegurusecurity", map[string]crud.OpMeta{ + "BatchGetFindings": {Verb: "List", Resource: "Finding", OutputListKey: "failedFindings", OutputItemKey: "", Method: "POST", URI: "/batchGetFindings"}, + "CreateScan": {Verb: "Create", Resource: "Scan", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/scans"}, + "CreateUploadUrl": {Verb: "Create", Resource: "UploadUrl", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/uploadUrl"}, + "GetAccountConfiguration": {Verb: "Get", Resource: "AccountConfiguration", OutputListKey: "", OutputItemKey: "encryptionConfig", Method: "GET", URI: "/accountConfiguration/get"}, + "GetFindings": {Verb: "Get", Resource: "Finding", OutputListKey: "findings", OutputItemKey: "", Method: "GET", URI: "/findings/{scanName}"}, + "GetMetricsSummary": {Verb: "Get", Resource: "MetricsSummary", OutputListKey: "", OutputItemKey: "metricsSummary", Method: "GET", URI: "/metrics/summary"}, + "GetScan": {Verb: "Get", Resource: "Scan", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/scans/{scanName}"}, + "ListFindingsMetrics": {Verb: "List", Resource: "FindingsMetric", OutputListKey: "findingsMetrics", OutputItemKey: "", Method: "GET", URI: "/metrics/findings"}, + "ListScans": {Verb: "List", Resource: "Scan", OutputListKey: "summaries", OutputItemKey: "", Method: "GET", URI: "/scans"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/tags/{resourceArn}"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/tags/{resourceArn}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/tags/{resourceArn}"}, + "UpdateAccountConfiguration": {Verb: "Update", Resource: "AccountConfiguration", OutputListKey: "", OutputItemKey: "encryptionConfig", Method: "PUT", URI: "/updateAccountConfiguration"}, + }) crud.Register("codepipeline", map[string]crud.OpMeta{ "CreateCustomActionType": {Verb: "Create", Resource: "CustomActionType", OutputListKey: "tags", OutputItemKey: "actionType"}, "CreatePipeline": {Verb: "Create", Resource: "Pipeline", OutputListKey: "tags", OutputItemKey: "pipeline"}, @@ -790,6 +1689,34 @@ func init() { "UpdateCostAllocationTagsStatus": {Verb: "Update", Resource: "CostAllocationTagsStatu", OutputListKey: "Errors", OutputItemKey: ""}, "UpdateCostCategoryDefinition": {Verb: "Update", Resource: "CostCategoryDefinition", OutputListKey: "", OutputItemKey: ""}, }) + crud.Register("devopsguru", map[string]crud.OpMeta{ + "DeleteInsight": {Verb: "Delete", Resource: "Insight", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/insights/{Id}"}, + "DescribeAccountHealth": {Verb: "Get", Resource: "AccountHealth", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/accounts/health"}, + "DescribeAccountOverview": {Verb: "Get", Resource: "AccountOverview", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/accounts/overview"}, + "DescribeAnomaly": {Verb: "Get", Resource: "Anomaly", OutputListKey: "", OutputItemKey: "ProactiveAnomaly", Method: "GET", URI: "/anomalies/{Id}"}, + "DescribeEventSourcesConfig": {Verb: "Get", Resource: "EventSourcesConfig", OutputListKey: "", OutputItemKey: "EventSources", Method: "POST", URI: "/event-sources"}, + "DescribeFeedback": {Verb: "Get", Resource: "Feedback", OutputListKey: "", OutputItemKey: "InsightFeedback", Method: "POST", URI: "/feedback"}, + "DescribeInsight": {Verb: "Get", Resource: "Insight", OutputListKey: "", OutputItemKey: "ProactiveInsight", Method: "GET", URI: "/insights/{Id}"}, + "DescribeOrganizationHealth": {Verb: "Get", Resource: "OrganizationHealth", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/organization/health"}, + "DescribeOrganizationOverview": {Verb: "Get", Resource: "OrganizationOverview", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/organization/overview"}, + "DescribeOrganizationResourceCollectionHealth": {Verb: "Get", Resource: "OrganizationResourceCollectionHealth", OutputListKey: "Account", OutputItemKey: "", Method: "POST", URI: "/organization/health/resource-collection"}, + "DescribeResourceCollectionHealth": {Verb: "Get", Resource: "ResourceCollectionHealth", OutputListKey: "CloudFormation", OutputItemKey: "", Method: "GET", URI: "/accounts/health/resource-collection/{ResourceCollectionType}"}, + "DescribeServiceIntegration": {Verb: "Get", Resource: "ServiceIntegration", OutputListKey: "", OutputItemKey: "ServiceIntegration", Method: "GET", URI: "/service-integrations"}, + "GetCostEstimation": {Verb: "Get", Resource: "CostEstimation", OutputListKey: "Costs", OutputItemKey: "ResourceCollection", Method: "GET", URI: "/cost-estimation"}, + "GetResourceCollection": {Verb: "Get", Resource: "ResourceCollection", OutputListKey: "", OutputItemKey: "ResourceCollection", Method: "GET", URI: "/resource-collections/{ResourceCollectionType}"}, + "ListAnomaliesForInsight": {Verb: "List", Resource: "AnomaliesForInsight", OutputListKey: "ProactiveAnomalies", OutputItemKey: "", Method: "POST", URI: "/anomalies/insight/{InsightId}"}, + "ListAnomalousLogGroups": {Verb: "List", Resource: "AnomalousLogGroup", OutputListKey: "AnomalousLogGroups", OutputItemKey: "", Method: "POST", URI: "/list-log-anomalies"}, + "ListEvents": {Verb: "List", Resource: "Event", OutputListKey: "Events", OutputItemKey: "", Method: "POST", URI: "/events"}, + "ListInsights": {Verb: "List", Resource: "Insight", OutputListKey: "ProactiveInsights", OutputItemKey: "", Method: "POST", URI: "/insights"}, + "ListMonitoredResources": {Verb: "List", Resource: "MonitoredResource", OutputListKey: "MonitoredResourceIdentifiers", OutputItemKey: "", Method: "POST", URI: "/monitoredResources"}, + "ListNotificationChannels": {Verb: "List", Resource: "NotificationChannel", OutputListKey: "Channels", OutputItemKey: "", Method: "POST", URI: "/channels"}, + "ListOrganizationInsights": {Verb: "List", Resource: "OrganizationInsight", OutputListKey: "ProactiveInsights", OutputItemKey: "", Method: "POST", URI: "/organization/insights"}, + "ListRecommendations": {Verb: "List", Resource: "Recommendation", OutputListKey: "Recommendations", OutputItemKey: "", Method: "POST", URI: "/recommendations"}, + "PutFeedback": {Verb: "Update", Resource: "Feedback", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/feedback"}, + "UpdateEventSourcesConfig": {Verb: "Update", Resource: "EventSourcesConfig", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/event-sources"}, + "UpdateResourceCollection": {Verb: "Update", Resource: "ResourceCollection", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/resource-collections"}, + "UpdateServiceIntegration": {Verb: "Update", Resource: "ServiceIntegration", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/service-integrations"}, + }) crud.Register("dynamodb", map[string]crud.OpMeta{ "BatchGetItem": {Verb: "List", Resource: "Item", OutputListKey: "ConsumedCapacity", OutputItemKey: ""}, "CreateBackup": {Verb: "Create", Resource: "Backup", OutputListKey: "", OutputItemKey: "BackupDetails"}, @@ -841,6 +1768,12 @@ func init() { "GetShardIterator": {Verb: "Get", Resource: "ShardIterator", OutputListKey: "", OutputItemKey: ""}, "ListStreams": {Verb: "List", Resource: "Stream", OutputListKey: "Streams", OutputItemKey: ""}, }) + crud.Register("ebs", map[string]crud.OpMeta{ + "GetSnapshotBlock": {Verb: "Get", Resource: "SnapshotBlock", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/snapshots/{SnapshotId}/blocks/{BlockIndex}"}, + "ListChangedBlocks": {Verb: "List", Resource: "ChangedBlock", OutputListKey: "ChangedBlocks", OutputItemKey: "", Method: "GET", URI: "/snapshots/{SecondSnapshotId}/changedblocks"}, + "ListSnapshotBlocks": {Verb: "List", Resource: "SnapshotBlock", OutputListKey: "Blocks", OutputItemKey: "", Method: "GET", URI: "/snapshots/{SnapshotId}/blocks"}, + "PutSnapshotBlock": {Verb: "Update", Resource: "SnapshotBlock", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/snapshots/{SnapshotId}/blocks/{BlockIndex}"}, + }) crud.Register("ecr", map[string]crud.OpMeta{ "BatchGetImage": {Verb: "List", Resource: "Image", OutputListKey: "failures", OutputItemKey: ""}, "BatchGetRepositoryScanningConfiguration": {Verb: "List", Resource: "RepositoryScanningConfiguration", OutputListKey: "failures", OutputItemKey: ""}, @@ -961,6 +1894,139 @@ func init() { "UpdateTaskProtection": {Verb: "Update", Resource: "TaskProtection", OutputListKey: "failures", OutputItemKey: ""}, "UpdateTaskSet": {Verb: "Update", Resource: "TaskSet", OutputListKey: "", OutputItemKey: "taskSet"}, }) + crud.Register("efs", map[string]crud.OpMeta{ + "CreateAccessPoint": {Verb: "Create", Resource: "AccessPoint", OutputListKey: "Tags", OutputItemKey: "PosixUser", Method: "POST", URI: "/2015-02-01/access-points"}, + "CreateFileSystem": {Verb: "Create", Resource: "FileSystem", OutputListKey: "Tags", OutputItemKey: "FileSystemProtection", Method: "POST", URI: "/2015-02-01/file-systems"}, + "CreateMountTarget": {Verb: "Create", Resource: "MountTarget", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/2015-02-01/mount-targets"}, + "CreateReplicationConfiguration": {Verb: "Create", Resource: "ReplicationConfiguration", OutputListKey: "Destinations", OutputItemKey: "", Method: "POST", URI: "/2015-02-01/file-systems/{SourceFileSystemId}/replication-configuration"}, + "CreateTags": {Verb: "Create", Resource: "Tag", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/2015-02-01/create-tags/{FileSystemId}"}, + "DeleteAccessPoint": {Verb: "Delete", Resource: "AccessPoint", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2015-02-01/access-points/{AccessPointId}"}, + "DeleteFileSystem": {Verb: "Delete", Resource: "FileSystem", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2015-02-01/file-systems/{FileSystemId}"}, + "DeleteFileSystemPolicy": {Verb: "Delete", Resource: "FileSystemPolicy", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2015-02-01/file-systems/{FileSystemId}/policy"}, + "DeleteMountTarget": {Verb: "Delete", Resource: "MountTarget", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2015-02-01/mount-targets/{MountTargetId}"}, + "DeleteReplicationConfiguration": {Verb: "Delete", Resource: "ReplicationConfiguration", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2015-02-01/file-systems/{SourceFileSystemId}/replication-configuration"}, + "DeleteTags": {Verb: "Delete", Resource: "Tag", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/2015-02-01/delete-tags/{FileSystemId}"}, + "DescribeAccessPoints": {Verb: "Get", Resource: "AccessPoint", OutputListKey: "AccessPoints", OutputItemKey: "", Method: "GET", URI: "/2015-02-01/access-points"}, + "DescribeAccountPreferences": {Verb: "Get", Resource: "AccountPreference", OutputListKey: "", OutputItemKey: "ResourceIdPreference", Method: "GET", URI: "/2015-02-01/account-preferences"}, + "DescribeBackupPolicy": {Verb: "Get", Resource: "BackupPolicy", OutputListKey: "", OutputItemKey: "BackupPolicy", Method: "GET", URI: "/2015-02-01/file-systems/{FileSystemId}/backup-policy"}, + "DescribeFileSystemPolicy": {Verb: "Get", Resource: "FileSystemPolicy", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/2015-02-01/file-systems/{FileSystemId}/policy"}, + "DescribeFileSystems": {Verb: "Get", Resource: "FileSystem", OutputListKey: "FileSystems", OutputItemKey: "", Method: "GET", URI: "/2015-02-01/file-systems"}, + "DescribeLifecycleConfiguration": {Verb: "Get", Resource: "LifecycleConfiguration", OutputListKey: "LifecyclePolicies", OutputItemKey: "", Method: "GET", URI: "/2015-02-01/file-systems/{FileSystemId}/lifecycle-configuration"}, + "DescribeMountTargetSecurityGroups": {Verb: "Get", Resource: "MountTargetSecurityGroup", OutputListKey: "SecurityGroups", OutputItemKey: "", Method: "GET", URI: "/2015-02-01/mount-targets/{MountTargetId}/security-groups"}, + "DescribeMountTargets": {Verb: "Get", Resource: "MountTarget", OutputListKey: "MountTargets", OutputItemKey: "", Method: "GET", URI: "/2015-02-01/mount-targets"}, + "DescribeReplicationConfigurations": {Verb: "Get", Resource: "ReplicationConfiguration", OutputListKey: "Replications", OutputItemKey: "", Method: "GET", URI: "/2015-02-01/file-systems/replication-configurations"}, + "DescribeTags": {Verb: "Get", Resource: "Tag", OutputListKey: "Tags", OutputItemKey: "", Method: "GET", URI: "/2015-02-01/tags/{FileSystemId}"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "Tags", OutputItemKey: "", Method: "GET", URI: "/2015-02-01/resource-tags/{ResourceId}"}, + "ModifyMountTargetSecurityGroups": {Verb: "Update", Resource: "MountTargetSecurityGroup", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/2015-02-01/mount-targets/{MountTargetId}/security-groups"}, + "PutAccountPreferences": {Verb: "Update", Resource: "AccountPreference", OutputListKey: "", OutputItemKey: "ResourceIdPreference", Method: "PUT", URI: "/2015-02-01/account-preferences"}, + "PutBackupPolicy": {Verb: "Update", Resource: "BackupPolicy", OutputListKey: "", OutputItemKey: "BackupPolicy", Method: "PUT", URI: "/2015-02-01/file-systems/{FileSystemId}/backup-policy"}, + "PutFileSystemPolicy": {Verb: "Update", Resource: "FileSystemPolicy", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/2015-02-01/file-systems/{FileSystemId}/policy"}, + "PutLifecycleConfiguration": {Verb: "Update", Resource: "LifecycleConfiguration", OutputListKey: "LifecyclePolicies", OutputItemKey: "", Method: "PUT", URI: "/2015-02-01/file-systems/{FileSystemId}/lifecycle-configuration"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/2015-02-01/resource-tags/{ResourceId}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2015-02-01/resource-tags/{ResourceId}"}, + "UpdateFileSystem": {Verb: "Update", Resource: "FileSystem", OutputListKey: "Tags", OutputItemKey: "FileSystemProtection", Method: "PUT", URI: "/2015-02-01/file-systems/{FileSystemId}"}, + "UpdateFileSystemProtection": {Verb: "Update", Resource: "FileSystemProtection", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/2015-02-01/file-systems/{FileSystemId}/protection"}, + }) + crud.Register("eks", map[string]crud.OpMeta{ + "CreateAccessEntry": {Verb: "Create", Resource: "AccessEntry", OutputListKey: "", OutputItemKey: "accessEntry", Method: "POST", URI: "/clusters/{clusterName}/access-entries"}, + "CreateAddon": {Verb: "Create", Resource: "Addon", OutputListKey: "", OutputItemKey: "addon", Method: "POST", URI: "/clusters/{clusterName}/addons"}, + "CreateCapability": {Verb: "Create", Resource: "Capability", OutputListKey: "", OutputItemKey: "capability", Method: "POST", URI: "/clusters/{clusterName}/capabilities"}, + "CreateCluster": {Verb: "Create", Resource: "Cluster", OutputListKey: "", OutputItemKey: "cluster", Method: "POST", URI: "/clusters"}, + "CreateEksAnywhereSubscription": {Verb: "Create", Resource: "EksAnywhereSubscription", OutputListKey: "", OutputItemKey: "subscription", Method: "POST", URI: "/eks-anywhere-subscriptions"}, + "CreateFargateProfile": {Verb: "Create", Resource: "FargateProfile", OutputListKey: "", OutputItemKey: "fargateProfile", Method: "POST", URI: "/clusters/{clusterName}/fargate-profiles"}, + "CreateNodegroup": {Verb: "Create", Resource: "Nodegroup", OutputListKey: "", OutputItemKey: "nodegroup", Method: "POST", URI: "/clusters/{clusterName}/node-groups"}, + "CreatePodIdentityAssociation": {Verb: "Create", Resource: "PodIdentityAssociation", OutputListKey: "", OutputItemKey: "association", Method: "POST", URI: "/clusters/{clusterName}/pod-identity-associations"}, + "DeleteAccessEntry": {Verb: "Delete", Resource: "AccessEntry", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/clusters/{clusterName}/access-entries/{principalArn}"}, + "DeleteAddon": {Verb: "Delete", Resource: "Addon", OutputListKey: "", OutputItemKey: "addon", Method: "DELETE", URI: "/clusters/{clusterName}/addons/{addonName}"}, + "DeleteCapability": {Verb: "Delete", Resource: "Capability", OutputListKey: "", OutputItemKey: "capability", Method: "DELETE", URI: "/clusters/{clusterName}/capabilities/{capabilityName}"}, + "DeleteCluster": {Verb: "Delete", Resource: "Cluster", OutputListKey: "", OutputItemKey: "cluster", Method: "DELETE", URI: "/clusters/{name}"}, + "DeleteEksAnywhereSubscription": {Verb: "Delete", Resource: "EksAnywhereSubscription", OutputListKey: "", OutputItemKey: "subscription", Method: "DELETE", URI: "/eks-anywhere-subscriptions/{id}"}, + "DeleteFargateProfile": {Verb: "Delete", Resource: "FargateProfile", OutputListKey: "", OutputItemKey: "fargateProfile", Method: "DELETE", URI: "/clusters/{clusterName}/fargate-profiles/{fargateProfileName}"}, + "DeleteNodegroup": {Verb: "Delete", Resource: "Nodegroup", OutputListKey: "", OutputItemKey: "nodegroup", Method: "DELETE", URI: "/clusters/{clusterName}/node-groups/{nodegroupName}"}, + "DeletePodIdentityAssociation": {Verb: "Delete", Resource: "PodIdentityAssociation", OutputListKey: "", OutputItemKey: "association", Method: "DELETE", URI: "/clusters/{clusterName}/pod-identity-associations/{associationId}"}, + "DeregisterCluster": {Verb: "Delete", Resource: "Cluster", OutputListKey: "", OutputItemKey: "cluster", Method: "DELETE", URI: "/cluster-registrations/{name}"}, + "DescribeAccessEntry": {Verb: "Get", Resource: "AccessEntry", OutputListKey: "", OutputItemKey: "accessEntry", Method: "GET", URI: "/clusters/{clusterName}/access-entries/{principalArn}"}, + "DescribeAddon": {Verb: "Get", Resource: "Addon", OutputListKey: "", OutputItemKey: "addon", Method: "GET", URI: "/clusters/{clusterName}/addons/{addonName}"}, + "DescribeAddonConfiguration": {Verb: "Get", Resource: "AddonConfiguration", OutputListKey: "podIdentityConfiguration", OutputItemKey: "", Method: "GET", URI: "/addons/configuration-schemas"}, + "DescribeAddonVersions": {Verb: "Get", Resource: "AddonVersion", OutputListKey: "addons", OutputItemKey: "", Method: "GET", URI: "/addons/supported-versions"}, + "DescribeCapability": {Verb: "Get", Resource: "Capability", OutputListKey: "", OutputItemKey: "capability", Method: "GET", URI: "/clusters/{clusterName}/capabilities/{capabilityName}"}, + "DescribeCluster": {Verb: "Get", Resource: "Cluster", OutputListKey: "", OutputItemKey: "cluster", Method: "GET", URI: "/clusters/{name}"}, + "DescribeClusterVersions": {Verb: "Get", Resource: "ClusterVersion", OutputListKey: "clusterVersions", OutputItemKey: "", Method: "GET", URI: "/cluster-versions"}, + "DescribeEksAnywhereSubscription": {Verb: "Get", Resource: "EksAnywhereSubscription", OutputListKey: "", OutputItemKey: "subscription", Method: "GET", URI: "/eks-anywhere-subscriptions/{id}"}, + "DescribeFargateProfile": {Verb: "Get", Resource: "FargateProfile", OutputListKey: "", OutputItemKey: "fargateProfile", Method: "GET", URI: "/clusters/{clusterName}/fargate-profiles/{fargateProfileName}"}, + "DescribeIdentityProviderConfig": {Verb: "Get", Resource: "IdentityProviderConfig", OutputListKey: "", OutputItemKey: "identityProviderConfig", Method: "POST", URI: "/clusters/{clusterName}/identity-provider-configs/describe"}, + "DescribeInsight": {Verb: "Get", Resource: "Insight", OutputListKey: "", OutputItemKey: "insight", Method: "GET", URI: "/clusters/{clusterName}/insights/{id}"}, + "DescribeInsightsRefresh": {Verb: "Get", Resource: "InsightsRefresh", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/clusters/{clusterName}/insights-refresh"}, + "DescribeNodegroup": {Verb: "Get", Resource: "Nodegroup", OutputListKey: "", OutputItemKey: "nodegroup", Method: "GET", URI: "/clusters/{clusterName}/node-groups/{nodegroupName}"}, + "DescribePodIdentityAssociation": {Verb: "Get", Resource: "PodIdentityAssociation", OutputListKey: "", OutputItemKey: "association", Method: "GET", URI: "/clusters/{clusterName}/pod-identity-associations/{associationId}"}, + "DescribeUpdate": {Verb: "Get", Resource: "Update", OutputListKey: "", OutputItemKey: "update", Method: "GET", URI: "/clusters/{name}/updates/{updateId}"}, + "ListAccessEntries": {Verb: "List", Resource: "AccessEntry", OutputListKey: "accessEntries", OutputItemKey: "", Method: "GET", URI: "/clusters/{clusterName}/access-entries"}, + "ListAccessPolicies": {Verb: "List", Resource: "AccessPolicy", OutputListKey: "accessPolicies", OutputItemKey: "", Method: "GET", URI: "/access-policies"}, + "ListAddons": {Verb: "List", Resource: "Addon", OutputListKey: "addons", OutputItemKey: "", Method: "GET", URI: "/clusters/{clusterName}/addons"}, + "ListAssociatedAccessPolicies": {Verb: "List", Resource: "AssociatedAccessPolicy", OutputListKey: "associatedAccessPolicies", OutputItemKey: "", Method: "GET", URI: "/clusters/{clusterName}/access-entries/{principalArn}/access-policies"}, + "ListCapabilities": {Verb: "List", Resource: "Capability", OutputListKey: "capabilities", OutputItemKey: "", Method: "GET", URI: "/clusters/{clusterName}/capabilities"}, + "ListClusters": {Verb: "List", Resource: "Cluster", OutputListKey: "clusters", OutputItemKey: "", Method: "GET", URI: "/clusters"}, + "ListEksAnywhereSubscriptions": {Verb: "List", Resource: "EksAnywhereSubscription", OutputListKey: "subscriptions", OutputItemKey: "", Method: "GET", URI: "/eks-anywhere-subscriptions"}, + "ListFargateProfiles": {Verb: "List", Resource: "FargateProfile", OutputListKey: "fargateProfileNames", OutputItemKey: "", Method: "GET", URI: "/clusters/{clusterName}/fargate-profiles"}, + "ListIdentityProviderConfigs": {Verb: "List", Resource: "IdentityProviderConfig", OutputListKey: "identityProviderConfigs", OutputItemKey: "", Method: "GET", URI: "/clusters/{clusterName}/identity-provider-configs"}, + "ListInsights": {Verb: "List", Resource: "Insight", OutputListKey: "insights", OutputItemKey: "", Method: "POST", URI: "/clusters/{clusterName}/insights"}, + "ListNodegroups": {Verb: "List", Resource: "Nodegroup", OutputListKey: "nodegroups", OutputItemKey: "", Method: "GET", URI: "/clusters/{clusterName}/node-groups"}, + "ListPodIdentityAssociations": {Verb: "List", Resource: "PodIdentityAssociation", OutputListKey: "associations", OutputItemKey: "", Method: "GET", URI: "/clusters/{clusterName}/pod-identity-associations"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/tags/{resourceArn}"}, + "ListUpdates": {Verb: "List", Resource: "Update", OutputListKey: "updateIds", OutputItemKey: "", Method: "GET", URI: "/clusters/{name}/updates"}, + "RegisterCluster": {Verb: "Create", Resource: "Cluster", OutputListKey: "", OutputItemKey: "cluster", Method: "POST", URI: "/cluster-registrations"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/tags/{resourceArn}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/tags/{resourceArn}"}, + "UpdateAccessEntry": {Verb: "Update", Resource: "AccessEntry", OutputListKey: "", OutputItemKey: "accessEntry", Method: "POST", URI: "/clusters/{clusterName}/access-entries/{principalArn}"}, + "UpdateAddon": {Verb: "Update", Resource: "Addon", OutputListKey: "", OutputItemKey: "update", Method: "POST", URI: "/clusters/{clusterName}/addons/{addonName}/update"}, + "UpdateCapability": {Verb: "Update", Resource: "Capability", OutputListKey: "", OutputItemKey: "update", Method: "POST", URI: "/clusters/{clusterName}/capabilities/{capabilityName}"}, + "UpdateClusterConfig": {Verb: "Update", Resource: "ClusterConfig", OutputListKey: "", OutputItemKey: "update", Method: "POST", URI: "/clusters/{name}/update-config"}, + "UpdateClusterVersion": {Verb: "Update", Resource: "ClusterVersion", OutputListKey: "", OutputItemKey: "update", Method: "POST", URI: "/clusters/{name}/updates"}, + "UpdateEksAnywhereSubscription": {Verb: "Update", Resource: "EksAnywhereSubscription", OutputListKey: "", OutputItemKey: "subscription", Method: "POST", URI: "/eks-anywhere-subscriptions/{id}"}, + "UpdateNodegroupConfig": {Verb: "Update", Resource: "NodegroupConfig", OutputListKey: "", OutputItemKey: "update", Method: "POST", URI: "/clusters/{clusterName}/node-groups/{nodegroupName}/update-config"}, + "UpdateNodegroupVersion": {Verb: "Update", Resource: "NodegroupVersion", OutputListKey: "", OutputItemKey: "update", Method: "POST", URI: "/clusters/{clusterName}/node-groups/{nodegroupName}/update-version"}, + "UpdatePodIdentityAssociation": {Verb: "Update", Resource: "PodIdentityAssociation", OutputListKey: "", OutputItemKey: "association", Method: "POST", URI: "/clusters/{clusterName}/pod-identity-associations/{associationId}"}, + }) + crud.Register("elasticsearchservice", map[string]crud.OpMeta{ + "CreateElasticsearchDomain": {Verb: "Create", Resource: "ElasticsearchDomain", OutputListKey: "", OutputItemKey: "DomainStatus", Method: "POST", URI: "/2015-01-01/es/domain"}, + "CreateOutboundCrossClusterSearchConnection": {Verb: "Create", Resource: "OutboundCrossClusterSearchConnection", OutputListKey: "", OutputItemKey: "ConnectionStatus", Method: "POST", URI: "/2015-01-01/es/ccs/outboundConnection"}, + "CreatePackage": {Verb: "Create", Resource: "Package", OutputListKey: "", OutputItemKey: "PackageDetails", Method: "POST", URI: "/2015-01-01/packages"}, + "CreateVpcEndpoint": {Verb: "Create", Resource: "VpcEndpoint", OutputListKey: "", OutputItemKey: "VpcEndpoint", Method: "POST", URI: "/2015-01-01/es/vpcEndpoints"}, + "DeleteElasticsearchDomain": {Verb: "Delete", Resource: "ElasticsearchDomain", OutputListKey: "", OutputItemKey: "DomainStatus", Method: "DELETE", URI: "/2015-01-01/es/domain/{DomainName}"}, + "DeleteElasticsearchServiceRole": {Verb: "Delete", Resource: "ElasticsearchServiceRole", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2015-01-01/es/role"}, + "DeleteInboundCrossClusterSearchConnection": {Verb: "Delete", Resource: "InboundCrossClusterSearchConnection", OutputListKey: "", OutputItemKey: "CrossClusterSearchConnection", Method: "DELETE", URI: "/2015-01-01/es/ccs/inboundConnection/{CrossClusterSearchConnectionId}"}, + "DeleteOutboundCrossClusterSearchConnection": {Verb: "Delete", Resource: "OutboundCrossClusterSearchConnection", OutputListKey: "", OutputItemKey: "CrossClusterSearchConnection", Method: "DELETE", URI: "/2015-01-01/es/ccs/outboundConnection/{CrossClusterSearchConnectionId}"}, + "DeletePackage": {Verb: "Delete", Resource: "Package", OutputListKey: "", OutputItemKey: "PackageDetails", Method: "DELETE", URI: "/2015-01-01/packages/{PackageID}"}, + "DeleteVpcEndpoint": {Verb: "Delete", Resource: "VpcEndpoint", OutputListKey: "", OutputItemKey: "VpcEndpointSummary", Method: "DELETE", URI: "/2015-01-01/es/vpcEndpoints/{VpcEndpointId}"}, + "DescribeDomainAutoTunes": {Verb: "Get", Resource: "DomainAutoTune", OutputListKey: "AutoTunes", OutputItemKey: "", Method: "GET", URI: "/2015-01-01/es/domain/{DomainName}/autoTunes"}, + "DescribeDomainChangeProgress": {Verb: "Get", Resource: "DomainChangeProgress", OutputListKey: "", OutputItemKey: "ChangeProgressStatus", Method: "GET", URI: "/2015-01-01/es/domain/{DomainName}/progress"}, + "DescribeElasticsearchDomain": {Verb: "Get", Resource: "ElasticsearchDomain", OutputListKey: "", OutputItemKey: "DomainStatus", Method: "GET", URI: "/2015-01-01/es/domain/{DomainName}"}, + "DescribeElasticsearchDomainConfig": {Verb: "Get", Resource: "ElasticsearchDomainConfig", OutputListKey: "", OutputItemKey: "DomainConfig", Method: "GET", URI: "/2015-01-01/es/domain/{DomainName}/config"}, + "DescribeElasticsearchDomains": {Verb: "Get", Resource: "ElasticsearchDomain", OutputListKey: "DomainStatusList", OutputItemKey: "", Method: "POST", URI: "/2015-01-01/es/domain-info"}, + "DescribeElasticsearchInstanceTypeLimits": {Verb: "Get", Resource: "ElasticsearchInstanceTypeLimit", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/2015-01-01/es/instanceTypeLimits/{ElasticsearchVersion}/{InstanceType}"}, + "DescribeInboundCrossClusterSearchConnections": {Verb: "Get", Resource: "InboundCrossClusterSearchConnection", OutputListKey: "CrossClusterSearchConnections", OutputItemKey: "", Method: "POST", URI: "/2015-01-01/es/ccs/inboundConnection/search"}, + "DescribeOutboundCrossClusterSearchConnections": {Verb: "Get", Resource: "OutboundCrossClusterSearchConnection", OutputListKey: "CrossClusterSearchConnections", OutputItemKey: "", Method: "POST", URI: "/2015-01-01/es/ccs/outboundConnection/search"}, + "DescribePackages": {Verb: "Get", Resource: "Package", OutputListKey: "PackageDetailsList", OutputItemKey: "", Method: "POST", URI: "/2015-01-01/packages/describe"}, + "DescribeReservedElasticsearchInstanceOfferings": {Verb: "Get", Resource: "ReservedElasticsearchInstanceOffering", OutputListKey: "ReservedElasticsearchInstanceOfferings", OutputItemKey: "", Method: "GET", URI: "/2015-01-01/es/reservedInstanceOfferings"}, + "DescribeReservedElasticsearchInstances": {Verb: "Get", Resource: "ReservedElasticsearchInstance", OutputListKey: "ReservedElasticsearchInstances", OutputItemKey: "", Method: "GET", URI: "/2015-01-01/es/reservedInstances"}, + "DescribeVpcEndpoints": {Verb: "Get", Resource: "VpcEndpoint", OutputListKey: "VpcEndpointErrors", OutputItemKey: "", Method: "POST", URI: "/2015-01-01/es/vpcEndpoints/describe"}, + "GetCompatibleElasticsearchVersions": {Verb: "Get", Resource: "CompatibleElasticsearchVersion", OutputListKey: "CompatibleElasticsearchVersions", OutputItemKey: "", Method: "GET", URI: "/2015-01-01/es/compatibleVersions"}, + "GetPackageVersionHistory": {Verb: "Get", Resource: "PackageVersionHistory", OutputListKey: "PackageVersionHistoryList", OutputItemKey: "", Method: "GET", URI: "/2015-01-01/packages/{PackageID}/history"}, + "GetUpgradeHistory": {Verb: "Get", Resource: "UpgradeHistory", OutputListKey: "UpgradeHistories", OutputItemKey: "", Method: "GET", URI: "/2015-01-01/es/upgradeDomain/{DomainName}/history"}, + "GetUpgradeStatus": {Verb: "Get", Resource: "UpgradeStatu", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/2015-01-01/es/upgradeDomain/{DomainName}/status"}, + "ListDomainNames": {Verb: "List", Resource: "DomainName", OutputListKey: "DomainNames", OutputItemKey: "", Method: "GET", URI: "/2015-01-01/domain"}, + "ListDomainsForPackage": {Verb: "List", Resource: "DomainsForPackage", OutputListKey: "DomainPackageDetailsList", OutputItemKey: "", Method: "GET", URI: "/2015-01-01/packages/{PackageID}/domains"}, + "ListElasticsearchInstanceTypes": {Verb: "List", Resource: "ElasticsearchInstanceType", OutputListKey: "ElasticsearchInstanceTypes", OutputItemKey: "", Method: "GET", URI: "/2015-01-01/es/instanceTypes/{ElasticsearchVersion}"}, + "ListElasticsearchVersions": {Verb: "List", Resource: "ElasticsearchVersion", OutputListKey: "ElasticsearchVersions", OutputItemKey: "", Method: "GET", URI: "/2015-01-01/es/versions"}, + "ListPackagesForDomain": {Verb: "List", Resource: "PackagesForDomain", OutputListKey: "DomainPackageDetailsList", OutputItemKey: "", Method: "GET", URI: "/2015-01-01/domain/{DomainName}/packages"}, + "ListTags": {Verb: "List", Resource: "Tag", OutputListKey: "TagList", OutputItemKey: "", Method: "GET", URI: "/2015-01-01/tags"}, + "ListVpcEndpointAccess": {Verb: "List", Resource: "VpcEndpointAccess", OutputListKey: "AuthorizedPrincipalList", OutputItemKey: "", Method: "GET", URI: "/2015-01-01/es/domain/{DomainName}/listVpcEndpointAccess"}, + "ListVpcEndpoints": {Verb: "List", Resource: "VpcEndpoint", OutputListKey: "VpcEndpointSummaryList", OutputItemKey: "", Method: "GET", URI: "/2015-01-01/es/vpcEndpoints"}, + "ListVpcEndpointsForDomain": {Verb: "List", Resource: "VpcEndpointsForDomain", OutputListKey: "VpcEndpointSummaryList", OutputItemKey: "", Method: "GET", URI: "/2015-01-01/es/domain/{DomainName}/vpcEndpoints"}, + "UpdateElasticsearchDomainConfig": {Verb: "Update", Resource: "ElasticsearchDomainConfig", OutputListKey: "", OutputItemKey: "DomainConfig", Method: "POST", URI: "/2015-01-01/es/domain/{DomainName}/config"}, + "UpdatePackage": {Verb: "Update", Resource: "Package", OutputListKey: "", OutputItemKey: "PackageDetails", Method: "POST", URI: "/2015-01-01/packages/update"}, + "UpdateVpcEndpoint": {Verb: "Update", Resource: "VpcEndpoint", OutputListKey: "", OutputItemKey: "VpcEndpoint", Method: "POST", URI: "/2015-01-01/es/vpcEndpoints/update"}, + }) crud.Register("emr", map[string]crud.OpMeta{ "CreatePersistentAppUI": {Verb: "Create", Resource: "PersistentAppUI", OutputListKey: "", OutputItemKey: ""}, "CreateSecurityConfiguration": {Verb: "Create", Resource: "SecurityConfiguration", OutputListKey: "", OutputItemKey: ""}, @@ -1006,6 +2072,41 @@ func init() { "UpdateStudio": {Verb: "Update", Resource: "Studio", OutputListKey: "", OutputItemKey: ""}, "UpdateStudioSessionMapping": {Verb: "Update", Resource: "StudioSessionMapping", OutputListKey: "", OutputItemKey: ""}, }) + crud.Register("entityresolution", map[string]crud.OpMeta{ + "CreateIdMappingWorkflow": {Verb: "Create", Resource: "IdMappingWorkflow", OutputListKey: "inputSourceConfig", OutputItemKey: "idMappingTechniques", Method: "POST", URI: "/idmappingworkflows"}, + "CreateIdNamespace": {Verb: "Create", Resource: "IdNamespace", OutputListKey: "idMappingWorkflowProperties", OutputItemKey: "", Method: "POST", URI: "/idnamespaces"}, + "CreateMatchingWorkflow": {Verb: "Create", Resource: "MatchingWorkflow", OutputListKey: "inputSourceConfig", OutputItemKey: "incrementalRunConfig", Method: "POST", URI: "/matchingworkflows"}, + "CreateSchemaMapping": {Verb: "Create", Resource: "SchemaMapping", OutputListKey: "mappedInputFields", OutputItemKey: "", Method: "POST", URI: "/schemas"}, + "DeleteIdMappingWorkflow": {Verb: "Delete", Resource: "IdMappingWorkflow", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/idmappingworkflows/{workflowName}"}, + "DeleteIdNamespace": {Verb: "Delete", Resource: "IdNamespace", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/idnamespaces/{idNamespaceName}"}, + "DeleteMatchingWorkflow": {Verb: "Delete", Resource: "MatchingWorkflow", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/matchingworkflows/{workflowName}"}, + "DeletePolicyStatement": {Verb: "Delete", Resource: "PolicyStatement", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/policies/{arn}/{statementId}"}, + "DeleteSchemaMapping": {Verb: "Delete", Resource: "SchemaMapping", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/schemas/{schemaName}"}, + "GetIdMappingJob": {Verb: "Get", Resource: "IdMappingJob", OutputListKey: "outputSourceConfig", OutputItemKey: "errorDetails", Method: "GET", URI: "/idmappingworkflows/{workflowName}/jobs/{jobId}"}, + "GetIdMappingWorkflow": {Verb: "Get", Resource: "IdMappingWorkflow", OutputListKey: "inputSourceConfig", OutputItemKey: "idMappingTechniques", Method: "GET", URI: "/idmappingworkflows/{workflowName}"}, + "GetIdNamespace": {Verb: "Get", Resource: "IdNamespace", OutputListKey: "idMappingWorkflowProperties", OutputItemKey: "", Method: "GET", URI: "/idnamespaces/{idNamespaceName}"}, + "GetMatchId": {Verb: "Get", Resource: "MatchId", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/matchingworkflows/{workflowName}/matches"}, + "GetMatchingJob": {Verb: "Get", Resource: "MatchingJob", OutputListKey: "outputSourceConfig", OutputItemKey: "errorDetails", Method: "GET", URI: "/matchingworkflows/{workflowName}/jobs/{jobId}"}, + "GetMatchingWorkflow": {Verb: "Get", Resource: "MatchingWorkflow", OutputListKey: "inputSourceConfig", OutputItemKey: "incrementalRunConfig", Method: "GET", URI: "/matchingworkflows/{workflowName}"}, + "GetPolicy": {Verb: "Get", Resource: "Policy", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/policies/{arn}"}, + "GetProviderService": {Verb: "Get", Resource: "ProviderService", OutputListKey: "", OutputItemKey: "providerComponentSchema", Method: "GET", URI: "/providerservices/{providerName}/{providerServiceName}"}, + "GetSchemaMapping": {Verb: "Get", Resource: "SchemaMapping", OutputListKey: "mappedInputFields", OutputItemKey: "", Method: "GET", URI: "/schemas/{schemaName}"}, + "ListIdMappingJobs": {Verb: "List", Resource: "IdMappingJob", OutputListKey: "jobs", OutputItemKey: "", Method: "GET", URI: "/idmappingworkflows/{workflowName}/jobs"}, + "ListIdMappingWorkflows": {Verb: "List", Resource: "IdMappingWorkflow", OutputListKey: "workflowSummaries", OutputItemKey: "", Method: "GET", URI: "/idmappingworkflows"}, + "ListIdNamespaces": {Verb: "List", Resource: "IdNamespace", OutputListKey: "idNamespaceSummaries", OutputItemKey: "", Method: "GET", URI: "/idnamespaces"}, + "ListMatchingJobs": {Verb: "List", Resource: "MatchingJob", OutputListKey: "jobs", OutputItemKey: "", Method: "GET", URI: "/matchingworkflows/{workflowName}/jobs"}, + "ListMatchingWorkflows": {Verb: "List", Resource: "MatchingWorkflow", OutputListKey: "workflowSummaries", OutputItemKey: "", Method: "GET", URI: "/matchingworkflows"}, + "ListProviderServices": {Verb: "List", Resource: "ProviderService", OutputListKey: "providerServiceSummaries", OutputItemKey: "", Method: "GET", URI: "/providerservices"}, + "ListSchemaMappings": {Verb: "List", Resource: "SchemaMapping", OutputListKey: "schemaList", OutputItemKey: "", Method: "GET", URI: "/schemas"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/tags/{resourceArn}"}, + "PutPolicy": {Verb: "Update", Resource: "Policy", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/policies/{arn}"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/tags/{resourceArn}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/tags/{resourceArn}"}, + "UpdateIdMappingWorkflow": {Verb: "Update", Resource: "IdMappingWorkflow", OutputListKey: "inputSourceConfig", OutputItemKey: "idMappingTechniques", Method: "PUT", URI: "/idmappingworkflows/{workflowName}"}, + "UpdateIdNamespace": {Verb: "Update", Resource: "IdNamespace", OutputListKey: "idMappingWorkflowProperties", OutputItemKey: "", Method: "PUT", URI: "/idnamespaces/{idNamespaceName}"}, + "UpdateMatchingWorkflow": {Verb: "Update", Resource: "MatchingWorkflow", OutputListKey: "inputSourceConfig", OutputItemKey: "incrementalRunConfig", Method: "PUT", URI: "/matchingworkflows/{workflowName}"}, + "UpdateSchemaMapping": {Verb: "Update", Resource: "SchemaMapping", OutputListKey: "mappedInputFields", OutputItemKey: "", Method: "PUT", URI: "/schemas/{schemaName}"}, + }) crud.Register("eventbridge", map[string]crud.OpMeta{ "CreateApiDestination": {Verb: "Create", Resource: "ApiDestination", OutputListKey: "", OutputItemKey: ""}, "CreateArchive": {Verb: "Create", Resource: "Archive", OutputListKey: "", OutputItemKey: ""}, @@ -1067,6 +2168,32 @@ func init() { "UntagDeliveryStream": {Verb: "Untag", Resource: "DeliveryStream", OutputListKey: "", OutputItemKey: ""}, "UpdateDestination": {Verb: "Update", Resource: "Destination", OutputListKey: "", OutputItemKey: ""}, }) + crud.Register("fis", map[string]crud.OpMeta{ + "CreateExperimentTemplate": {Verb: "Create", Resource: "ExperimentTemplate", OutputListKey: "", OutputItemKey: "experimentTemplate", Method: "POST", URI: "/experimentTemplates"}, + "CreateTargetAccountConfiguration": {Verb: "Create", Resource: "TargetAccountConfiguration", OutputListKey: "", OutputItemKey: "targetAccountConfiguration", Method: "POST", URI: "/experimentTemplates/{experimentTemplateId}/targetAccountConfigurations/{accountId}"}, + "DeleteExperimentTemplate": {Verb: "Delete", Resource: "ExperimentTemplate", OutputListKey: "", OutputItemKey: "experimentTemplate", Method: "DELETE", URI: "/experimentTemplates/{id}"}, + "DeleteTargetAccountConfiguration": {Verb: "Delete", Resource: "TargetAccountConfiguration", OutputListKey: "", OutputItemKey: "targetAccountConfiguration", Method: "DELETE", URI: "/experimentTemplates/{experimentTemplateId}/targetAccountConfigurations/{accountId}"}, + "GetAction": {Verb: "Get", Resource: "Action", OutputListKey: "", OutputItemKey: "action", Method: "GET", URI: "/actions/{id}"}, + "GetExperiment": {Verb: "Get", Resource: "Experiment", OutputListKey: "", OutputItemKey: "experiment", Method: "GET", URI: "/experiments/{id}"}, + "GetExperimentTargetAccountConfiguration": {Verb: "Get", Resource: "ExperimentTargetAccountConfiguration", OutputListKey: "", OutputItemKey: "targetAccountConfiguration", Method: "GET", URI: "/experiments/{experimentId}/targetAccountConfigurations/{accountId}"}, + "GetExperimentTemplate": {Verb: "Get", Resource: "ExperimentTemplate", OutputListKey: "", OutputItemKey: "experimentTemplate", Method: "GET", URI: "/experimentTemplates/{id}"}, + "GetSafetyLever": {Verb: "Get", Resource: "SafetyLever", OutputListKey: "", OutputItemKey: "safetyLever", Method: "GET", URI: "/safetyLevers/{id}"}, + "GetTargetAccountConfiguration": {Verb: "Get", Resource: "TargetAccountConfiguration", OutputListKey: "", OutputItemKey: "targetAccountConfiguration", Method: "GET", URI: "/experimentTemplates/{experimentTemplateId}/targetAccountConfigurations/{accountId}"}, + "GetTargetResourceType": {Verb: "Get", Resource: "TargetResourceType", OutputListKey: "", OutputItemKey: "targetResourceType", Method: "GET", URI: "/targetResourceTypes/{resourceType}"}, + "ListActions": {Verb: "List", Resource: "Action", OutputListKey: "actions", OutputItemKey: "", Method: "GET", URI: "/actions"}, + "ListExperimentResolvedTargets": {Verb: "List", Resource: "ExperimentResolvedTarget", OutputListKey: "resolvedTargets", OutputItemKey: "", Method: "GET", URI: "/experiments/{experimentId}/resolvedTargets"}, + "ListExperimentTargetAccountConfigurations": {Verb: "List", Resource: "ExperimentTargetAccountConfiguration", OutputListKey: "targetAccountConfigurations", OutputItemKey: "", Method: "GET", URI: "/experiments/{experimentId}/targetAccountConfigurations"}, + "ListExperimentTemplates": {Verb: "List", Resource: "ExperimentTemplate", OutputListKey: "experimentTemplates", OutputItemKey: "", Method: "GET", URI: "/experimentTemplates"}, + "ListExperiments": {Verb: "List", Resource: "Experiment", OutputListKey: "experiments", OutputItemKey: "", Method: "GET", URI: "/experiments"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/tags/{resourceArn}"}, + "ListTargetAccountConfigurations": {Verb: "List", Resource: "TargetAccountConfiguration", OutputListKey: "targetAccountConfigurations", OutputItemKey: "", Method: "GET", URI: "/experimentTemplates/{experimentTemplateId}/targetAccountConfigurations"}, + "ListTargetResourceTypes": {Verb: "List", Resource: "TargetResourceType", OutputListKey: "targetResourceTypes", OutputItemKey: "", Method: "GET", URI: "/targetResourceTypes"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/tags/{resourceArn}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/tags/{resourceArn}"}, + "UpdateExperimentTemplate": {Verb: "Update", Resource: "ExperimentTemplate", OutputListKey: "", OutputItemKey: "experimentTemplate", Method: "PATCH", URI: "/experimentTemplates/{id}"}, + "UpdateSafetyLeverState": {Verb: "Update", Resource: "SafetyLeverState", OutputListKey: "", OutputItemKey: "safetyLever", Method: "PATCH", URI: "/safetyLevers/{id}/state"}, + "UpdateTargetAccountConfiguration": {Verb: "Update", Resource: "TargetAccountConfiguration", OutputListKey: "", OutputItemKey: "targetAccountConfiguration", Method: "PATCH", URI: "/experimentTemplates/{experimentTemplateId}/targetAccountConfigurations/{accountId}"}, + }) crud.Register("forecast", map[string]crud.OpMeta{ "CreateAutoPredictor": {Verb: "Create", Resource: "AutoPredictor", OutputListKey: "", OutputItemKey: ""}, "CreateDataset": {Verb: "Create", Resource: "Dataset", OutputListKey: "", OutputItemKey: ""}, @@ -1201,6 +2328,26 @@ func init() { "UpdateRuleVersion": {Verb: "Update", Resource: "RuleVersion", OutputListKey: "", OutputItemKey: "rule"}, "UpdateVariable": {Verb: "Update", Resource: "Variable", OutputListKey: "", OutputItemKey: ""}, }) + crud.Register("glacier", map[string]crud.OpMeta{ + "CreateVault": {Verb: "Create", Resource: "Vault", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{accountId}/vaults/{vaultName}"}, + "DeleteArchive": {Verb: "Delete", Resource: "Archive", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/{accountId}/vaults/{vaultName}/archives/{archiveId}"}, + "DeleteVault": {Verb: "Delete", Resource: "Vault", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/{accountId}/vaults/{vaultName}"}, + "DeleteVaultAccessPolicy": {Verb: "Delete", Resource: "VaultAccessPolicy", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/{accountId}/vaults/{vaultName}/access-policy"}, + "DeleteVaultNotifications": {Verb: "Delete", Resource: "VaultNotification", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/{accountId}/vaults/{vaultName}/notification-configuration"}, + "DescribeJob": {Verb: "Get", Resource: "Job", OutputListKey: "", OutputItemKey: "InventoryRetrievalParameters", Method: "GET", URI: "/{accountId}/vaults/{vaultName}/jobs/{jobId}"}, + "DescribeVault": {Verb: "Get", Resource: "Vault", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/{accountId}/vaults/{vaultName}"}, + "GetDataRetrievalPolicy": {Verb: "Get", Resource: "DataRetrievalPolicy", OutputListKey: "", OutputItemKey: "Policy", Method: "GET", URI: "/{accountId}/policies/data-retrieval"}, + "GetJobOutput": {Verb: "Get", Resource: "JobOutput", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/{accountId}/vaults/{vaultName}/jobs/{jobId}/output"}, + "GetVaultAccessPolicy": {Verb: "Get", Resource: "VaultAccessPolicy", OutputListKey: "", OutputItemKey: "policy", Method: "GET", URI: "/{accountId}/vaults/{vaultName}/access-policy"}, + "GetVaultLock": {Verb: "Get", Resource: "VaultLock", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/{accountId}/vaults/{vaultName}/lock-policy"}, + "GetVaultNotifications": {Verb: "Get", Resource: "VaultNotification", OutputListKey: "", OutputItemKey: "vaultNotificationConfig", Method: "GET", URI: "/{accountId}/vaults/{vaultName}/notification-configuration"}, + "ListJobs": {Verb: "List", Resource: "Job", OutputListKey: "JobList", OutputItemKey: "", Method: "GET", URI: "/{accountId}/vaults/{vaultName}/jobs"}, + "ListMultipartUploads": {Verb: "List", Resource: "MultipartUpload", OutputListKey: "UploadsList", OutputItemKey: "", Method: "GET", URI: "/{accountId}/vaults/{vaultName}/multipart-uploads"}, + "ListParts": {Verb: "List", Resource: "Part", OutputListKey: "Parts", OutputItemKey: "", Method: "GET", URI: "/{accountId}/vaults/{vaultName}/multipart-uploads/{uploadId}"}, + "ListProvisionedCapacity": {Verb: "List", Resource: "ProvisionedCapacity", OutputListKey: "ProvisionedCapacityList", OutputItemKey: "", Method: "GET", URI: "/{accountId}/provisioned-capacity"}, + "ListTagsForVault": {Verb: "List", Resource: "TagsForVault", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/{accountId}/vaults/{vaultName}/tags"}, + "ListVaults": {Verb: "List", Resource: "Vault", OutputListKey: "VaultList", OutputItemKey: "", Method: "GET", URI: "/{accountId}/vaults"}, + }) crud.Register("glue", map[string]crud.OpMeta{ "BatchGetBlueprints": {Verb: "List", Resource: "Blueprint", OutputListKey: "Blueprints", OutputItemKey: ""}, "BatchGetCrawlers": {Verb: "List", Resource: "Crawler", OutputListKey: "Crawlers", OutputItemKey: ""}, @@ -1425,27 +2572,411 @@ func init() { "UpdateWorkflow": {Verb: "Update", Resource: "Workflow", OutputListKey: "", OutputItemKey: ""}, }) crud.Register("healthlake", map[string]crud.OpMeta{ - "CreateDataTransformationProfile": {Verb: "Create", Resource: "DataTransformationProfile", OutputListKey: "", OutputItemKey: ""}, + "CreateDataTransformationProfile": {Verb: "Create", Resource: "DataTransformationProfile", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/data-transformation-profile"}, "CreateFHIRDatastore": {Verb: "Create", Resource: "FHIRDatastore", OutputListKey: "", OutputItemKey: ""}, - "DeleteDataTransformationProfile": {Verb: "Delete", Resource: "DataTransformationProfile", OutputListKey: "", OutputItemKey: ""}, + "DeleteDataTransformationProfile": {Verb: "Delete", Resource: "DataTransformationProfile", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/data-transformation-profile/{ProfileId}"}, "DeleteFHIRDatastore": {Verb: "Delete", Resource: "FHIRDatastore", OutputListKey: "", OutputItemKey: ""}, - "DescribeDataTransformationJob": {Verb: "Get", Resource: "DataTransformationJob", OutputListKey: "", OutputItemKey: "TransformationJobProperties"}, + "DescribeDataTransformationJob": {Verb: "Get", Resource: "DataTransformationJob", OutputListKey: "", OutputItemKey: "TransformationJobProperties", Method: "GET", URI: "/data-transformation-job/{JobId}"}, "DescribeFHIRDatastore": {Verb: "Get", Resource: "FHIRDatastore", OutputListKey: "", OutputItemKey: "DatastoreProperties"}, "DescribeFHIRExportJob": {Verb: "Get", Resource: "FHIRExportJob", OutputListKey: "", OutputItemKey: "ExportJobProperties"}, "DescribeFHIRImportJob": {Verb: "Get", Resource: "FHIRImportJob", OutputListKey: "", OutputItemKey: "ImportJobProperties"}, - "GetDataTransformationProfile": {Verb: "Get", Resource: "DataTransformationProfile", OutputListKey: "", OutputItemKey: ""}, - "ListDataTransformationJobs": {Verb: "List", Resource: "DataTransformationJob", OutputListKey: "Items", OutputItemKey: ""}, - "ListDataTransformationProfileVersions": {Verb: "List", Resource: "DataTransformationProfileVersion", OutputListKey: "Items", OutputItemKey: ""}, - "ListDataTransformationProfiles": {Verb: "List", Resource: "DataTransformationProfile", OutputListKey: "Items", OutputItemKey: ""}, + "GetDataTransformationProfile": {Verb: "Get", Resource: "DataTransformationProfile", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/data-transformation-profile/{ProfileId}"}, + "ListDataTransformationJobs": {Verb: "List", Resource: "DataTransformationJob", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/data-transformation-jobs"}, + "ListDataTransformationProfileVersions": {Verb: "List", Resource: "DataTransformationProfileVersion", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/data-transformation-profile/{ProfileId}/versions"}, + "ListDataTransformationProfiles": {Verb: "List", Resource: "DataTransformationProfile", OutputListKey: "Items", OutputItemKey: "", Method: "GET", URI: "/data-transformation-profile"}, "ListFHIRDatastores": {Verb: "List", Resource: "FHIRDatastore", OutputListKey: "DatastorePropertiesList", OutputItemKey: ""}, "ListFHIRExportJobs": {Verb: "List", Resource: "FHIRExportJob", OutputListKey: "ExportJobPropertiesList", OutputItemKey: ""}, "ListFHIRImportJobs": {Verb: "List", Resource: "FHIRImportJob", OutputListKey: "ImportJobPropertiesList", OutputItemKey: ""}, "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "Tags", OutputItemKey: ""}, "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: ""}, "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: ""}, - "UpdateDataTransformationProfile": {Verb: "Update", Resource: "DataTransformationProfile", OutputListKey: "", OutputItemKey: ""}, + "UpdateDataTransformationProfile": {Verb: "Update", Resource: "DataTransformationProfile", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/data-transformation-profile/{ProfileId}"}, "UpdateFHIRDatastore": {Verb: "Update", Resource: "FHIRDatastore", OutputListKey: "", OutputItemKey: "DatastoreProperties"}, - "UpdateProfileWithAgent": {Verb: "Update", Resource: "ProfileWithAgent", OutputListKey: "", OutputItemKey: "AgentResponse"}, + "UpdateProfileWithAgent": {Verb: "Update", Resource: "ProfileWithAgent", OutputListKey: "", OutputItemKey: "AgentResponse", Method: "POST", URI: "/update-profile-with-agent"}, + }) + crud.Register("iot", map[string]crud.OpMeta{ + "CreateAuditSuppression": {Verb: "Create", Resource: "AuditSuppression", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/audit/suppressions/create"}, + "CreateAuthorizer": {Verb: "Create", Resource: "Authorizer", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/authorizer/{authorizerName}"}, + "CreateBillingGroup": {Verb: "Create", Resource: "BillingGroup", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/billing-groups/{billingGroupName}"}, + "CreateCertificateFromCsr": {Verb: "Create", Resource: "CertificateFromCsr", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/certificates"}, + "CreateCertificateProvider": {Verb: "Create", Resource: "CertificateProvider", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/certificate-providers/{certificateProviderName}"}, + "CreateCommand": {Verb: "Create", Resource: "Command", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/commands/{commandId}"}, + "CreateCustomMetric": {Verb: "Create", Resource: "CustomMetric", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/custom-metric/{metricName}"}, + "CreateDimension": {Verb: "Create", Resource: "Dimension", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/dimensions/{name}"}, + "CreateDomainConfiguration": {Verb: "Create", Resource: "DomainConfiguration", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/domainConfigurations/{domainConfigurationName}"}, + "CreateDynamicThingGroup": {Verb: "Create", Resource: "DynamicThingGroup", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/dynamic-thing-groups/{thingGroupName}"}, + "CreateFleetMetric": {Verb: "Create", Resource: "FleetMetric", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/fleet-metric/{metricName}"}, + "CreateJob": {Verb: "Create", Resource: "Job", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/jobs/{jobId}"}, + "CreateJobTemplate": {Verb: "Create", Resource: "JobTemplate", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/job-templates/{jobTemplateId}"}, + "CreateKeysAndCertificate": {Verb: "Create", Resource: "KeysAndCertificate", OutputListKey: "", OutputItemKey: "keyPair", Method: "POST", URI: "/keys-and-certificate"}, + "CreateMitigationAction": {Verb: "Create", Resource: "MitigationAction", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/mitigationactions/actions/{actionName}"}, + "CreateOTAUpdate": {Verb: "Create", Resource: "OTAUpdate", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/otaUpdates/{otaUpdateId}"}, + "CreatePackage": {Verb: "Create", Resource: "Package", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/packages/{packageName}"}, + "CreatePackageVersion": {Verb: "Create", Resource: "PackageVersion", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/packages/{packageName}/versions/{versionName}"}, + "CreatePolicy": {Verb: "Create", Resource: "Policy", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/policies/{policyName}"}, + "CreatePolicyVersion": {Verb: "Create", Resource: "PolicyVersion", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/policies/{policyName}/version"}, + "CreateProvisioningClaim": {Verb: "Create", Resource: "ProvisioningClaim", OutputListKey: "", OutputItemKey: "keyPair", Method: "POST", URI: "/provisioning-templates/{templateName}/provisioning-claim"}, + "CreateProvisioningTemplate": {Verb: "Create", Resource: "ProvisioningTemplate", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/provisioning-templates"}, + "CreateProvisioningTemplateVersion": {Verb: "Create", Resource: "ProvisioningTemplateVersion", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/provisioning-templates/{templateName}/versions"}, + "CreateRoleAlias": {Verb: "Create", Resource: "RoleAlia", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/role-aliases/{roleAlias}"}, + "CreateScheduledAudit": {Verb: "Create", Resource: "ScheduledAudit", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/audit/scheduledaudits/{scheduledAuditName}"}, + "CreateSecurityProfile": {Verb: "Create", Resource: "SecurityProfile", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/security-profiles/{securityProfileName}"}, + "CreateStream": {Verb: "Create", Resource: "Stream", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/streams/{streamId}"}, + "CreateThing": {Verb: "Create", Resource: "Thing", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/things/{thingName}"}, + "CreateThingGroup": {Verb: "Create", Resource: "ThingGroup", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/thing-groups/{thingGroupName}"}, + "CreateThingType": {Verb: "Create", Resource: "ThingType", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/thing-types/{thingTypeName}"}, + "CreateTopicRule": {Verb: "Create", Resource: "TopicRule", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/rules/{ruleName}"}, + "CreateTopicRuleDestination": {Verb: "Create", Resource: "TopicRuleDestination", OutputListKey: "", OutputItemKey: "topicRuleDestination", Method: "POST", URI: "/destinations"}, + "DeleteAccountAuditConfiguration": {Verb: "Delete", Resource: "AccountAuditConfiguration", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/audit/configuration"}, + "DeleteAuditSuppression": {Verb: "Delete", Resource: "AuditSuppression", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/audit/suppressions/delete"}, + "DeleteAuthorizer": {Verb: "Delete", Resource: "Authorizer", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/authorizer/{authorizerName}"}, + "DeleteBillingGroup": {Verb: "Delete", Resource: "BillingGroup", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/billing-groups/{billingGroupName}"}, + "DeleteCACertificate": {Verb: "Delete", Resource: "CACertificate", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/cacertificate/{certificateId}"}, + "DeleteCertificate": {Verb: "Delete", Resource: "Certificate", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/certificates/{certificateId}"}, + "DeleteCertificateProvider": {Verb: "Delete", Resource: "CertificateProvider", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/certificate-providers/{certificateProviderName}"}, + "DeleteCommand": {Verb: "Delete", Resource: "Command", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/commands/{commandId}"}, + "DeleteCommandExecution": {Verb: "Delete", Resource: "CommandExecution", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/command-executions/{executionId}"}, + "DeleteCustomMetric": {Verb: "Delete", Resource: "CustomMetric", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/custom-metric/{metricName}"}, + "DeleteDimension": {Verb: "Delete", Resource: "Dimension", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/dimensions/{name}"}, + "DeleteDomainConfiguration": {Verb: "Delete", Resource: "DomainConfiguration", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/domainConfigurations/{domainConfigurationName}"}, + "DeleteDynamicThingGroup": {Verb: "Delete", Resource: "DynamicThingGroup", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/dynamic-thing-groups/{thingGroupName}"}, + "DeleteFleetMetric": {Verb: "Delete", Resource: "FleetMetric", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/fleet-metric/{metricName}"}, + "DeleteJob": {Verb: "Delete", Resource: "Job", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/jobs/{jobId}"}, + "DeleteJobExecution": {Verb: "Delete", Resource: "JobExecution", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/things/{thingName}/jobs/{jobId}/executionNumber/{executionNumber}"}, + "DeleteJobTemplate": {Verb: "Delete", Resource: "JobTemplate", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/job-templates/{jobTemplateId}"}, + "DeleteMitigationAction": {Verb: "Delete", Resource: "MitigationAction", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/mitigationactions/actions/{actionName}"}, + "DeleteOTAUpdate": {Verb: "Delete", Resource: "OTAUpdate", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/otaUpdates/{otaUpdateId}"}, + "DeletePackage": {Verb: "Delete", Resource: "Package", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/packages/{packageName}"}, + "DeletePackageVersion": {Verb: "Delete", Resource: "PackageVersion", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/packages/{packageName}/versions/{versionName}"}, + "DeletePolicy": {Verb: "Delete", Resource: "Policy", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/policies/{policyName}"}, + "DeletePolicyVersion": {Verb: "Delete", Resource: "PolicyVersion", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/policies/{policyName}/version/{policyVersionId}"}, + "DeleteProvisioningTemplate": {Verb: "Delete", Resource: "ProvisioningTemplate", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/provisioning-templates/{templateName}"}, + "DeleteProvisioningTemplateVersion": {Verb: "Delete", Resource: "ProvisioningTemplateVersion", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/provisioning-templates/{templateName}/versions/{versionId}"}, + "DeleteRegistrationCode": {Verb: "Delete", Resource: "RegistrationCode", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/registrationcode"}, + "DeleteRoleAlias": {Verb: "Delete", Resource: "RoleAlia", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/role-aliases/{roleAlias}"}, + "DeleteScheduledAudit": {Verb: "Delete", Resource: "ScheduledAudit", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/audit/scheduledaudits/{scheduledAuditName}"}, + "DeleteSecurityProfile": {Verb: "Delete", Resource: "SecurityProfile", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/security-profiles/{securityProfileName}"}, + "DeleteStream": {Verb: "Delete", Resource: "Stream", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/streams/{streamId}"}, + "DeleteThing": {Verb: "Delete", Resource: "Thing", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/things/{thingName}"}, + "DeleteThingGroup": {Verb: "Delete", Resource: "ThingGroup", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/thing-groups/{thingGroupName}"}, + "DeleteThingType": {Verb: "Delete", Resource: "ThingType", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/thing-types/{thingTypeName}"}, + "DeleteTopicRule": {Verb: "Delete", Resource: "TopicRule", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/rules/{ruleName}"}, + "DeleteTopicRuleDestination": {Verb: "Delete", Resource: "TopicRuleDestination", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/destinations/{arn+}"}, + "DeleteV2LoggingLevel": {Verb: "Delete", Resource: "V2LoggingLevel", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2LoggingLevel"}, + "DescribeAccountAuditConfiguration": {Verb: "Get", Resource: "AccountAuditConfiguration", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/audit/configuration"}, + "DescribeAuditFinding": {Verb: "Get", Resource: "AuditFinding", OutputListKey: "", OutputItemKey: "finding", Method: "GET", URI: "/audit/findings/{findingId}"}, + "DescribeAuditMitigationActionsTask": {Verb: "Get", Resource: "AuditMitigationActionsTask", OutputListKey: "actionsDefinition", OutputItemKey: "target", Method: "GET", URI: "/audit/mitigationactions/tasks/{taskId}"}, + "DescribeAuditSuppression": {Verb: "Get", Resource: "AuditSuppression", OutputListKey: "", OutputItemKey: "resourceIdentifier", Method: "POST", URI: "/audit/suppressions/describe"}, + "DescribeAuditTask": {Verb: "Get", Resource: "AuditTask", OutputListKey: "", OutputItemKey: "taskStatistics", Method: "GET", URI: "/audit/tasks/{taskId}"}, + "DescribeAuthorizer": {Verb: "Get", Resource: "Authorizer", OutputListKey: "", OutputItemKey: "authorizerDescription", Method: "GET", URI: "/authorizer/{authorizerName}"}, + "DescribeBillingGroup": {Verb: "Get", Resource: "BillingGroup", OutputListKey: "", OutputItemKey: "billingGroupMetadata", Method: "GET", URI: "/billing-groups/{billingGroupName}"}, + "DescribeCACertificate": {Verb: "Get", Resource: "CACertificate", OutputListKey: "", OutputItemKey: "certificateDescription", Method: "GET", URI: "/cacertificate/{certificateId}"}, + "DescribeCertificate": {Verb: "Get", Resource: "Certificate", OutputListKey: "", OutputItemKey: "certificateDescription", Method: "GET", URI: "/certificates/{certificateId}"}, + "DescribeCertificateProvider": {Verb: "Get", Resource: "CertificateProvider", OutputListKey: "accountDefaultForOperations", OutputItemKey: "", Method: "GET", URI: "/certificate-providers/{certificateProviderName}"}, + "DescribeCustomMetric": {Verb: "Get", Resource: "CustomMetric", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/custom-metric/{metricName}"}, + "DescribeDefaultAuthorizer": {Verb: "Get", Resource: "DefaultAuthorizer", OutputListKey: "", OutputItemKey: "authorizerDescription", Method: "GET", URI: "/default-authorizer"}, + "DescribeDetectMitigationActionsTask": {Verb: "Get", Resource: "DetectMitigationActionsTask", OutputListKey: "", OutputItemKey: "taskSummary", Method: "GET", URI: "/detect/mitigationactions/tasks/{taskId}"}, + "DescribeDimension": {Verb: "Get", Resource: "Dimension", OutputListKey: "stringValues", OutputItemKey: "", Method: "GET", URI: "/dimensions/{name}"}, + "DescribeDomainConfiguration": {Verb: "Get", Resource: "DomainConfiguration", OutputListKey: "serverCertificates", OutputItemKey: "authorizerConfig", Method: "GET", URI: "/domainConfigurations/{domainConfigurationName}"}, + "DescribeEncryptionConfiguration": {Verb: "Get", Resource: "EncryptionConfiguration", OutputListKey: "", OutputItemKey: "configurationDetails", Method: "GET", URI: "/encryption-configuration"}, + "DescribeEndpoint": {Verb: "Get", Resource: "Endpoint", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/endpoint"}, + "DescribeEventConfigurations": {Verb: "Get", Resource: "EventConfiguration", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/event-configurations"}, + "DescribeFleetMetric": {Verb: "Get", Resource: "FleetMetric", OutputListKey: "", OutputItemKey: "aggregationType", Method: "GET", URI: "/fleet-metric/{metricName}"}, + "DescribeIndex": {Verb: "Get", Resource: "Index", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/indices/{indexName}"}, + "DescribeJob": {Verb: "Get", Resource: "Job", OutputListKey: "", OutputItemKey: "job", Method: "GET", URI: "/jobs/{jobId}"}, + "DescribeJobExecution": {Verb: "Get", Resource: "JobExecution", OutputListKey: "", OutputItemKey: "execution", Method: "GET", URI: "/things/{thingName}/jobs/{jobId}"}, + "DescribeJobTemplate": {Verb: "Get", Resource: "JobTemplate", OutputListKey: "destinationPackageVersions", OutputItemKey: "abortConfig", Method: "GET", URI: "/job-templates/{jobTemplateId}"}, + "DescribeManagedJobTemplate": {Verb: "Get", Resource: "ManagedJobTemplate", OutputListKey: "documentParameters", OutputItemKey: "", Method: "GET", URI: "/managed-job-templates/{templateName}"}, + "DescribeMitigationAction": {Verb: "Get", Resource: "MitigationAction", OutputListKey: "", OutputItemKey: "actionParams", Method: "GET", URI: "/mitigationactions/actions/{actionName}"}, + "DescribeProvisioningTemplate": {Verb: "Get", Resource: "ProvisioningTemplate", OutputListKey: "", OutputItemKey: "preProvisioningHook", Method: "GET", URI: "/provisioning-templates/{templateName}"}, + "DescribeProvisioningTemplateVersion": {Verb: "Get", Resource: "ProvisioningTemplateVersion", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/provisioning-templates/{templateName}/versions/{versionId}"}, + "DescribeRoleAlias": {Verb: "Get", Resource: "RoleAlia", OutputListKey: "", OutputItemKey: "roleAliasDescription", Method: "GET", URI: "/role-aliases/{roleAlias}"}, + "DescribeScheduledAudit": {Verb: "Get", Resource: "ScheduledAudit", OutputListKey: "targetCheckNames", OutputItemKey: "", Method: "GET", URI: "/audit/scheduledaudits/{scheduledAuditName}"}, + "DescribeSecurityProfile": {Verb: "Get", Resource: "SecurityProfile", OutputListKey: "additionalMetricsToRetain", OutputItemKey: "metricsExportConfig", Method: "GET", URI: "/security-profiles/{securityProfileName}"}, + "DescribeStream": {Verb: "Get", Resource: "Stream", OutputListKey: "", OutputItemKey: "streamInfo", Method: "GET", URI: "/streams/{streamId}"}, + "DescribeThing": {Verb: "Get", Resource: "Thing", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/things/{thingName}"}, + "DescribeThingGroup": {Verb: "Get", Resource: "ThingGroup", OutputListKey: "", OutputItemKey: "thingGroupMetadata", Method: "GET", URI: "/thing-groups/{thingGroupName}"}, + "DescribeThingRegistrationTask": {Verb: "Get", Resource: "ThingRegistrationTask", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/thing-registration-tasks/{taskId}"}, + "DescribeThingType": {Verb: "Get", Resource: "ThingType", OutputListKey: "", OutputItemKey: "thingTypeMetadata", Method: "GET", URI: "/thing-types/{thingTypeName}"}, + "GetBehaviorModelTrainingSummaries": {Verb: "Get", Resource: "BehaviorModelTrainingSummary", OutputListKey: "summaries", OutputItemKey: "", Method: "GET", URI: "/behavior-model-training/summaries"}, + "GetBucketsAggregation": {Verb: "Get", Resource: "BucketsAggregation", OutputListKey: "buckets", OutputItemKey: "", Method: "POST", URI: "/indices/buckets"}, + "GetCardinality": {Verb: "Get", Resource: "Cardinality", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/indices/cardinality"}, + "GetCommand": {Verb: "Get", Resource: "Command", OutputListKey: "mandatoryParameters", OutputItemKey: "payload", Method: "GET", URI: "/commands/{commandId}"}, + "GetCommandExecution": {Verb: "Get", Resource: "CommandExecution", OutputListKey: "", OutputItemKey: "statusReason", Method: "GET", URI: "/command-executions/{executionId}"}, + "GetEffectivePolicies": {Verb: "Get", Resource: "EffectivePolicy", OutputListKey: "effectivePolicies", OutputItemKey: "", Method: "POST", URI: "/effective-policies"}, + "GetIndexingConfiguration": {Verb: "Get", Resource: "IndexingConfiguration", OutputListKey: "", OutputItemKey: "thingGroupIndexingConfiguration", Method: "GET", URI: "/indexing/config"}, + "GetJobDocument": {Verb: "Get", Resource: "JobDocument", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/jobs/{jobId}/job-document"}, + "GetLoggingOptions": {Verb: "Get", Resource: "LoggingOption", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/loggingOptions"}, + "GetOTAUpdate": {Verb: "Get", Resource: "OTAUpdate", OutputListKey: "", OutputItemKey: "otaUpdateInfo", Method: "GET", URI: "/otaUpdates/{otaUpdateId}"}, + "GetPackage": {Verb: "Get", Resource: "Package", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/packages/{packageName}"}, + "GetPackageConfiguration": {Verb: "Get", Resource: "PackageConfiguration", OutputListKey: "", OutputItemKey: "versionUpdateByJobsConfig", Method: "GET", URI: "/package-configuration"}, + "GetPackageVersion": {Verb: "Get", Resource: "PackageVersion", OutputListKey: "", OutputItemKey: "artifact", Method: "GET", URI: "/packages/{packageName}/versions/{versionName}"}, + "GetPercentiles": {Verb: "Get", Resource: "Percentile", OutputListKey: "percentiles", OutputItemKey: "", Method: "POST", URI: "/indices/percentiles"}, + "GetPolicy": {Verb: "Get", Resource: "Policy", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/policies/{policyName}"}, + "GetPolicyVersion": {Verb: "Get", Resource: "PolicyVersion", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/policies/{policyName}/version/{policyVersionId}"}, + "GetRegistrationCode": {Verb: "Get", Resource: "RegistrationCode", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/registrationcode"}, + "GetStatistics": {Verb: "Get", Resource: "Statistic", OutputListKey: "", OutputItemKey: "statistics", Method: "POST", URI: "/indices/statistics"}, + "GetThingConnectivityData": {Verb: "Get", Resource: "ThingConnectivityData", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/things/{thingName}/connectivity-data"}, + "GetTopicRule": {Verb: "Get", Resource: "TopicRule", OutputListKey: "", OutputItemKey: "rule", Method: "GET", URI: "/rules/{ruleName}"}, + "GetTopicRuleDestination": {Verb: "Get", Resource: "TopicRuleDestination", OutputListKey: "", OutputItemKey: "topicRuleDestination", Method: "GET", URI: "/destinations/{arn+}"}, + "GetV2LoggingOptions": {Verb: "Get", Resource: "V2LoggingOption", OutputListKey: "eventConfigurations", OutputItemKey: "", Method: "GET", URI: "/v2LoggingOptions"}, + "ListActiveViolations": {Verb: "List", Resource: "ActiveViolation", OutputListKey: "activeViolations", OutputItemKey: "", Method: "GET", URI: "/active-violations"}, + "ListAttachedPolicies": {Verb: "List", Resource: "AttachedPolicy", OutputListKey: "policies", OutputItemKey: "", Method: "POST", URI: "/attached-policies/{target}"}, + "ListAuditFindings": {Verb: "List", Resource: "AuditFinding", OutputListKey: "findings", OutputItemKey: "", Method: "POST", URI: "/audit/findings"}, + "ListAuditMitigationActionsExecutions": {Verb: "List", Resource: "AuditMitigationActionsExecution", OutputListKey: "actionsExecutions", OutputItemKey: "", Method: "GET", URI: "/audit/mitigationactions/executions"}, + "ListAuditMitigationActionsTasks": {Verb: "List", Resource: "AuditMitigationActionsTask", OutputListKey: "tasks", OutputItemKey: "", Method: "GET", URI: "/audit/mitigationactions/tasks"}, + "ListAuditSuppressions": {Verb: "List", Resource: "AuditSuppression", OutputListKey: "suppressions", OutputItemKey: "", Method: "POST", URI: "/audit/suppressions/list"}, + "ListAuditTasks": {Verb: "List", Resource: "AuditTask", OutputListKey: "tasks", OutputItemKey: "", Method: "GET", URI: "/audit/tasks"}, + "ListAuthorizers": {Verb: "List", Resource: "Authorizer", OutputListKey: "authorizers", OutputItemKey: "", Method: "GET", URI: "/authorizers"}, + "ListBillingGroups": {Verb: "List", Resource: "BillingGroup", OutputListKey: "billingGroups", OutputItemKey: "", Method: "GET", URI: "/billing-groups"}, + "ListCACertificates": {Verb: "List", Resource: "CACertificate", OutputListKey: "certificates", OutputItemKey: "", Method: "GET", URI: "/cacertificates"}, + "ListCertificateProviders": {Verb: "List", Resource: "CertificateProvider", OutputListKey: "certificateProviders", OutputItemKey: "", Method: "GET", URI: "/certificate-providers"}, + "ListCertificates": {Verb: "List", Resource: "Certificate", OutputListKey: "certificates", OutputItemKey: "", Method: "GET", URI: "/certificates"}, + "ListCertificatesByCA": {Verb: "List", Resource: "CertificatesByCA", OutputListKey: "certificates", OutputItemKey: "", Method: "GET", URI: "/certificates-by-ca/{caCertificateId}"}, + "ListCommandExecutions": {Verb: "List", Resource: "CommandExecution", OutputListKey: "commandExecutions", OutputItemKey: "", Method: "POST", URI: "/command-executions"}, + "ListCommands": {Verb: "List", Resource: "Command", OutputListKey: "commands", OutputItemKey: "", Method: "GET", URI: "/commands"}, + "ListCustomMetrics": {Verb: "List", Resource: "CustomMetric", OutputListKey: "metricNames", OutputItemKey: "", Method: "GET", URI: "/custom-metrics"}, + "ListDetectMitigationActionsExecutions": {Verb: "List", Resource: "DetectMitigationActionsExecution", OutputListKey: "actionsExecutions", OutputItemKey: "", Method: "GET", URI: "/detect/mitigationactions/executions"}, + "ListDetectMitigationActionsTasks": {Verb: "List", Resource: "DetectMitigationActionsTask", OutputListKey: "tasks", OutputItemKey: "", Method: "GET", URI: "/detect/mitigationactions/tasks"}, + "ListDimensions": {Verb: "List", Resource: "Dimension", OutputListKey: "dimensionNames", OutputItemKey: "", Method: "GET", URI: "/dimensions"}, + "ListDomainConfigurations": {Verb: "List", Resource: "DomainConfiguration", OutputListKey: "domainConfigurations", OutputItemKey: "", Method: "GET", URI: "/domainConfigurations"}, + "ListFleetMetrics": {Verb: "List", Resource: "FleetMetric", OutputListKey: "fleetMetrics", OutputItemKey: "", Method: "GET", URI: "/fleet-metrics"}, + "ListIndices": {Verb: "List", Resource: "Indice", OutputListKey: "indexNames", OutputItemKey: "", Method: "GET", URI: "/indices"}, + "ListJobExecutionsForJob": {Verb: "List", Resource: "JobExecutionsForJob", OutputListKey: "executionSummaries", OutputItemKey: "", Method: "GET", URI: "/jobs/{jobId}/things"}, + "ListJobExecutionsForThing": {Verb: "List", Resource: "JobExecutionsForThing", OutputListKey: "executionSummaries", OutputItemKey: "", Method: "GET", URI: "/things/{thingName}/jobs"}, + "ListJobTemplates": {Verb: "List", Resource: "JobTemplate", OutputListKey: "jobTemplates", OutputItemKey: "", Method: "GET", URI: "/job-templates"}, + "ListJobs": {Verb: "List", Resource: "Job", OutputListKey: "jobs", OutputItemKey: "", Method: "GET", URI: "/jobs"}, + "ListManagedJobTemplates": {Verb: "List", Resource: "ManagedJobTemplate", OutputListKey: "managedJobTemplates", OutputItemKey: "", Method: "GET", URI: "/managed-job-templates"}, + "ListMetricValues": {Verb: "List", Resource: "MetricValue", OutputListKey: "metricDatumList", OutputItemKey: "", Method: "GET", URI: "/metric-values"}, + "ListMitigationActions": {Verb: "List", Resource: "MitigationAction", OutputListKey: "actionIdentifiers", OutputItemKey: "", Method: "GET", URI: "/mitigationactions/actions"}, + "ListOTAUpdates": {Verb: "List", Resource: "OTAUpdate", OutputListKey: "otaUpdates", OutputItemKey: "", Method: "GET", URI: "/otaUpdates"}, + "ListOutgoingCertificates": {Verb: "List", Resource: "OutgoingCertificate", OutputListKey: "outgoingCertificates", OutputItemKey: "", Method: "GET", URI: "/certificates-out-going"}, + "ListPackageVersions": {Verb: "List", Resource: "PackageVersion", OutputListKey: "packageVersionSummaries", OutputItemKey: "", Method: "GET", URI: "/packages/{packageName}/versions"}, + "ListPackages": {Verb: "List", Resource: "Package", OutputListKey: "packageSummaries", OutputItemKey: "", Method: "GET", URI: "/packages"}, + "ListPolicies": {Verb: "List", Resource: "Policy", OutputListKey: "policies", OutputItemKey: "", Method: "GET", URI: "/policies"}, + "ListPolicyPrincipals": {Verb: "List", Resource: "PolicyPrincipal", OutputListKey: "principals", OutputItemKey: "", Method: "GET", URI: "/policy-principals"}, + "ListPolicyVersions": {Verb: "List", Resource: "PolicyVersion", OutputListKey: "policyVersions", OutputItemKey: "", Method: "GET", URI: "/policies/{policyName}/version"}, + "ListPrincipalPolicies": {Verb: "List", Resource: "PrincipalPolicy", OutputListKey: "policies", OutputItemKey: "", Method: "GET", URI: "/principal-policies"}, + "ListPrincipalThings": {Verb: "List", Resource: "PrincipalThing", OutputListKey: "things", OutputItemKey: "", Method: "GET", URI: "/principals/things"}, + "ListPrincipalThingsV2": {Verb: "List", Resource: "PrincipalThingsV2", OutputListKey: "principalThingObjects", OutputItemKey: "", Method: "GET", URI: "/principals/things-v2"}, + "ListProvisioningTemplateVersions": {Verb: "List", Resource: "ProvisioningTemplateVersion", OutputListKey: "versions", OutputItemKey: "", Method: "GET", URI: "/provisioning-templates/{templateName}/versions"}, + "ListProvisioningTemplates": {Verb: "List", Resource: "ProvisioningTemplate", OutputListKey: "templates", OutputItemKey: "", Method: "GET", URI: "/provisioning-templates"}, + "ListRelatedResourcesForAuditFinding": {Verb: "List", Resource: "RelatedResourcesForAuditFinding", OutputListKey: "relatedResources", OutputItemKey: "", Method: "GET", URI: "/audit/relatedResources"}, + "ListRoleAliases": {Verb: "List", Resource: "RoleAliase", OutputListKey: "roleAliases", OutputItemKey: "", Method: "GET", URI: "/role-aliases"}, + "ListSbomValidationResults": {Verb: "List", Resource: "SbomValidationResult", OutputListKey: "validationResultSummaries", OutputItemKey: "", Method: "GET", URI: "/packages/{packageName}/versions/{versionName}/sbom-validation-results"}, + "ListScheduledAudits": {Verb: "List", Resource: "ScheduledAudit", OutputListKey: "scheduledAudits", OutputItemKey: "", Method: "GET", URI: "/audit/scheduledaudits"}, + "ListSecurityProfiles": {Verb: "List", Resource: "SecurityProfile", OutputListKey: "securityProfileIdentifiers", OutputItemKey: "", Method: "GET", URI: "/security-profiles"}, + "ListSecurityProfilesForTarget": {Verb: "List", Resource: "SecurityProfilesForTarget", OutputListKey: "securityProfileTargetMappings", OutputItemKey: "", Method: "GET", URI: "/security-profiles-for-target"}, + "ListStreams": {Verb: "List", Resource: "Stream", OutputListKey: "streams", OutputItemKey: "", Method: "GET", URI: "/streams"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "tags", OutputItemKey: "", Method: "GET", URI: "/tags"}, + "ListTargetsForPolicy": {Verb: "List", Resource: "TargetsForPolicy", OutputListKey: "targets", OutputItemKey: "", Method: "POST", URI: "/policy-targets/{policyName}"}, + "ListTargetsForSecurityProfile": {Verb: "List", Resource: "TargetsForSecurityProfile", OutputListKey: "securityProfileTargets", OutputItemKey: "", Method: "GET", URI: "/security-profiles/{securityProfileName}/targets"}, + "ListThingGroups": {Verb: "List", Resource: "ThingGroup", OutputListKey: "thingGroups", OutputItemKey: "", Method: "GET", URI: "/thing-groups"}, + "ListThingGroupsForThing": {Verb: "List", Resource: "ThingGroupsForThing", OutputListKey: "thingGroups", OutputItemKey: "", Method: "GET", URI: "/things/{thingName}/thing-groups"}, + "ListThingPrincipals": {Verb: "List", Resource: "ThingPrincipal", OutputListKey: "principals", OutputItemKey: "", Method: "GET", URI: "/things/{thingName}/principals"}, + "ListThingPrincipalsV2": {Verb: "List", Resource: "ThingPrincipalsV2", OutputListKey: "thingPrincipalObjects", OutputItemKey: "", Method: "GET", URI: "/things/{thingName}/principals-v2"}, + "ListThingRegistrationTaskReports": {Verb: "List", Resource: "ThingRegistrationTaskReport", OutputListKey: "resourceLinks", OutputItemKey: "", Method: "GET", URI: "/thing-registration-tasks/{taskId}/reports"}, + "ListThingRegistrationTasks": {Verb: "List", Resource: "ThingRegistrationTask", OutputListKey: "taskIds", OutputItemKey: "", Method: "GET", URI: "/thing-registration-tasks"}, + "ListThingTypes": {Verb: "List", Resource: "ThingType", OutputListKey: "thingTypes", OutputItemKey: "", Method: "GET", URI: "/thing-types"}, + "ListThings": {Verb: "List", Resource: "Thing", OutputListKey: "things", OutputItemKey: "", Method: "GET", URI: "/things"}, + "ListThingsInBillingGroup": {Verb: "List", Resource: "ThingsInBillingGroup", OutputListKey: "things", OutputItemKey: "", Method: "GET", URI: "/billing-groups/{billingGroupName}/things"}, + "ListThingsInThingGroup": {Verb: "List", Resource: "ThingsInThingGroup", OutputListKey: "things", OutputItemKey: "", Method: "GET", URI: "/thing-groups/{thingGroupName}/things"}, + "ListTopicRuleDestinations": {Verb: "List", Resource: "TopicRuleDestination", OutputListKey: "destinationSummaries", OutputItemKey: "", Method: "GET", URI: "/destinations"}, + "ListTopicRules": {Verb: "List", Resource: "TopicRule", OutputListKey: "rules", OutputItemKey: "", Method: "GET", URI: "/rules"}, + "ListV2LoggingLevels": {Verb: "List", Resource: "V2LoggingLevel", OutputListKey: "logTargetConfigurations", OutputItemKey: "", Method: "GET", URI: "/v2LoggingLevel"}, + "ListViolationEvents": {Verb: "List", Resource: "ViolationEvent", OutputListKey: "violationEvents", OutputItemKey: "", Method: "GET", URI: "/violation-events"}, + "PutVerificationStateOnViolation": {Verb: "Update", Resource: "VerificationStateOnViolation", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/violations/verification-state/{violationId}"}, + "RegisterCACertificate": {Verb: "Create", Resource: "CACertificate", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/cacertificate"}, + "RegisterCertificate": {Verb: "Create", Resource: "Certificate", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/certificate/register"}, + "RegisterCertificateWithoutCA": {Verb: "Create", Resource: "CertificateWithoutCA", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/certificate/register-no-ca"}, + "RegisterThing": {Verb: "Create", Resource: "Thing", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/things"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/tags"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/untag"}, + "UpdateAccountAuditConfiguration": {Verb: "Update", Resource: "AccountAuditConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/audit/configuration"}, + "UpdateAuditSuppression": {Verb: "Update", Resource: "AuditSuppression", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/audit/suppressions/update"}, + "UpdateAuthorizer": {Verb: "Update", Resource: "Authorizer", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/authorizer/{authorizerName}"}, + "UpdateBillingGroup": {Verb: "Update", Resource: "BillingGroup", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/billing-groups/{billingGroupName}"}, + "UpdateCACertificate": {Verb: "Update", Resource: "CACertificate", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/cacertificate/{certificateId}"}, + "UpdateCertificate": {Verb: "Update", Resource: "Certificate", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/certificates/{certificateId}"}, + "UpdateCertificateProvider": {Verb: "Update", Resource: "CertificateProvider", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/certificate-providers/{certificateProviderName}"}, + "UpdateCommand": {Verb: "Update", Resource: "Command", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/commands/{commandId}"}, + "UpdateCustomMetric": {Verb: "Update", Resource: "CustomMetric", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/custom-metric/{metricName}"}, + "UpdateDimension": {Verb: "Update", Resource: "Dimension", OutputListKey: "stringValues", OutputItemKey: "", Method: "PATCH", URI: "/dimensions/{name}"}, + "UpdateDomainConfiguration": {Verb: "Update", Resource: "DomainConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/domainConfigurations/{domainConfigurationName}"}, + "UpdateDynamicThingGroup": {Verb: "Update", Resource: "DynamicThingGroup", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/dynamic-thing-groups/{thingGroupName}"}, + "UpdateEncryptionConfiguration": {Verb: "Update", Resource: "EncryptionConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/encryption-configuration"}, + "UpdateEventConfigurations": {Verb: "Update", Resource: "EventConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/event-configurations"}, + "UpdateFleetMetric": {Verb: "Update", Resource: "FleetMetric", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/fleet-metric/{metricName}"}, + "UpdateIndexingConfiguration": {Verb: "Update", Resource: "IndexingConfiguration", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/indexing/config"}, + "UpdateJob": {Verb: "Update", Resource: "Job", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/jobs/{jobId}"}, + "UpdateMitigationAction": {Verb: "Update", Resource: "MitigationAction", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/mitigationactions/actions/{actionName}"}, + "UpdatePackage": {Verb: "Update", Resource: "Package", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/packages/{packageName}"}, + "UpdatePackageConfiguration": {Verb: "Update", Resource: "PackageConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/package-configuration"}, + "UpdatePackageVersion": {Verb: "Update", Resource: "PackageVersion", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/packages/{packageName}/versions/{versionName}"}, + "UpdateProvisioningTemplate": {Verb: "Update", Resource: "ProvisioningTemplate", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/provisioning-templates/{templateName}"}, + "UpdateRoleAlias": {Verb: "Update", Resource: "RoleAlia", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/role-aliases/{roleAlias}"}, + "UpdateScheduledAudit": {Verb: "Update", Resource: "ScheduledAudit", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/audit/scheduledaudits/{scheduledAuditName}"}, + "UpdateSecurityProfile": {Verb: "Update", Resource: "SecurityProfile", OutputListKey: "additionalMetricsToRetain", OutputItemKey: "metricsExportConfig", Method: "PATCH", URI: "/security-profiles/{securityProfileName}"}, + "UpdateStream": {Verb: "Update", Resource: "Stream", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/streams/{streamId}"}, + "UpdateThing": {Verb: "Update", Resource: "Thing", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/things/{thingName}"}, + "UpdateThingGroup": {Verb: "Update", Resource: "ThingGroup", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/thing-groups/{thingGroupName}"}, + "UpdateThingGroupsForThing": {Verb: "Update", Resource: "ThingGroupsForThing", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/thing-groups/updateThingGroupsForThing"}, + "UpdateThingType": {Verb: "Update", Resource: "ThingType", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/thing-types/{thingTypeName}"}, + "UpdateTopicRuleDestination": {Verb: "Update", Resource: "TopicRuleDestination", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/destinations"}, + }) + crud.Register("iotdataplane", map[string]crud.OpMeta{ + "DeleteConnection": {Verb: "Delete", Resource: "Connection", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/connections/{clientId}"}, + "DeleteThingShadow": {Verb: "Delete", Resource: "ThingShadow", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/things/{thingName}/shadow"}, + "GetRetainedMessage": {Verb: "Get", Resource: "RetainedMessage", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/retainedMessage/{topic}"}, + "GetThingShadow": {Verb: "Get", Resource: "ThingShadow", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/things/{thingName}/shadow"}, + "ListNamedShadowsForThing": {Verb: "List", Resource: "NamedShadowsForThing", OutputListKey: "results", OutputItemKey: "", Method: "GET", URI: "/api/things/shadow/ListNamedShadowsForThing/{thingName}"}, + "ListRetainedMessages": {Verb: "List", Resource: "RetainedMessage", OutputListKey: "retainedTopics", OutputItemKey: "", Method: "GET", URI: "/retainedMessage"}, + "UpdateThingShadow": {Verb: "Update", Resource: "ThingShadow", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/things/{thingName}/shadow"}, + }) + crud.Register("iotwireless", map[string]crud.OpMeta{ + "CreateDestination": {Verb: "Create", Resource: "Destination", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/destinations"}, + "CreateDeviceProfile": {Verb: "Create", Resource: "DeviceProfile", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/device-profiles"}, + "CreateFuotaTask": {Verb: "Create", Resource: "FuotaTask", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/fuota-tasks"}, + "CreateMulticastGroup": {Verb: "Create", Resource: "MulticastGroup", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/multicast-groups"}, + "CreateNetworkAnalyzerConfiguration": {Verb: "Create", Resource: "NetworkAnalyzerConfiguration", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/network-analyzer-configurations"}, + "CreateServiceProfile": {Verb: "Create", Resource: "ServiceProfile", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/service-profiles"}, + "CreateWirelessDevice": {Verb: "Create", Resource: "WirelessDevice", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/wireless-devices"}, + "CreateWirelessGateway": {Verb: "Create", Resource: "WirelessGateway", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/wireless-gateways"}, + "CreateWirelessGatewayTask": {Verb: "Create", Resource: "WirelessGatewayTask", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/wireless-gateways/{Id}/tasks"}, + "CreateWirelessGatewayTaskDefinition": {Verb: "Create", Resource: "WirelessGatewayTaskDefinition", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/wireless-gateway-task-definitions"}, + "DeleteDestination": {Verb: "Delete", Resource: "Destination", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/destinations/{Name}"}, + "DeleteDeviceProfile": {Verb: "Delete", Resource: "DeviceProfile", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/device-profiles/{Id}"}, + "DeleteFuotaTask": {Verb: "Delete", Resource: "FuotaTask", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/fuota-tasks/{Id}"}, + "DeleteMulticastGroup": {Verb: "Delete", Resource: "MulticastGroup", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/multicast-groups/{Id}"}, + "DeleteNetworkAnalyzerConfiguration": {Verb: "Delete", Resource: "NetworkAnalyzerConfiguration", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/network-analyzer-configurations/{ConfigurationName}"}, + "DeleteQueuedMessages": {Verb: "Delete", Resource: "QueuedMessage", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/wireless-devices/{Id}/data"}, + "DeleteServiceProfile": {Verb: "Delete", Resource: "ServiceProfile", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/service-profiles/{Id}"}, + "DeleteWirelessDevice": {Verb: "Delete", Resource: "WirelessDevice", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/wireless-devices/{Id}"}, + "DeleteWirelessDeviceImportTask": {Verb: "Delete", Resource: "WirelessDeviceImportTask", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/wireless_device_import_task/{Id}"}, + "DeleteWirelessGateway": {Verb: "Delete", Resource: "WirelessGateway", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/wireless-gateways/{Id}"}, + "DeleteWirelessGatewayTask": {Verb: "Delete", Resource: "WirelessGatewayTask", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/wireless-gateways/{Id}/tasks"}, + "DeleteWirelessGatewayTaskDefinition": {Verb: "Delete", Resource: "WirelessGatewayTaskDefinition", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/wireless-gateway-task-definitions/{Id}"}, + "DeregisterWirelessDevice": {Verb: "Delete", Resource: "WirelessDevice", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/wireless-devices/{Identifier}/deregister"}, + "GetDestination": {Verb: "Get", Resource: "Destination", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/destinations/{Name}"}, + "GetDeviceProfile": {Verb: "Get", Resource: "DeviceProfile", OutputListKey: "", OutputItemKey: "LoRaWAN", Method: "GET", URI: "/device-profiles/{Id}"}, + "GetEventConfigurationByResourceTypes": {Verb: "Get", Resource: "EventConfigurationByResourceType", OutputListKey: "", OutputItemKey: "ConnectionStatus", Method: "GET", URI: "/event-configurations-resource-types"}, + "GetFuotaTask": {Verb: "Get", Resource: "FuotaTask", OutputListKey: "", OutputItemKey: "LoRaWAN", Method: "GET", URI: "/fuota-tasks/{Id}"}, + "GetLogLevelsByResourceTypes": {Verb: "Get", Resource: "LogLevelsByResourceType", OutputListKey: "FuotaTaskLogOptions", OutputItemKey: "", Method: "GET", URI: "/log-levels"}, + "GetMetricConfiguration": {Verb: "Get", Resource: "MetricConfiguration", OutputListKey: "", OutputItemKey: "SummaryMetric", Method: "GET", URI: "/metric-configuration"}, + "GetMetrics": {Verb: "Get", Resource: "Metric", OutputListKey: "SummaryMetricQueryResults", OutputItemKey: "", Method: "POST", URI: "/metrics"}, + "GetMulticastGroup": {Verb: "Get", Resource: "MulticastGroup", OutputListKey: "", OutputItemKey: "LoRaWAN", Method: "GET", URI: "/multicast-groups/{Id}"}, + "GetMulticastGroupSession": {Verb: "Get", Resource: "MulticastGroupSession", OutputListKey: "", OutputItemKey: "LoRaWAN", Method: "GET", URI: "/multicast-groups/{Id}/session"}, + "GetNetworkAnalyzerConfiguration": {Verb: "Get", Resource: "NetworkAnalyzerConfiguration", OutputListKey: "MulticastGroups", OutputItemKey: "TraceContent", Method: "GET", URI: "/network-analyzer-configurations/{ConfigurationName}"}, + "GetPartnerAccount": {Verb: "Get", Resource: "PartnerAccount", OutputListKey: "", OutputItemKey: "Sidewalk", Method: "GET", URI: "/partner-accounts/{PartnerAccountId}"}, + "GetPosition": {Verb: "Get", Resource: "Position", OutputListKey: "Position", OutputItemKey: "Accuracy", Method: "GET", URI: "/positions/{ResourceIdentifier}"}, + "GetPositionConfiguration": {Verb: "Get", Resource: "PositionConfiguration", OutputListKey: "", OutputItemKey: "Solvers", Method: "GET", URI: "/position-configurations/{ResourceIdentifier}"}, + "GetPositionEstimate": {Verb: "Get", Resource: "PositionEstimate", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/position-estimate"}, + "GetResourceEventConfiguration": {Verb: "Get", Resource: "ResourceEventConfiguration", OutputListKey: "", OutputItemKey: "ConnectionStatus", Method: "GET", URI: "/event-configurations/{Identifier}"}, + "GetResourceLogLevel": {Verb: "Get", Resource: "ResourceLogLevel", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/log-levels/{ResourceIdentifier}"}, + "GetResourcePosition": {Verb: "Get", Resource: "ResourcePosition", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/resource-positions/{ResourceIdentifier}"}, + "GetServiceEndpoint": {Verb: "Get", Resource: "ServiceEndpoint", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/service-endpoint"}, + "GetServiceProfile": {Verb: "Get", Resource: "ServiceProfile", OutputListKey: "", OutputItemKey: "LoRaWAN", Method: "GET", URI: "/service-profiles/{Id}"}, + "GetWirelessDevice": {Verb: "Get", Resource: "WirelessDevice", OutputListKey: "", OutputItemKey: "LoRaWAN", Method: "GET", URI: "/wireless-devices/{Identifier}"}, + "GetWirelessDeviceImportTask": {Verb: "Get", Resource: "WirelessDeviceImportTask", OutputListKey: "", OutputItemKey: "Sidewalk", Method: "GET", URI: "/wireless_device_import_task/{Id}"}, + "GetWirelessDeviceStatistics": {Verb: "Get", Resource: "WirelessDeviceStatistic", OutputListKey: "", OutputItemKey: "LoRaWAN", Method: "GET", URI: "/wireless-devices/{WirelessDeviceId}/statistics"}, + "GetWirelessGateway": {Verb: "Get", Resource: "WirelessGateway", OutputListKey: "", OutputItemKey: "LoRaWAN", Method: "GET", URI: "/wireless-gateways/{Identifier}"}, + "GetWirelessGatewayCertificate": {Verb: "Get", Resource: "WirelessGatewayCertificate", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/wireless-gateways/{Id}/certificate"}, + "GetWirelessGatewayFirmwareInformation": {Verb: "Get", Resource: "WirelessGatewayFirmwareInformation", OutputListKey: "", OutputItemKey: "LoRaWAN", Method: "GET", URI: "/wireless-gateways/{Id}/firmware-information"}, + "GetWirelessGatewayStatistics": {Verb: "Get", Resource: "WirelessGatewayStatistic", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/wireless-gateways/{WirelessGatewayId}/statistics"}, + "GetWirelessGatewayTask": {Verb: "Get", Resource: "WirelessGatewayTask", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/wireless-gateways/{Id}/tasks"}, + "GetWirelessGatewayTaskDefinition": {Verb: "Get", Resource: "WirelessGatewayTaskDefinition", OutputListKey: "", OutputItemKey: "Update", Method: "GET", URI: "/wireless-gateway-task-definitions/{Id}"}, + "ListDestinations": {Verb: "List", Resource: "Destination", OutputListKey: "DestinationList", OutputItemKey: "", Method: "GET", URI: "/destinations"}, + "ListDeviceProfiles": {Verb: "List", Resource: "DeviceProfile", OutputListKey: "DeviceProfileList", OutputItemKey: "", Method: "GET", URI: "/device-profiles"}, + "ListDevicesForWirelessDeviceImportTask": {Verb: "List", Resource: "DevicesForWirelessDeviceImportTask", OutputListKey: "ImportedWirelessDeviceList", OutputItemKey: "Sidewalk", Method: "GET", URI: "/wireless_device_import_task"}, + "ListEventConfigurations": {Verb: "List", Resource: "EventConfiguration", OutputListKey: "EventConfigurationsList", OutputItemKey: "", Method: "GET", URI: "/event-configurations"}, + "ListFuotaTasks": {Verb: "List", Resource: "FuotaTask", OutputListKey: "FuotaTaskList", OutputItemKey: "", Method: "GET", URI: "/fuota-tasks"}, + "ListMulticastGroups": {Verb: "List", Resource: "MulticastGroup", OutputListKey: "MulticastGroupList", OutputItemKey: "", Method: "GET", URI: "/multicast-groups"}, + "ListMulticastGroupsByFuotaTask": {Verb: "List", Resource: "MulticastGroupsByFuotaTask", OutputListKey: "MulticastGroupList", OutputItemKey: "", Method: "GET", URI: "/fuota-tasks/{Id}/multicast-groups"}, + "ListNetworkAnalyzerConfigurations": {Verb: "List", Resource: "NetworkAnalyzerConfiguration", OutputListKey: "NetworkAnalyzerConfigurationList", OutputItemKey: "", Method: "GET", URI: "/network-analyzer-configurations"}, + "ListPartnerAccounts": {Verb: "List", Resource: "PartnerAccount", OutputListKey: "Sidewalk", OutputItemKey: "", Method: "GET", URI: "/partner-accounts"}, + "ListPositionConfigurations": {Verb: "List", Resource: "PositionConfiguration", OutputListKey: "PositionConfigurationList", OutputItemKey: "", Method: "GET", URI: "/position-configurations"}, + "ListQueuedMessages": {Verb: "List", Resource: "QueuedMessage", OutputListKey: "DownlinkQueueMessagesList", OutputItemKey: "", Method: "GET", URI: "/wireless-devices/{Id}/data"}, + "ListServiceProfiles": {Verb: "List", Resource: "ServiceProfile", OutputListKey: "ServiceProfileList", OutputItemKey: "", Method: "GET", URI: "/service-profiles"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "Tags", OutputItemKey: "", Method: "GET", URI: "/tags"}, + "ListWirelessDeviceImportTasks": {Verb: "List", Resource: "WirelessDeviceImportTask", OutputListKey: "WirelessDeviceImportTaskList", OutputItemKey: "", Method: "GET", URI: "/wireless_device_import_tasks"}, + "ListWirelessDevices": {Verb: "List", Resource: "WirelessDevice", OutputListKey: "WirelessDeviceList", OutputItemKey: "", Method: "GET", URI: "/wireless-devices"}, + "ListWirelessGatewayTaskDefinitions": {Verb: "List", Resource: "WirelessGatewayTaskDefinition", OutputListKey: "TaskDefinitions", OutputItemKey: "", Method: "GET", URI: "/wireless-gateway-task-definitions"}, + "ListWirelessGateways": {Verb: "List", Resource: "WirelessGateway", OutputListKey: "WirelessGatewayList", OutputItemKey: "", Method: "GET", URI: "/wireless-gateways"}, + "PutPositionConfiguration": {Verb: "Update", Resource: "PositionConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/position-configurations/{ResourceIdentifier}"}, + "PutResourceLogLevel": {Verb: "Update", Resource: "ResourceLogLevel", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/log-levels/{ResourceIdentifier}"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/tags"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/tags"}, + "UpdateDestination": {Verb: "Update", Resource: "Destination", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/destinations/{Name}"}, + "UpdateEventConfigurationByResourceTypes": {Verb: "Update", Resource: "EventConfigurationByResourceType", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/event-configurations-resource-types"}, + "UpdateFuotaTask": {Verb: "Update", Resource: "FuotaTask", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/fuota-tasks/{Id}"}, + "UpdateLogLevelsByResourceTypes": {Verb: "Update", Resource: "LogLevelsByResourceType", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/log-levels"}, + "UpdateMetricConfiguration": {Verb: "Update", Resource: "MetricConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/metric-configuration"}, + "UpdateMulticastGroup": {Verb: "Update", Resource: "MulticastGroup", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/multicast-groups/{Id}"}, + "UpdateNetworkAnalyzerConfiguration": {Verb: "Update", Resource: "NetworkAnalyzerConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/network-analyzer-configurations/{ConfigurationName}"}, + "UpdatePartnerAccount": {Verb: "Update", Resource: "PartnerAccount", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/partner-accounts/{PartnerAccountId}"}, + "UpdatePosition": {Verb: "Update", Resource: "Position", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/positions/{ResourceIdentifier}"}, + "UpdateResourceEventConfiguration": {Verb: "Update", Resource: "ResourceEventConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/event-configurations/{Identifier}"}, + "UpdateResourcePosition": {Verb: "Update", Resource: "ResourcePosition", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/resource-positions/{ResourceIdentifier}"}, + "UpdateWirelessDevice": {Verb: "Update", Resource: "WirelessDevice", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/wireless-devices/{Id}"}, + "UpdateWirelessDeviceImportTask": {Verb: "Update", Resource: "WirelessDeviceImportTask", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/wireless_device_import_task/{Id}"}, + "UpdateWirelessGateway": {Verb: "Update", Resource: "WirelessGateway", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/wireless-gateways/{Id}"}, + }) + crud.Register("kafka", map[string]crud.OpMeta{ + "CreateCluster": {Verb: "Create", Resource: "Cluster", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/clusters"}, + "CreateClusterV2": {Verb: "Create", Resource: "ClusterV2", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/api/v2/clusters"}, + "CreateConfiguration": {Verb: "Create", Resource: "Configuration", OutputListKey: "", OutputItemKey: "LatestRevision", Method: "POST", URI: "/v1/configurations"}, + "CreateReplicator": {Verb: "Create", Resource: "Replicator", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/replication/v1/replicators"}, + "CreateTopic": {Verb: "Create", Resource: "Topic", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/clusters/{ClusterArn}/topics"}, + "CreateVpcConnection": {Verb: "Create", Resource: "VpcConnection", OutputListKey: "ClientSubnets", OutputItemKey: "", Method: "POST", URI: "/v1/vpc-connection"}, + "DeleteCluster": {Verb: "Delete", Resource: "Cluster", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v1/clusters/{ClusterArn}"}, + "DeleteClusterPolicy": {Verb: "Delete", Resource: "ClusterPolicy", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v1/clusters/{ClusterArn}/policy"}, + "DeleteConfiguration": {Verb: "Delete", Resource: "Configuration", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v1/configurations/{Arn}"}, + "DeleteReplicator": {Verb: "Delete", Resource: "Replicator", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/replication/v1/replicators/{ReplicatorArn}"}, + "DeleteTopic": {Verb: "Delete", Resource: "Topic", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v1/clusters/{ClusterArn}/topics/{TopicName}"}, + "DeleteVpcConnection": {Verb: "Delete", Resource: "VpcConnection", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v1/vpc-connection/{Arn}"}, + "DescribeCluster": {Verb: "Get", Resource: "Cluster", OutputListKey: "", OutputItemKey: "ClusterInfo", Method: "GET", URI: "/v1/clusters/{ClusterArn}"}, + "DescribeClusterOperation": {Verb: "Get", Resource: "ClusterOperation", OutputListKey: "", OutputItemKey: "ClusterOperationInfo", Method: "GET", URI: "/v1/operations/{ClusterOperationArn}"}, + "DescribeClusterOperationV2": {Verb: "Get", Resource: "ClusterOperationV2", OutputListKey: "", OutputItemKey: "ClusterOperationInfo", Method: "GET", URI: "/api/v2/operations/{ClusterOperationArn}"}, + "DescribeClusterV2": {Verb: "Get", Resource: "ClusterV2", OutputListKey: "", OutputItemKey: "ClusterInfo", Method: "GET", URI: "/api/v2/clusters/{ClusterArn}"}, + "DescribeConfiguration": {Verb: "Get", Resource: "Configuration", OutputListKey: "KafkaVersions", OutputItemKey: "LatestRevision", Method: "GET", URI: "/v1/configurations/{Arn}"}, + "DescribeConfigurationRevision": {Verb: "Get", Resource: "ConfigurationRevision", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v1/configurations/{Arn}/revisions/{Revision}"}, + "DescribeReplicator": {Verb: "Get", Resource: "Replicator", OutputListKey: "KafkaClusters", OutputItemKey: "StateInfo", Method: "GET", URI: "/replication/v1/replicators/{ReplicatorArn}"}, + "DescribeTopic": {Verb: "Get", Resource: "Topic", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v1/clusters/{ClusterArn}/topics/{TopicName}"}, + "DescribeTopicPartitions": {Verb: "Get", Resource: "TopicPartition", OutputListKey: "Partitions", OutputItemKey: "", Method: "GET", URI: "/v1/clusters/{ClusterArn}/topics/{TopicName}/partitions"}, + "DescribeVpcConnection": {Verb: "Get", Resource: "VpcConnection", OutputListKey: "SecurityGroups", OutputItemKey: "", Method: "GET", URI: "/v1/vpc-connection/{Arn}"}, + "GetBootstrapBrokers": {Verb: "Get", Resource: "BootstrapBroker", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v1/clusters/{ClusterArn}/bootstrap-brokers"}, + "GetClusterPolicy": {Verb: "Get", Resource: "ClusterPolicy", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v1/clusters/{ClusterArn}/policy"}, + "GetCompatibleKafkaVersions": {Verb: "Get", Resource: "CompatibleKafkaVersion", OutputListKey: "CompatibleKafkaVersions", OutputItemKey: "", Method: "GET", URI: "/v1/compatible-kafka-versions"}, + "ListClientVpcConnections": {Verb: "List", Resource: "ClientVpcConnection", OutputListKey: "ClientVpcConnections", OutputItemKey: "", Method: "GET", URI: "/v1/clusters/{ClusterArn}/client-vpc-connections"}, + "ListClusterOperations": {Verb: "List", Resource: "ClusterOperation", OutputListKey: "ClusterOperationInfoList", OutputItemKey: "", Method: "GET", URI: "/v1/clusters/{ClusterArn}/operations"}, + "ListClusterOperationsV2": {Verb: "List", Resource: "ClusterOperationsV2", OutputListKey: "ClusterOperationInfoList", OutputItemKey: "", Method: "GET", URI: "/api/v2/clusters/{ClusterArn}/operations"}, + "ListClusters": {Verb: "List", Resource: "Cluster", OutputListKey: "ClusterInfoList", OutputItemKey: "", Method: "GET", URI: "/v1/clusters"}, + "ListClustersV2": {Verb: "List", Resource: "ClustersV2", OutputListKey: "ClusterInfoList", OutputItemKey: "", Method: "GET", URI: "/api/v2/clusters"}, + "ListConfigurationRevisions": {Verb: "List", Resource: "ConfigurationRevision", OutputListKey: "Revisions", OutputItemKey: "", Method: "GET", URI: "/v1/configurations/{Arn}/revisions"}, + "ListConfigurations": {Verb: "List", Resource: "Configuration", OutputListKey: "Configurations", OutputItemKey: "", Method: "GET", URI: "/v1/configurations"}, + "ListKafkaVersions": {Verb: "List", Resource: "KafkaVersion", OutputListKey: "KafkaVersions", OutputItemKey: "", Method: "GET", URI: "/v1/kafka-versions"}, + "ListNodes": {Verb: "List", Resource: "Node", OutputListKey: "NodeInfoList", OutputItemKey: "", Method: "GET", URI: "/v1/clusters/{ClusterArn}/nodes"}, + "ListReplicators": {Verb: "List", Resource: "Replicator", OutputListKey: "Replicators", OutputItemKey: "", Method: "GET", URI: "/replication/v1/replicators"}, + "ListScramSecrets": {Verb: "List", Resource: "ScramSecret", OutputListKey: "SecretArnList", OutputItemKey: "", Method: "GET", URI: "/v1/clusters/{ClusterArn}/scram-secrets"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v1/tags/{ResourceArn}"}, + "ListTopics": {Verb: "List", Resource: "Topic", OutputListKey: "Topics", OutputItemKey: "", Method: "GET", URI: "/v1/clusters/{ClusterArn}/topics"}, + "ListVpcConnections": {Verb: "List", Resource: "VpcConnection", OutputListKey: "VpcConnections", OutputItemKey: "", Method: "GET", URI: "/v1/vpc-connections"}, + "PutClusterPolicy": {Verb: "Update", Resource: "ClusterPolicy", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v1/clusters/{ClusterArn}/policy"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/tags/{ResourceArn}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v1/tags/{ResourceArn}"}, + "UpdateBrokerCount": {Verb: "Update", Resource: "BrokerCount", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v1/clusters/{ClusterArn}/nodes/count"}, + "UpdateBrokerStorage": {Verb: "Update", Resource: "BrokerStorage", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v1/clusters/{ClusterArn}/nodes/storage"}, + "UpdateBrokerType": {Verb: "Update", Resource: "BrokerType", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v1/clusters/{ClusterArn}/nodes/type"}, + "UpdateClusterConfiguration": {Verb: "Update", Resource: "ClusterConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v1/clusters/{ClusterArn}/configuration"}, + "UpdateClusterKafkaVersion": {Verb: "Update", Resource: "ClusterKafkaVersion", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v1/clusters/{ClusterArn}/version"}, + "UpdateConfiguration": {Verb: "Update", Resource: "Configuration", OutputListKey: "", OutputItemKey: "LatestRevision", Method: "PUT", URI: "/v1/configurations/{Arn}"}, + "UpdateConnectivity": {Verb: "Update", Resource: "Connectivity", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v1/clusters/{ClusterArn}/connectivity"}, + "UpdateMonitoring": {Verb: "Update", Resource: "Monitoring", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v1/clusters/{ClusterArn}/monitoring"}, + "UpdateRebalancing": {Verb: "Update", Resource: "Rebalancing", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v1/clusters/{ClusterArn}/rebalancing"}, + "UpdateReplicationInfo": {Verb: "Update", Resource: "ReplicationInfo", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/replication/v1/replicators/{ReplicatorArn}/replication-info"}, + "UpdateSecurity": {Verb: "Update", Resource: "Security", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/v1/clusters/{ClusterArn}/security"}, + "UpdateStorage": {Verb: "Update", Resource: "Storage", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v1/clusters/{ClusterArn}/storage"}, + "UpdateTopic": {Verb: "Update", Resource: "Topic", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v1/clusters/{ClusterArn}/topics/{TopicName}"}, }) crud.Register("kendra", map[string]crud.OpMeta{ "BatchGetDocumentStatus": {Verb: "List", Resource: "DocumentStatu", OutputListKey: "DocumentStatusList", OutputItemKey: ""}, @@ -1503,14 +3034,14 @@ func init() { "UpdateThesaurus": {Verb: "Update", Resource: "Thesauru", OutputListKey: "", OutputItemKey: ""}, }) crud.Register("kendraranking", map[string]crud.OpMeta{ - "CreateRescoreExecutionPlan": {Verb: "Create", Resource: "RescoreExecutionPlan", OutputListKey: "", OutputItemKey: ""}, - "DeleteRescoreExecutionPlan": {Verb: "Delete", Resource: "RescoreExecutionPlan", OutputListKey: "", OutputItemKey: ""}, - "DescribeRescoreExecutionPlan": {Verb: "Get", Resource: "RescoreExecutionPlan", OutputListKey: "", OutputItemKey: "CapacityUnits"}, - "ListRescoreExecutionPlans": {Verb: "List", Resource: "RescoreExecutionPlan", OutputListKey: "SummaryItems", OutputItemKey: ""}, + "CreateRescoreExecutionPlan": {Verb: "Create", Resource: "RescoreExecutionPlan", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/rescore-execution-plans"}, + "DeleteRescoreExecutionPlan": {Verb: "Delete", Resource: "RescoreExecutionPlan", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/rescore-execution-plans/{Id}"}, + "DescribeRescoreExecutionPlan": {Verb: "Get", Resource: "RescoreExecutionPlan", OutputListKey: "", OutputItemKey: "CapacityUnits", Method: "GET", URI: "/rescore-execution-plans/{Id}"}, + "ListRescoreExecutionPlans": {Verb: "List", Resource: "RescoreExecutionPlan", OutputListKey: "SummaryItems", OutputItemKey: "", Method: "GET", URI: "/rescore-execution-plans"}, "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "Tags", OutputItemKey: ""}, "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: ""}, "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: ""}, - "UpdateRescoreExecutionPlan": {Verb: "Update", Resource: "RescoreExecutionPlan", OutputListKey: "", OutputItemKey: ""}, + "UpdateRescoreExecutionPlan": {Verb: "Update", Resource: "RescoreExecutionPlan", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/rescore-execution-plans/{Id}"}, }) crud.Register("kinesis", map[string]crud.OpMeta{ "CreateStream": {Verb: "Create", Resource: "Stream", OutputListKey: "", OutputItemKey: ""}, @@ -1596,6 +3127,275 @@ func init() { "UpdateKeyDescription": {Verb: "Update", Resource: "KeyDescription", OutputListKey: "", OutputItemKey: ""}, "UpdatePrimaryRegion": {Verb: "Update", Resource: "PrimaryRegion", OutputListKey: "", OutputItemKey: ""}, }) + crud.Register("lakeformation", map[string]crud.OpMeta{ + "CreateDataCellsFilter": {Verb: "Create", Resource: "DataCellsFilter", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/CreateDataCellsFilter"}, + "CreateLFTag": {Verb: "Create", Resource: "LFTag", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/CreateLFTag"}, + "CreateLFTagExpression": {Verb: "Create", Resource: "LFTagExpression", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/CreateLFTagExpression"}, + "CreateLakeFormationIdentityCenterConfiguration": {Verb: "Create", Resource: "LakeFormationIdentityCenterConfiguration", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/CreateLakeFormationIdentityCenterConfiguration"}, + "CreateLakeFormationOptIn": {Verb: "Create", Resource: "LakeFormationOptIn", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/CreateLakeFormationOptIn"}, + "DeleteDataCellsFilter": {Verb: "Delete", Resource: "DataCellsFilter", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/DeleteDataCellsFilter"}, + "DeleteLFTag": {Verb: "Delete", Resource: "LFTag", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/DeleteLFTag"}, + "DeleteLFTagExpression": {Verb: "Delete", Resource: "LFTagExpression", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/DeleteLFTagExpression"}, + "DeleteLakeFormationIdentityCenterConfiguration": {Verb: "Delete", Resource: "LakeFormationIdentityCenterConfiguration", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/DeleteLakeFormationIdentityCenterConfiguration"}, + "DeleteLakeFormationOptIn": {Verb: "Delete", Resource: "LakeFormationOptIn", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/DeleteLakeFormationOptIn"}, + "DeleteObjectsOnCancel": {Verb: "Delete", Resource: "ObjectsOnCancel", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/DeleteObjectsOnCancel"}, + "DeregisterResource": {Verb: "Delete", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/DeregisterResource"}, + "DescribeLakeFormationIdentityCenterConfiguration": {Verb: "Get", Resource: "LakeFormationIdentityCenterConfiguration", OutputListKey: "ServiceIntegrations", OutputItemKey: "ExternalFiltering", Method: "POST", URI: "/DescribeLakeFormationIdentityCenterConfiguration"}, + "DescribeResource": {Verb: "Get", Resource: "Resource", OutputListKey: "", OutputItemKey: "ResourceInfo", Method: "POST", URI: "/DescribeResource"}, + "DescribeTransaction": {Verb: "Get", Resource: "Transaction", OutputListKey: "", OutputItemKey: "TransactionDescription", Method: "POST", URI: "/DescribeTransaction"}, + "GetDataCellsFilter": {Verb: "Get", Resource: "DataCellsFilter", OutputListKey: "", OutputItemKey: "DataCellsFilter", Method: "POST", URI: "/GetDataCellsFilter"}, + "GetDataLakePrincipal": {Verb: "Get", Resource: "DataLakePrincipal", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/GetDataLakePrincipal"}, + "GetDataLakeSettings": {Verb: "Get", Resource: "DataLakeSetting", OutputListKey: "", OutputItemKey: "DataLakeSettings", Method: "POST", URI: "/GetDataLakeSettings"}, + "GetEffectivePermissionsForPath": {Verb: "Get", Resource: "EffectivePermissionsForPath", OutputListKey: "Permissions", OutputItemKey: "", Method: "POST", URI: "/GetEffectivePermissionsForPath"}, + "GetLFTag": {Verb: "Get", Resource: "LFTag", OutputListKey: "TagValues", OutputItemKey: "", Method: "POST", URI: "/GetLFTag"}, + "GetLFTagExpression": {Verb: "Get", Resource: "LFTagExpression", OutputListKey: "Expression", OutputItemKey: "", Method: "POST", URI: "/GetLFTagExpression"}, + "GetQueryState": {Verb: "Get", Resource: "QueryState", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/GetQueryState"}, + "GetQueryStatistics": {Verb: "Get", Resource: "QueryStatistic", OutputListKey: "", OutputItemKey: "ExecutionStatistics", Method: "POST", URI: "/GetQueryStatistics"}, + "GetResourceLFTags": {Verb: "Get", Resource: "ResourceLFTag", OutputListKey: "LFTagOnDatabase", OutputItemKey: "", Method: "POST", URI: "/GetResourceLFTags"}, + "GetTableObjects": {Verb: "Get", Resource: "TableObject", OutputListKey: "Objects", OutputItemKey: "", Method: "POST", URI: "/GetTableObjects"}, + "GetTemporaryDataLocationCredentials": {Verb: "Get", Resource: "TemporaryDataLocationCredential", OutputListKey: "AccessibleDataLocations", OutputItemKey: "Credentials", Method: "POST", URI: "/GetTemporaryDataLocationCredentials"}, + "GetTemporaryGluePartitionCredentials": {Verb: "Get", Resource: "TemporaryGluePartitionCredential", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/GetTemporaryGluePartitionCredentials"}, + "GetTemporaryGlueTableCredentials": {Verb: "Get", Resource: "TemporaryGlueTableCredential", OutputListKey: "VendedS3Path", OutputItemKey: "", Method: "POST", URI: "/GetTemporaryGlueTableCredentials"}, + "GetWorkUnitResults": {Verb: "Get", Resource: "WorkUnitResult", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/GetWorkUnitResults"}, + "GetWorkUnits": {Verb: "Get", Resource: "WorkUnit", OutputListKey: "WorkUnitRanges", OutputItemKey: "", Method: "POST", URI: "/GetWorkUnits"}, + "ListDataCellsFilter": {Verb: "List", Resource: "DataCellsFilter", OutputListKey: "DataCellsFilters", OutputItemKey: "", Method: "POST", URI: "/ListDataCellsFilter"}, + "ListLFTagExpressions": {Verb: "List", Resource: "LFTagExpression", OutputListKey: "LFTagExpressions", OutputItemKey: "", Method: "POST", URI: "/ListLFTagExpressions"}, + "ListLFTags": {Verb: "List", Resource: "LFTag", OutputListKey: "LFTags", OutputItemKey: "", Method: "POST", URI: "/ListLFTags"}, + "ListLakeFormationOptIns": {Verb: "List", Resource: "LakeFormationOptIn", OutputListKey: "LakeFormationOptInsInfoList", OutputItemKey: "", Method: "POST", URI: "/ListLakeFormationOptIns"}, + "ListPermissions": {Verb: "List", Resource: "Permission", OutputListKey: "PrincipalResourcePermissions", OutputItemKey: "", Method: "POST", URI: "/ListPermissions"}, + "ListResources": {Verb: "List", Resource: "Resource", OutputListKey: "ResourceInfoList", OutputItemKey: "", Method: "POST", URI: "/ListResources"}, + "ListTableStorageOptimizers": {Verb: "List", Resource: "TableStorageOptimizer", OutputListKey: "StorageOptimizerList", OutputItemKey: "", Method: "POST", URI: "/ListTableStorageOptimizers"}, + "ListTransactions": {Verb: "List", Resource: "Transaction", OutputListKey: "Transactions", OutputItemKey: "", Method: "POST", URI: "/ListTransactions"}, + "PutDataLakeSettings": {Verb: "Update", Resource: "DataLakeSetting", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/PutDataLakeSettings"}, + "RegisterResource": {Verb: "Create", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/RegisterResource"}, + "UpdateDataCellsFilter": {Verb: "Update", Resource: "DataCellsFilter", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/UpdateDataCellsFilter"}, + "UpdateLFTag": {Verb: "Update", Resource: "LFTag", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/UpdateLFTag"}, + "UpdateLFTagExpression": {Verb: "Update", Resource: "LFTagExpression", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/UpdateLFTagExpression"}, + "UpdateLakeFormationIdentityCenterConfiguration": {Verb: "Update", Resource: "LakeFormationIdentityCenterConfiguration", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/UpdateLakeFormationIdentityCenterConfiguration"}, + "UpdateResource": {Verb: "Update", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/UpdateResource"}, + "UpdateTableObjects": {Verb: "Update", Resource: "TableObject", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/UpdateTableObjects"}, + "UpdateTableStorageOptimizer": {Verb: "Update", Resource: "TableStorageOptimizer", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/UpdateTableStorageOptimizer"}, + }) + crud.Register("lambda", map[string]crud.OpMeta{ + "CreateAlias": {Verb: "Create", Resource: "Alia", OutputListKey: "", OutputItemKey: "RoutingConfig", Method: "POST", URI: "/2015-03-31/functions/{FunctionName}/aliases"}, + "CreateCapacityProvider": {Verb: "Create", Resource: "CapacityProvider", OutputListKey: "", OutputItemKey: "CapacityProvider", Method: "POST", URI: "/2025-11-30/capacity-providers"}, + "CreateCodeSigningConfig": {Verb: "Create", Resource: "CodeSigningConfig", OutputListKey: "", OutputItemKey: "CodeSigningConfig", Method: "POST", URI: "/2020-04-22/code-signing-configs"}, + "CreateEventSourceMapping": {Verb: "Create", Resource: "EventSourceMapping", OutputListKey: "FunctionResponseTypes", OutputItemKey: "AmazonManagedKafkaEventSourceConfig", Method: "POST", URI: "/2015-03-31/event-source-mappings"}, + "CreateFunction": {Verb: "Create", Resource: "Function", OutputListKey: "Architectures", OutputItemKey: "CapacityProviderConfig", Method: "POST", URI: "/2015-03-31/functions"}, + "CreateFunctionUrlConfig": {Verb: "Create", Resource: "FunctionUrlConfig", OutputListKey: "", OutputItemKey: "Cors", Method: "POST", URI: "/2021-10-31/functions/{FunctionName}/url"}, + "DeleteAlias": {Verb: "Delete", Resource: "Alia", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2015-03-31/functions/{FunctionName}/aliases/{Name}"}, + "DeleteCapacityProvider": {Verb: "Delete", Resource: "CapacityProvider", OutputListKey: "", OutputItemKey: "CapacityProvider", Method: "DELETE", URI: "/2025-11-30/capacity-providers/{CapacityProviderName}"}, + "DeleteCodeSigningConfig": {Verb: "Delete", Resource: "CodeSigningConfig", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2020-04-22/code-signing-configs/{CodeSigningConfigArn}"}, + "DeleteEventSourceMapping": {Verb: "Delete", Resource: "EventSourceMapping", OutputListKey: "FunctionResponseTypes", OutputItemKey: "AmazonManagedKafkaEventSourceConfig", Method: "DELETE", URI: "/2015-03-31/event-source-mappings/{UUID}"}, + "DeleteFunction": {Verb: "Delete", Resource: "Function", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2015-03-31/functions/{FunctionName}"}, + "DeleteFunctionCodeSigningConfig": {Verb: "Delete", Resource: "FunctionCodeSigningConfig", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2020-06-30/functions/{FunctionName}/code-signing-config"}, + "DeleteFunctionConcurrency": {Verb: "Delete", Resource: "FunctionConcurrency", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2017-10-31/functions/{FunctionName}/concurrency"}, + "DeleteFunctionEventInvokeConfig": {Verb: "Delete", Resource: "FunctionEventInvokeConfig", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2019-09-25/functions/{FunctionName}/event-invoke-config"}, + "DeleteFunctionUrlConfig": {Verb: "Delete", Resource: "FunctionUrlConfig", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2021-10-31/functions/{FunctionName}/url"}, + "DeleteLayerVersion": {Verb: "Delete", Resource: "LayerVersion", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2018-10-31/layers/{LayerName}/versions/{VersionNumber}"}, + "DeleteProvisionedConcurrencyConfig": {Verb: "Delete", Resource: "ProvisionedConcurrencyConfig", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2019-09-30/functions/{FunctionName}/provisioned-concurrency"}, + "GetAccountSettings": {Verb: "Get", Resource: "AccountSetting", OutputListKey: "", OutputItemKey: "AccountLimit", Method: "GET", URI: "/2016-08-19/account-settings"}, + "GetAlias": {Verb: "Get", Resource: "Alia", OutputListKey: "", OutputItemKey: "RoutingConfig", Method: "GET", URI: "/2015-03-31/functions/{FunctionName}/aliases/{Name}"}, + "GetCapacityProvider": {Verb: "Get", Resource: "CapacityProvider", OutputListKey: "", OutputItemKey: "CapacityProvider", Method: "GET", URI: "/2025-11-30/capacity-providers/{CapacityProviderName}"}, + "GetCodeSigningConfig": {Verb: "Get", Resource: "CodeSigningConfig", OutputListKey: "", OutputItemKey: "CodeSigningConfig", Method: "GET", URI: "/2020-04-22/code-signing-configs/{CodeSigningConfigArn}"}, + "GetDurableExecution": {Verb: "Get", Resource: "DurableExecution", OutputListKey: "", OutputItemKey: "Error", Method: "GET", URI: "/2025-12-01/durable-executions/{DurableExecutionArn}"}, + "GetDurableExecutionHistory": {Verb: "Get", Resource: "DurableExecutionHistory", OutputListKey: "Events", OutputItemKey: "", Method: "GET", URI: "/2025-12-01/durable-executions/{DurableExecutionArn}/history"}, + "GetDurableExecutionState": {Verb: "Get", Resource: "DurableExecutionState", OutputListKey: "Operations", OutputItemKey: "", Method: "GET", URI: "/2025-12-01/durable-executions/{DurableExecutionArn}/state"}, + "GetEventSourceMapping": {Verb: "Get", Resource: "EventSourceMapping", OutputListKey: "FunctionResponseTypes", OutputItemKey: "AmazonManagedKafkaEventSourceConfig", Method: "GET", URI: "/2015-03-31/event-source-mappings/{UUID}"}, + "GetFunction": {Verb: "Get", Resource: "Function", OutputListKey: "", OutputItemKey: "Code", Method: "GET", URI: "/2015-03-31/functions/{FunctionName}"}, + "GetFunctionCodeSigningConfig": {Verb: "Get", Resource: "FunctionCodeSigningConfig", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/2020-06-30/functions/{FunctionName}/code-signing-config"}, + "GetFunctionConcurrency": {Verb: "Get", Resource: "FunctionConcurrency", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/2019-09-30/functions/{FunctionName}/concurrency"}, + "GetFunctionConfiguration": {Verb: "Get", Resource: "FunctionConfiguration", OutputListKey: "Architectures", OutputItemKey: "CapacityProviderConfig", Method: "GET", URI: "/2015-03-31/functions/{FunctionName}/configuration"}, + "GetFunctionEventInvokeConfig": {Verb: "Get", Resource: "FunctionEventInvokeConfig", OutputListKey: "", OutputItemKey: "DestinationConfig", Method: "GET", URI: "/2019-09-25/functions/{FunctionName}/event-invoke-config"}, + "GetFunctionRecursionConfig": {Verb: "Get", Resource: "FunctionRecursionConfig", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/2024-08-31/functions/{FunctionName}/recursion-config"}, + "GetFunctionScalingConfig": {Verb: "Get", Resource: "FunctionScalingConfig", OutputListKey: "", OutputItemKey: "AppliedFunctionScalingConfig", Method: "GET", URI: "/2025-11-30/functions/{FunctionName}/function-scaling-config"}, + "GetFunctionUrlConfig": {Verb: "Get", Resource: "FunctionUrlConfig", OutputListKey: "", OutputItemKey: "Cors", Method: "GET", URI: "/2021-10-31/functions/{FunctionName}/url"}, + "GetLayerVersion": {Verb: "Get", Resource: "LayerVersion", OutputListKey: "CompatibleArchitectures", OutputItemKey: "Content", Method: "GET", URI: "/2018-10-31/layers/{LayerName}/versions/{VersionNumber}"}, + "GetLayerVersionByArn": {Verb: "Get", Resource: "LayerVersionByArn", OutputListKey: "CompatibleArchitectures", OutputItemKey: "Content", Method: "GET", URI: "/2018-10-31/layers?find=LayerVersion"}, + "GetLayerVersionPolicy": {Verb: "Get", Resource: "LayerVersionPolicy", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/2018-10-31/layers/{LayerName}/versions/{VersionNumber}/policy"}, + "GetPolicy": {Verb: "Get", Resource: "Policy", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/2015-03-31/functions/{FunctionName}/policy"}, + "GetProvisionedConcurrencyConfig": {Verb: "Get", Resource: "ProvisionedConcurrencyConfig", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/2019-09-30/functions/{FunctionName}/provisioned-concurrency"}, + "GetRuntimeManagementConfig": {Verb: "Get", Resource: "RuntimeManagementConfig", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/2021-07-20/functions/{FunctionName}/runtime-management-config"}, + "ListAliases": {Verb: "List", Resource: "Aliase", OutputListKey: "Aliases", OutputItemKey: "", Method: "GET", URI: "/2015-03-31/functions/{FunctionName}/aliases"}, + "ListCapacityProviders": {Verb: "List", Resource: "CapacityProvider", OutputListKey: "CapacityProviders", OutputItemKey: "", Method: "GET", URI: "/2025-11-30/capacity-providers"}, + "ListCodeSigningConfigs": {Verb: "List", Resource: "CodeSigningConfig", OutputListKey: "CodeSigningConfigs", OutputItemKey: "", Method: "GET", URI: "/2020-04-22/code-signing-configs"}, + "ListDurableExecutionsByFunction": {Verb: "List", Resource: "DurableExecutionsByFunction", OutputListKey: "DurableExecutions", OutputItemKey: "", Method: "GET", URI: "/2025-12-01/functions/{FunctionName}/durable-executions"}, + "ListEventSourceMappings": {Verb: "List", Resource: "EventSourceMapping", OutputListKey: "EventSourceMappings", OutputItemKey: "", Method: "GET", URI: "/2015-03-31/event-source-mappings"}, + "ListFunctionEventInvokeConfigs": {Verb: "List", Resource: "FunctionEventInvokeConfig", OutputListKey: "FunctionEventInvokeConfigs", OutputItemKey: "", Method: "GET", URI: "/2019-09-25/functions/{FunctionName}/event-invoke-config/list"}, + "ListFunctionUrlConfigs": {Verb: "List", Resource: "FunctionUrlConfig", OutputListKey: "FunctionUrlConfigs", OutputItemKey: "", Method: "GET", URI: "/2021-10-31/functions/{FunctionName}/urls"}, + "ListFunctionVersionsByCapacityProvider": {Verb: "List", Resource: "FunctionVersionsByCapacityProvider", OutputListKey: "FunctionVersions", OutputItemKey: "", Method: "GET", URI: "/2025-11-30/capacity-providers/{CapacityProviderName}/function-versions"}, + "ListFunctions": {Verb: "List", Resource: "Function", OutputListKey: "Functions", OutputItemKey: "", Method: "GET", URI: "/2015-03-31/functions"}, + "ListFunctionsByCodeSigningConfig": {Verb: "List", Resource: "FunctionsByCodeSigningConfig", OutputListKey: "FunctionArns", OutputItemKey: "", Method: "GET", URI: "/2020-04-22/code-signing-configs/{CodeSigningConfigArn}/functions"}, + "ListLayerVersions": {Verb: "List", Resource: "LayerVersion", OutputListKey: "LayerVersions", OutputItemKey: "", Method: "GET", URI: "/2018-10-31/layers/{LayerName}/versions"}, + "ListLayers": {Verb: "List", Resource: "Layer", OutputListKey: "Layers", OutputItemKey: "", Method: "GET", URI: "/2018-10-31/layers"}, + "ListProvisionedConcurrencyConfigs": {Verb: "List", Resource: "ProvisionedConcurrencyConfig", OutputListKey: "ProvisionedConcurrencyConfigs", OutputItemKey: "", Method: "GET", URI: "/2019-09-30/functions/{FunctionName}/provisioned-concurrency?List=ALL"}, + "ListTags": {Verb: "List", Resource: "Tag", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/2017-03-31/tags/{Resource}"}, + "ListVersionsByFunction": {Verb: "List", Resource: "VersionsByFunction", OutputListKey: "Versions", OutputItemKey: "", Method: "GET", URI: "/2015-03-31/functions/{FunctionName}/versions"}, + "PutFunctionCodeSigningConfig": {Verb: "Update", Resource: "FunctionCodeSigningConfig", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/2020-06-30/functions/{FunctionName}/code-signing-config"}, + "PutFunctionConcurrency": {Verb: "Update", Resource: "FunctionConcurrency", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/2017-10-31/functions/{FunctionName}/concurrency"}, + "PutFunctionEventInvokeConfig": {Verb: "Update", Resource: "FunctionEventInvokeConfig", OutputListKey: "", OutputItemKey: "DestinationConfig", Method: "PUT", URI: "/2019-09-25/functions/{FunctionName}/event-invoke-config"}, + "PutFunctionRecursionConfig": {Verb: "Update", Resource: "FunctionRecursionConfig", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/2024-08-31/functions/{FunctionName}/recursion-config"}, + "PutFunctionScalingConfig": {Verb: "Update", Resource: "FunctionScalingConfig", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/2025-11-30/functions/{FunctionName}/function-scaling-config"}, + "PutProvisionedConcurrencyConfig": {Verb: "Update", Resource: "ProvisionedConcurrencyConfig", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/2019-09-30/functions/{FunctionName}/provisioned-concurrency"}, + "PutRuntimeManagementConfig": {Verb: "Update", Resource: "RuntimeManagementConfig", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/2021-07-20/functions/{FunctionName}/runtime-management-config"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/2017-03-31/tags/{Resource}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2017-03-31/tags/{Resource}"}, + "UpdateAlias": {Verb: "Update", Resource: "Alia", OutputListKey: "", OutputItemKey: "RoutingConfig", Method: "PUT", URI: "/2015-03-31/functions/{FunctionName}/aliases/{Name}"}, + "UpdateCapacityProvider": {Verb: "Update", Resource: "CapacityProvider", OutputListKey: "", OutputItemKey: "CapacityProvider", Method: "PUT", URI: "/2025-11-30/capacity-providers/{CapacityProviderName}"}, + "UpdateCodeSigningConfig": {Verb: "Update", Resource: "CodeSigningConfig", OutputListKey: "", OutputItemKey: "CodeSigningConfig", Method: "PUT", URI: "/2020-04-22/code-signing-configs/{CodeSigningConfigArn}"}, + "UpdateEventSourceMapping": {Verb: "Update", Resource: "EventSourceMapping", OutputListKey: "FunctionResponseTypes", OutputItemKey: "AmazonManagedKafkaEventSourceConfig", Method: "PUT", URI: "/2015-03-31/event-source-mappings/{UUID}"}, + "UpdateFunctionCode": {Verb: "Update", Resource: "FunctionCode", OutputListKey: "Architectures", OutputItemKey: "CapacityProviderConfig", Method: "PUT", URI: "/2015-03-31/functions/{FunctionName}/code"}, + "UpdateFunctionConfiguration": {Verb: "Update", Resource: "FunctionConfiguration", OutputListKey: "Architectures", OutputItemKey: "CapacityProviderConfig", Method: "PUT", URI: "/2015-03-31/functions/{FunctionName}/configuration"}, + "UpdateFunctionEventInvokeConfig": {Verb: "Update", Resource: "FunctionEventInvokeConfig", OutputListKey: "", OutputItemKey: "DestinationConfig", Method: "POST", URI: "/2019-09-25/functions/{FunctionName}/event-invoke-config"}, + "UpdateFunctionUrlConfig": {Verb: "Update", Resource: "FunctionUrlConfig", OutputListKey: "", OutputItemKey: "Cors", Method: "PUT", URI: "/2021-10-31/functions/{FunctionName}/url"}, + }) + crud.Register("lexmodelbuildingservice", map[string]crud.OpMeta{ + "CreateBotVersion": {Verb: "Create", Resource: "BotVersion", OutputListKey: "intents", OutputItemKey: "abortStatement", Method: "POST", URI: "/bots/{name}/versions"}, + "CreateIntentVersion": {Verb: "Create", Resource: "IntentVersion", OutputListKey: "inputContexts", OutputItemKey: "conclusionStatement", Method: "POST", URI: "/intents/{name}/versions"}, + "CreateSlotTypeVersion": {Verb: "Create", Resource: "SlotTypeVersion", OutputListKey: "enumerationValues", OutputItemKey: "", Method: "POST", URI: "/slottypes/{name}/versions"}, + "DeleteBot": {Verb: "Delete", Resource: "Bot", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/bots/{name}"}, + "DeleteBotAlias": {Verb: "Delete", Resource: "BotAlia", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/bots/{botName}/aliases/{name}"}, + "DeleteBotChannelAssociation": {Verb: "Delete", Resource: "BotChannelAssociation", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/bots/{botName}/aliases/{botAlias}/channels/{name}"}, + "DeleteBotVersion": {Verb: "Delete", Resource: "BotVersion", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/bots/{name}/versions/{version}"}, + "DeleteIntent": {Verb: "Delete", Resource: "Intent", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/intents/{name}"}, + "DeleteIntentVersion": {Verb: "Delete", Resource: "IntentVersion", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/intents/{name}/versions/{version}"}, + "DeleteSlotType": {Verb: "Delete", Resource: "SlotType", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/slottypes/{name}"}, + "DeleteSlotTypeVersion": {Verb: "Delete", Resource: "SlotTypeVersion", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/slottypes/{name}/version/{version}"}, + "DeleteUtterances": {Verb: "Delete", Resource: "Utterance", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/bots/{botName}/utterances/{userId}"}, + "GetBot": {Verb: "Get", Resource: "Bot", OutputListKey: "intents", OutputItemKey: "abortStatement", Method: "GET", URI: "/bots/{name}/versions/{versionOrAlias}"}, + "GetBotAlias": {Verb: "Get", Resource: "BotAlia", OutputListKey: "", OutputItemKey: "conversationLogs", Method: "GET", URI: "/bots/{botName}/aliases/{name}"}, + "GetBotAliases": {Verb: "Get", Resource: "BotAliase", OutputListKey: "BotAliases", OutputItemKey: "", Method: "GET", URI: "/bots/{botName}/aliases"}, + "GetBotChannelAssociation": {Verb: "Get", Resource: "BotChannelAssociation", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/bots/{botName}/aliases/{botAlias}/channels/{name}"}, + "GetBotChannelAssociations": {Verb: "Get", Resource: "BotChannelAssociation", OutputListKey: "botChannelAssociations", OutputItemKey: "", Method: "GET", URI: "/bots/{botName}/aliases/{botAlias}/channels"}, + "GetBotVersions": {Verb: "Get", Resource: "BotVersion", OutputListKey: "bots", OutputItemKey: "", Method: "GET", URI: "/bots/{name}/versions"}, + "GetBots": {Verb: "Get", Resource: "Bot", OutputListKey: "bots", OutputItemKey: "", Method: "GET", URI: "/bots"}, + "GetBuiltinIntent": {Verb: "Get", Resource: "BuiltinIntent", OutputListKey: "slots", OutputItemKey: "", Method: "GET", URI: "/builtins/intents/{signature}"}, + "GetBuiltinIntents": {Verb: "Get", Resource: "BuiltinIntent", OutputListKey: "intents", OutputItemKey: "", Method: "GET", URI: "/builtins/intents"}, + "GetBuiltinSlotTypes": {Verb: "Get", Resource: "BuiltinSlotType", OutputListKey: "slotTypes", OutputItemKey: "", Method: "GET", URI: "/builtins/slottypes"}, + "GetExport": {Verb: "Get", Resource: "Export", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/exports"}, + "GetImport": {Verb: "Get", Resource: "Import", OutputListKey: "failureReason", OutputItemKey: "", Method: "GET", URI: "/imports/{importId}"}, + "GetIntent": {Verb: "Get", Resource: "Intent", OutputListKey: "inputContexts", OutputItemKey: "conclusionStatement", Method: "GET", URI: "/intents/{name}/versions/{version}"}, + "GetIntentVersions": {Verb: "Get", Resource: "IntentVersion", OutputListKey: "intents", OutputItemKey: "", Method: "GET", URI: "/intents/{name}/versions"}, + "GetIntents": {Verb: "Get", Resource: "Intent", OutputListKey: "intents", OutputItemKey: "", Method: "GET", URI: "/intents"}, + "GetMigration": {Verb: "Get", Resource: "Migration", OutputListKey: "alerts", OutputItemKey: "", Method: "GET", URI: "/migrations/{migrationId}"}, + "GetMigrations": {Verb: "Get", Resource: "Migration", OutputListKey: "migrationSummaries", OutputItemKey: "", Method: "GET", URI: "/migrations"}, + "GetSlotType": {Verb: "Get", Resource: "SlotType", OutputListKey: "enumerationValues", OutputItemKey: "", Method: "GET", URI: "/slottypes/{name}/versions/{version}"}, + "GetSlotTypeVersions": {Verb: "Get", Resource: "SlotTypeVersion", OutputListKey: "slotTypes", OutputItemKey: "", Method: "GET", URI: "/slottypes/{name}/versions"}, + "GetSlotTypes": {Verb: "Get", Resource: "SlotType", OutputListKey: "slotTypes", OutputItemKey: "", Method: "GET", URI: "/slottypes"}, + "GetUtterancesView": {Verb: "Get", Resource: "UtterancesView", OutputListKey: "utterances", OutputItemKey: "", Method: "GET", URI: "/bots/{botName}/utterances?view=aggregation"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "tags", OutputItemKey: "", Method: "GET", URI: "/tags/{resourceArn}"}, + "PutBot": {Verb: "Update", Resource: "Bot", OutputListKey: "intents", OutputItemKey: "abortStatement", Method: "PUT", URI: "/bots/{name}/versions/$LATEST"}, + "PutBotAlias": {Verb: "Update", Resource: "BotAlia", OutputListKey: "tags", OutputItemKey: "conversationLogs", Method: "PUT", URI: "/bots/{botName}/aliases/{name}"}, + "PutIntent": {Verb: "Update", Resource: "Intent", OutputListKey: "inputContexts", OutputItemKey: "conclusionStatement", Method: "PUT", URI: "/intents/{name}/versions/$LATEST"}, + "PutSlotType": {Verb: "Update", Resource: "SlotType", OutputListKey: "enumerationValues", OutputItemKey: "", Method: "PUT", URI: "/slottypes/{name}/versions/$LATEST"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/tags/{resourceArn}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/tags/{resourceArn}"}, + }) + crud.Register("lexmodelsv2", map[string]crud.OpMeta{ + "CreateBot": {Verb: "Create", Resource: "Bot", OutputListKey: "botMembers", OutputItemKey: "dataPrivacy", Method: "PUT", URI: "/bots"}, + "CreateBotAlias": {Verb: "Create", Resource: "BotAlia", OutputListKey: "", OutputItemKey: "conversationLogSettings", Method: "PUT", URI: "/bots/{botId}/botaliases"}, + "CreateBotLocale": {Verb: "Create", Resource: "BotLocale", OutputListKey: "", OutputItemKey: "audioFillerSettings", Method: "PUT", URI: "/bots/{botId}/botversions/{botVersion}/botlocales"}, + "CreateBotReplica": {Verb: "Create", Resource: "BotReplica", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/bots/{botId}/replicas"}, + "CreateBotVersion": {Verb: "Create", Resource: "BotVersion", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/bots/{botId}/botversions"}, + "CreateExport": {Verb: "Create", Resource: "Export", OutputListKey: "", OutputItemKey: "resourceSpecification", Method: "PUT", URI: "/exports"}, + "CreateIntent": {Verb: "Create", Resource: "Intent", OutputListKey: "inputContexts", OutputItemKey: "dialogCodeHook", Method: "PUT", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}/intents"}, + "CreateResourcePolicy": {Verb: "Create", Resource: "ResourcePolicy", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/policy/{resourceArn}"}, + "CreateResourcePolicyStatement": {Verb: "Create", Resource: "ResourcePolicyStatement", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/policy/{resourceArn}/statements"}, + "CreateSlot": {Verb: "Create", Resource: "Slot", OutputListKey: "", OutputItemKey: "multipleValuesSetting", Method: "PUT", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}/intents/{intentId}/slots"}, + "CreateSlotType": {Verb: "Create", Resource: "SlotType", OutputListKey: "slotTypeValues", OutputItemKey: "compositeSlotTypeSetting", Method: "PUT", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}/slottypes"}, + "CreateTestSetDiscrepancyReport": {Verb: "Create", Resource: "TestSetDiscrepancyReport", OutputListKey: "", OutputItemKey: "target", Method: "POST", URI: "/testsets/{testSetId}/testsetdiscrepancy"}, + "CreateUploadUrl": {Verb: "Create", Resource: "UploadUrl", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/createuploadurl"}, + "DeleteBot": {Verb: "Delete", Resource: "Bot", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/bots/{botId}"}, + "DeleteBotAlias": {Verb: "Delete", Resource: "BotAlia", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/bots/{botId}/botaliases/{botAliasId}"}, + "DeleteBotAnalyzerRecommendation": {Verb: "Delete", Resource: "BotAnalyzerRecommendation", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/bots/{botId}/botanalyzer/{botAnalyzerRequestId}"}, + "DeleteBotLocale": {Verb: "Delete", Resource: "BotLocale", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}"}, + "DeleteBotReplica": {Verb: "Delete", Resource: "BotReplica", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/bots/{botId}/replicas/{replicaRegion}"}, + "DeleteBotVersion": {Verb: "Delete", Resource: "BotVersion", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/bots/{botId}/botversions/{botVersion}"}, + "DeleteCustomVocabulary": {Verb: "Delete", Resource: "CustomVocabulary", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}/customvocabulary"}, + "DeleteExport": {Verb: "Delete", Resource: "Export", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/exports/{exportId}"}, + "DeleteImport": {Verb: "Delete", Resource: "Import", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/imports/{importId}"}, + "DeleteIntent": {Verb: "Delete", Resource: "Intent", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}/intents/{intentId}"}, + "DeleteResourcePolicy": {Verb: "Delete", Resource: "ResourcePolicy", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/policy/{resourceArn}"}, + "DeleteResourcePolicyStatement": {Verb: "Delete", Resource: "ResourcePolicyStatement", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/policy/{resourceArn}/statements/{statementId}"}, + "DeleteSlot": {Verb: "Delete", Resource: "Slot", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}/intents/{intentId}/slots/{slotId}"}, + "DeleteSlotType": {Verb: "Delete", Resource: "SlotType", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}/slottypes/{slotTypeId}"}, + "DeleteTestSet": {Verb: "Delete", Resource: "TestSet", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/testsets/{testSetId}"}, + "DeleteUtterances": {Verb: "Delete", Resource: "Utterance", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/bots/{botId}/utterances"}, + "DescribeBot": {Verb: "Get", Resource: "Bot", OutputListKey: "botMembers", OutputItemKey: "dataPrivacy", Method: "GET", URI: "/bots/{botId}"}, + "DescribeBotAlias": {Verb: "Get", Resource: "BotAlia", OutputListKey: "botAliasHistoryEvents", OutputItemKey: "conversationLogSettings", Method: "GET", URI: "/bots/{botId}/botaliases/{botAliasId}"}, + "DescribeBotAnalyzerRecommendation": {Verb: "Get", Resource: "BotAnalyzerRecommendation", OutputListKey: "botAnalyzerRecommendationList", OutputItemKey: "", Method: "POST", URI: "/bots/{botId}/botanalyzer/describe/{botAnalyzerRequestId}"}, + "DescribeBotLocale": {Verb: "Get", Resource: "BotLocale", OutputListKey: "botLocaleHistoryEvents", OutputItemKey: "audioFillerSettings", Method: "GET", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}"}, + "DescribeBotRecommendation": {Verb: "Get", Resource: "BotRecommendation", OutputListKey: "failureReasons", OutputItemKey: "botRecommendationResults", Method: "GET", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}/botrecommendations/{botRecommendationId}"}, + "DescribeBotReplica": {Verb: "Get", Resource: "BotReplica", OutputListKey: "failureReasons", OutputItemKey: "", Method: "GET", URI: "/bots/{botId}/replicas/{replicaRegion}"}, + "DescribeBotResourceGeneration": {Verb: "Get", Resource: "BotResourceGeneration", OutputListKey: "failureReasons", OutputItemKey: "", Method: "GET", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}/generations/{generationId}"}, + "DescribeBotVersion": {Verb: "Get", Resource: "BotVersion", OutputListKey: "botMembers", OutputItemKey: "dataPrivacy", Method: "GET", URI: "/bots/{botId}/botversions/{botVersion}"}, + "DescribeCustomVocabularyMetadata": {Verb: "Get", Resource: "CustomVocabularyMetadata", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}/customvocabulary/DEFAULT/metadata"}, + "DescribeExport": {Verb: "Get", Resource: "Export", OutputListKey: "failureReasons", OutputItemKey: "resourceSpecification", Method: "GET", URI: "/exports/{exportId}"}, + "DescribeImport": {Verb: "Get", Resource: "Import", OutputListKey: "failureReasons", OutputItemKey: "resourceSpecification", Method: "GET", URI: "/imports/{importId}"}, + "DescribeIntent": {Verb: "Get", Resource: "Intent", OutputListKey: "inputContexts", OutputItemKey: "dialogCodeHook", Method: "GET", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}/intents/{intentId}"}, + "DescribeResourcePolicy": {Verb: "Get", Resource: "ResourcePolicy", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/policy/{resourceArn}"}, + "DescribeSlot": {Verb: "Get", Resource: "Slot", OutputListKey: "", OutputItemKey: "multipleValuesSetting", Method: "GET", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}/intents/{intentId}/slots/{slotId}"}, + "DescribeSlotType": {Verb: "Get", Resource: "SlotType", OutputListKey: "slotTypeValues", OutputItemKey: "compositeSlotTypeSetting", Method: "GET", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}/slottypes/{slotTypeId}"}, + "DescribeTestExecution": {Verb: "Get", Resource: "TestExecution", OutputListKey: "failureReasons", OutputItemKey: "target", Method: "GET", URI: "/testexecutions/{testExecutionId}"}, + "DescribeTestSet": {Verb: "Get", Resource: "TestSet", OutputListKey: "", OutputItemKey: "storageLocation", Method: "GET", URI: "/testsets/{testSetId}"}, + "DescribeTestSetDiscrepancyReport": {Verb: "Get", Resource: "TestSetDiscrepancyReport", OutputListKey: "failureReasons", OutputItemKey: "target", Method: "GET", URI: "/testsetdiscrepancy/{testSetDiscrepancyReportId}"}, + "DescribeTestSetGeneration": {Verb: "Get", Resource: "TestSetGeneration", OutputListKey: "failureReasons", OutputItemKey: "generationDataSource", Method: "GET", URI: "/testsetgenerations/{testSetGenerationId}"}, + "GetTestExecutionArtifactsUrl": {Verb: "Get", Resource: "TestExecutionArtifactsUrl", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/testexecutions/{testExecutionId}/artifacturl"}, + "ListAggregatedUtterances": {Verb: "List", Resource: "AggregatedUtterance", OutputListKey: "aggregatedUtterancesSummaries", OutputItemKey: "aggregationDuration", Method: "POST", URI: "/bots/{botId}/aggregatedutterances"}, + "ListBotAliasReplicas": {Verb: "List", Resource: "BotAliasReplica", OutputListKey: "botAliasReplicaSummaries", OutputItemKey: "", Method: "POST", URI: "/bots/{botId}/replicas/{replicaRegion}/botaliases"}, + "ListBotAliases": {Verb: "List", Resource: "BotAliase", OutputListKey: "botAliasSummaries", OutputItemKey: "", Method: "POST", URI: "/bots/{botId}/botaliases"}, + "ListBotAnalyzerHistory": {Verb: "List", Resource: "BotAnalyzerHistory", OutputListKey: "botAnalyzerHistoryList", OutputItemKey: "", Method: "POST", URI: "/bots/{botId}/botanalyzer/history"}, + "ListBotLocales": {Verb: "List", Resource: "BotLocale", OutputListKey: "botLocaleSummaries", OutputItemKey: "", Method: "POST", URI: "/bots/{botId}/botversions/{botVersion}/botlocales"}, + "ListBotRecommendations": {Verb: "List", Resource: "BotRecommendation", OutputListKey: "botRecommendationSummaries", OutputItemKey: "", Method: "POST", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}/botrecommendations"}, + "ListBotReplicas": {Verb: "List", Resource: "BotReplica", OutputListKey: "botReplicaSummaries", OutputItemKey: "", Method: "POST", URI: "/bots/{botId}/replicas"}, + "ListBotResourceGenerations": {Verb: "List", Resource: "BotResourceGeneration", OutputListKey: "generationSummaries", OutputItemKey: "", Method: "POST", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}/generations"}, + "ListBotVersionReplicas": {Verb: "List", Resource: "BotVersionReplica", OutputListKey: "botVersionReplicaSummaries", OutputItemKey: "", Method: "POST", URI: "/bots/{botId}/replicas/{replicaRegion}/botversions"}, + "ListBotVersions": {Verb: "List", Resource: "BotVersion", OutputListKey: "botVersionSummaries", OutputItemKey: "", Method: "POST", URI: "/bots/{botId}/botversions"}, + "ListBots": {Verb: "List", Resource: "Bot", OutputListKey: "botSummaries", OutputItemKey: "", Method: "POST", URI: "/bots"}, + "ListBuiltInIntents": {Verb: "List", Resource: "BuiltInIntent", OutputListKey: "builtInIntentSummaries", OutputItemKey: "", Method: "POST", URI: "/builtins/locales/{localeId}/intents"}, + "ListBuiltInSlotTypes": {Verb: "List", Resource: "BuiltInSlotType", OutputListKey: "builtInSlotTypeSummaries", OutputItemKey: "", Method: "POST", URI: "/builtins/locales/{localeId}/slottypes"}, + "ListCustomVocabularyItems": {Verb: "List", Resource: "CustomVocabularyItem", OutputListKey: "customVocabularyItems", OutputItemKey: "", Method: "POST", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}/customvocabulary/DEFAULT/list"}, + "ListExports": {Verb: "List", Resource: "Export", OutputListKey: "exportSummaries", OutputItemKey: "", Method: "POST", URI: "/exports"}, + "ListImports": {Verb: "List", Resource: "Import", OutputListKey: "importSummaries", OutputItemKey: "", Method: "POST", URI: "/imports"}, + "ListIntentMetrics": {Verb: "List", Resource: "IntentMetric", OutputListKey: "results", OutputItemKey: "", Method: "POST", URI: "/bots/{botId}/analytics/intentmetrics"}, + "ListIntentPaths": {Verb: "List", Resource: "IntentPath", OutputListKey: "nodeSummaries", OutputItemKey: "", Method: "POST", URI: "/bots/{botId}/analytics/intentpaths"}, + "ListIntentStageMetrics": {Verb: "List", Resource: "IntentStageMetric", OutputListKey: "results", OutputItemKey: "", Method: "POST", URI: "/bots/{botId}/analytics/intentstagemetrics"}, + "ListIntents": {Verb: "List", Resource: "Intent", OutputListKey: "intentSummaries", OutputItemKey: "", Method: "POST", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}/intents"}, + "ListRecommendedIntents": {Verb: "List", Resource: "RecommendedIntent", OutputListKey: "summaryList", OutputItemKey: "", Method: "POST", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}/botrecommendations/{botRecommendationId}/intents"}, + "ListSessionAnalyticsData": {Verb: "List", Resource: "SessionAnalyticsData", OutputListKey: "sessions", OutputItemKey: "", Method: "POST", URI: "/bots/{botId}/analytics/sessions"}, + "ListSessionMetrics": {Verb: "List", Resource: "SessionMetric", OutputListKey: "results", OutputItemKey: "", Method: "POST", URI: "/bots/{botId}/analytics/sessionmetrics"}, + "ListSlotTypes": {Verb: "List", Resource: "SlotType", OutputListKey: "slotTypeSummaries", OutputItemKey: "", Method: "POST", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}/slottypes"}, + "ListSlots": {Verb: "List", Resource: "Slot", OutputListKey: "slotSummaries", OutputItemKey: "", Method: "POST", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}/intents/{intentId}/slots"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/tags/{resourceARN}"}, + "ListTestExecutionResultItems": {Verb: "List", Resource: "TestExecutionResultItem", OutputListKey: "", OutputItemKey: "testExecutionResults", Method: "POST", URI: "/testexecutions/{testExecutionId}/results"}, + "ListTestExecutions": {Verb: "List", Resource: "TestExecution", OutputListKey: "testExecutions", OutputItemKey: "", Method: "POST", URI: "/testexecutions"}, + "ListTestSetRecords": {Verb: "List", Resource: "TestSetRecord", OutputListKey: "testSetRecords", OutputItemKey: "", Method: "POST", URI: "/testsets/{testSetId}/records"}, + "ListTestSets": {Verb: "List", Resource: "TestSet", OutputListKey: "testSets", OutputItemKey: "", Method: "POST", URI: "/testsets"}, + "ListUtteranceAnalyticsData": {Verb: "List", Resource: "UtteranceAnalyticsData", OutputListKey: "utterances", OutputItemKey: "", Method: "POST", URI: "/bots/{botId}/analytics/utterances"}, + "ListUtteranceMetrics": {Verb: "List", Resource: "UtteranceMetric", OutputListKey: "results", OutputItemKey: "", Method: "POST", URI: "/bots/{botId}/analytics/utterancemetrics"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/tags/{resourceARN}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/tags/{resourceARN}"}, + "UpdateBot": {Verb: "Update", Resource: "Bot", OutputListKey: "botMembers", OutputItemKey: "dataPrivacy", Method: "PUT", URI: "/bots/{botId}"}, + "UpdateBotAlias": {Verb: "Update", Resource: "BotAlia", OutputListKey: "", OutputItemKey: "conversationLogSettings", Method: "PUT", URI: "/bots/{botId}/botaliases/{botAliasId}"}, + "UpdateBotLocale": {Verb: "Update", Resource: "BotLocale", OutputListKey: "failureReasons", OutputItemKey: "audioFillerSettings", Method: "PUT", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}"}, + "UpdateBotRecommendation": {Verb: "Update", Resource: "BotRecommendation", OutputListKey: "", OutputItemKey: "encryptionSetting", Method: "PUT", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}/botrecommendations/{botRecommendationId}"}, + "UpdateExport": {Verb: "Update", Resource: "Export", OutputListKey: "", OutputItemKey: "resourceSpecification", Method: "PUT", URI: "/exports/{exportId}"}, + "UpdateIntent": {Verb: "Update", Resource: "Intent", OutputListKey: "inputContexts", OutputItemKey: "dialogCodeHook", Method: "PUT", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}/intents/{intentId}"}, + "UpdateResourcePolicy": {Verb: "Update", Resource: "ResourcePolicy", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/policy/{resourceArn}"}, + "UpdateSlot": {Verb: "Update", Resource: "Slot", OutputListKey: "", OutputItemKey: "multipleValuesSetting", Method: "PUT", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}/intents/{intentId}/slots/{slotId}"}, + "UpdateSlotType": {Verb: "Update", Resource: "SlotType", OutputListKey: "slotTypeValues", OutputItemKey: "compositeSlotTypeSetting", Method: "PUT", URI: "/bots/{botId}/botversions/{botVersion}/botlocales/{localeId}/slottypes/{slotTypeId}"}, + "UpdateTestSet": {Verb: "Update", Resource: "TestSet", OutputListKey: "", OutputItemKey: "storageLocation", Method: "PUT", URI: "/testsets/{testSetId}"}, + }) + crud.Register("lexruntimeservice", map[string]crud.OpMeta{ + "DeleteSession": {Verb: "Delete", Resource: "Session", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/bot/{botName}/alias/{botAlias}/user/{userId}/session"}, + "GetSession": {Verb: "Get", Resource: "Session", OutputListKey: "activeContexts", OutputItemKey: "dialogAction", Method: "GET", URI: "/bot/{botName}/alias/{botAlias}/user/{userId}/session"}, + "PutSession": {Verb: "Update", Resource: "Session", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/bot/{botName}/alias/{botAlias}/user/{userId}/session"}, + }) + crud.Register("lexruntimev2", map[string]crud.OpMeta{ + "DeleteSession": {Verb: "Delete", Resource: "Session", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/bots/{botId}/botAliases/{botAliasId}/botLocales/{localeId}/sessions/{sessionId}"}, + "GetSession": {Verb: "Get", Resource: "Session", OutputListKey: "interpretations", OutputItemKey: "sessionState", Method: "GET", URI: "/bots/{botId}/botAliases/{botAliasId}/botLocales/{localeId}/sessions/{sessionId}"}, + "PutSession": {Verb: "Update", Resource: "Session", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/bots/{botId}/botAliases/{botAliasId}/botLocales/{localeId}/sessions/{sessionId}"}, + }) crud.Register("lookoutequipment", map[string]crud.OpMeta{ "CreateDataset": {Verb: "Create", Resource: "Dataset", OutputListKey: "", OutputItemKey: ""}, "CreateInferenceScheduler": {Verb: "Create", Resource: "InferenceScheduler", OutputListKey: "", OutputItemKey: ""}, @@ -1640,6 +3440,33 @@ func init() { "UpdateModel": {Verb: "Update", Resource: "Model", OutputListKey: "", OutputItemKey: ""}, "UpdateRetrainingScheduler": {Verb: "Update", Resource: "RetrainingScheduler", OutputListKey: "", OutputItemKey: ""}, }) + crud.Register("managedblockchain", map[string]crud.OpMeta{ + "CreateAccessor": {Verb: "Create", Resource: "Accessor", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/accessors"}, + "CreateMember": {Verb: "Create", Resource: "Member", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/networks/{NetworkId}/members"}, + "CreateNetwork": {Verb: "Create", Resource: "Network", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/networks"}, + "CreateNode": {Verb: "Create", Resource: "Node", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/networks/{NetworkId}/nodes"}, + "CreateProposal": {Verb: "Create", Resource: "Proposal", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/networks/{NetworkId}/proposals"}, + "DeleteAccessor": {Verb: "Delete", Resource: "Accessor", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/accessors/{AccessorId}"}, + "DeleteMember": {Verb: "Delete", Resource: "Member", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/networks/{NetworkId}/members/{MemberId}"}, + "DeleteNode": {Verb: "Delete", Resource: "Node", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/networks/{NetworkId}/nodes/{NodeId}"}, + "GetAccessor": {Verb: "Get", Resource: "Accessor", OutputListKey: "", OutputItemKey: "Accessor", Method: "GET", URI: "/accessors/{AccessorId}"}, + "GetMember": {Verb: "Get", Resource: "Member", OutputListKey: "", OutputItemKey: "Member", Method: "GET", URI: "/networks/{NetworkId}/members/{MemberId}"}, + "GetNetwork": {Verb: "Get", Resource: "Network", OutputListKey: "", OutputItemKey: "Network", Method: "GET", URI: "/networks/{NetworkId}"}, + "GetNode": {Verb: "Get", Resource: "Node", OutputListKey: "", OutputItemKey: "Node", Method: "GET", URI: "/networks/{NetworkId}/nodes/{NodeId}"}, + "GetProposal": {Verb: "Get", Resource: "Proposal", OutputListKey: "", OutputItemKey: "Proposal", Method: "GET", URI: "/networks/{NetworkId}/proposals/{ProposalId}"}, + "ListAccessors": {Verb: "List", Resource: "Accessor", OutputListKey: "Accessors", OutputItemKey: "", Method: "GET", URI: "/accessors"}, + "ListInvitations": {Verb: "List", Resource: "Invitation", OutputListKey: "Invitations", OutputItemKey: "", Method: "GET", URI: "/invitations"}, + "ListMembers": {Verb: "List", Resource: "Member", OutputListKey: "Members", OutputItemKey: "", Method: "GET", URI: "/networks/{NetworkId}/members"}, + "ListNetworks": {Verb: "List", Resource: "Network", OutputListKey: "Networks", OutputItemKey: "", Method: "GET", URI: "/networks"}, + "ListNodes": {Verb: "List", Resource: "Node", OutputListKey: "Nodes", OutputItemKey: "", Method: "GET", URI: "/networks/{NetworkId}/nodes"}, + "ListProposalVotes": {Verb: "List", Resource: "ProposalVote", OutputListKey: "ProposalVotes", OutputItemKey: "", Method: "GET", URI: "/networks/{NetworkId}/proposals/{ProposalId}/votes"}, + "ListProposals": {Verb: "List", Resource: "Proposal", OutputListKey: "Proposals", OutputItemKey: "", Method: "GET", URI: "/networks/{NetworkId}/proposals"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/tags/{ResourceArn}"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/tags/{ResourceArn}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/tags/{ResourceArn}"}, + "UpdateMember": {Verb: "Update", Resource: "Member", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/networks/{NetworkId}/members/{MemberId}"}, + "UpdateNode": {Verb: "Update", Resource: "Node", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/networks/{NetworkId}/nodes/{NodeId}"}, + }) crud.Register("memorydb", map[string]crud.OpMeta{ "CreateACL": {Verb: "Create", Resource: "ACL", OutputListKey: "", OutputItemKey: "ACL"}, "CreateCluster": {Verb: "Create", Resource: "Cluster", OutputListKey: "", OutputItemKey: "Cluster"}, @@ -1682,6 +3509,205 @@ func init() { "UpdateSubnetGroup": {Verb: "Update", Resource: "SubnetGroup", OutputListKey: "", OutputItemKey: "SubnetGroup"}, "UpdateUser": {Verb: "Update", Resource: "User", OutputListKey: "", OutputItemKey: "User"}, }) + crud.Register("mq", map[string]crud.OpMeta{ + "CreateBroker": {Verb: "Create", Resource: "Broker", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/brokers"}, + "CreateConfiguration": {Verb: "Create", Resource: "Configuration", OutputListKey: "", OutputItemKey: "LatestRevision", Method: "POST", URI: "/v1/configurations"}, + "CreateTags": {Verb: "Create", Resource: "Tag", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/tags/{ResourceArn}"}, + "CreateUser": {Verb: "Create", Resource: "User", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/brokers/{BrokerId}/users/{Username}"}, + "DeleteBroker": {Verb: "Delete", Resource: "Broker", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v1/brokers/{BrokerId}"}, + "DeleteConfiguration": {Verb: "Delete", Resource: "Configuration", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v1/configurations/{ConfigurationId}"}, + "DeleteTags": {Verb: "Delete", Resource: "Tag", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v1/tags/{ResourceArn}"}, + "DeleteUser": {Verb: "Delete", Resource: "User", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v1/brokers/{BrokerId}/users/{Username}"}, + "DescribeBroker": {Verb: "Get", Resource: "Broker", OutputListKey: "ActionsRequired", OutputItemKey: "Configurations", Method: "GET", URI: "/v1/brokers/{BrokerId}"}, + "DescribeBrokerEngineTypes": {Verb: "Get", Resource: "BrokerEngineType", OutputListKey: "BrokerEngineTypes", OutputItemKey: "", Method: "GET", URI: "/v1/broker-engine-types"}, + "DescribeBrokerInstanceOptions": {Verb: "Get", Resource: "BrokerInstanceOption", OutputListKey: "BrokerInstanceOptions", OutputItemKey: "", Method: "GET", URI: "/v1/broker-instance-options"}, + "DescribeConfiguration": {Verb: "Get", Resource: "Configuration", OutputListKey: "", OutputItemKey: "LatestRevision", Method: "GET", URI: "/v1/configurations/{ConfigurationId}"}, + "DescribeConfigurationRevision": {Verb: "Get", Resource: "ConfigurationRevision", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v1/configurations/{ConfigurationId}/revisions/{ConfigurationRevision}"}, + "DescribeUser": {Verb: "Get", Resource: "User", OutputListKey: "Groups", OutputItemKey: "Pending", Method: "GET", URI: "/v1/brokers/{BrokerId}/users/{Username}"}, + "ListBrokers": {Verb: "List", Resource: "Broker", OutputListKey: "BrokerSummaries", OutputItemKey: "", Method: "GET", URI: "/v1/brokers"}, + "ListConfigurationRevisions": {Verb: "List", Resource: "ConfigurationRevision", OutputListKey: "Revisions", OutputItemKey: "", Method: "GET", URI: "/v1/configurations/{ConfigurationId}/revisions"}, + "ListConfigurations": {Verb: "List", Resource: "Configuration", OutputListKey: "Configurations", OutputItemKey: "", Method: "GET", URI: "/v1/configurations"}, + "ListTags": {Verb: "List", Resource: "Tag", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v1/tags/{ResourceArn}"}, + "ListUsers": {Verb: "List", Resource: "User", OutputListKey: "Users", OutputItemKey: "", Method: "GET", URI: "/v1/brokers/{BrokerId}/users"}, + "UpdateBroker": {Verb: "Update", Resource: "Broker", OutputListKey: "SecurityGroups", OutputItemKey: "Configuration", Method: "PUT", URI: "/v1/brokers/{BrokerId}"}, + "UpdateConfiguration": {Verb: "Update", Resource: "Configuration", OutputListKey: "Warnings", OutputItemKey: "LatestRevision", Method: "PUT", URI: "/v1/configurations/{ConfigurationId}"}, + "UpdateUser": {Verb: "Update", Resource: "User", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v1/brokers/{BrokerId}/users/{Username}"}, + }) + crud.Register("mwaa", map[string]crud.OpMeta{ + "CreateCliToken": {Verb: "Create", Resource: "CliToken", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/clitoken/{Name}"}, + "CreateEnvironment": {Verb: "Create", Resource: "Environment", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/environments/{Name}"}, + "CreateWebLoginToken": {Verb: "Create", Resource: "WebLoginToken", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/webtoken/{Name}"}, + "DeleteEnvironment": {Verb: "Delete", Resource: "Environment", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/environments/{Name}"}, + "GetEnvironment": {Verb: "Get", Resource: "Environment", OutputListKey: "", OutputItemKey: "Environment", Method: "GET", URI: "/environments/{Name}"}, + "ListEnvironments": {Verb: "List", Resource: "Environment", OutputListKey: "Environments", OutputItemKey: "", Method: "GET", URI: "/environments"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/tags/{ResourceArn}"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/tags/{ResourceArn}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/tags/{ResourceArn}"}, + "UpdateEnvironment": {Verb: "Update", Resource: "Environment", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/environments/{Name}"}, + }) + crud.Register("omics", map[string]crud.OpMeta{ + "CreateAnnotationStore": {Verb: "Create", Resource: "AnnotationStore", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/annotationStore"}, + "CreateAnnotationStoreVersion": {Verb: "Create", Resource: "AnnotationStoreVersion", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/annotationStore/{name}/version"}, + "CreateConfiguration": {Verb: "Create", Resource: "Configuration", OutputListKey: "", OutputItemKey: "runConfigurations", Method: "POST", URI: "/configuration"}, + "CreateMultipartReadSetUpload": {Verb: "Create", Resource: "MultipartReadSetUpload", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/sequencestore/{sequenceStoreId}/upload"}, + "CreateReferenceStore": {Verb: "Create", Resource: "ReferenceStore", OutputListKey: "", OutputItemKey: "sseConfig", Method: "POST", URI: "/referencestore"}, + "CreateRunCache": {Verb: "Create", Resource: "RunCache", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/runCache"}, + "CreateRunGroup": {Verb: "Create", Resource: "RunGroup", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/runGroup"}, + "CreateSequenceStore": {Verb: "Create", Resource: "SequenceStore", OutputListKey: "propagatedSetLevelTags", OutputItemKey: "s3Access", Method: "POST", URI: "/sequencestore"}, + "CreateShare": {Verb: "Create", Resource: "Share", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/share"}, + "CreateVariantStore": {Verb: "Create", Resource: "VariantStore", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/variantStore"}, + "CreateWorkflow": {Verb: "Create", Resource: "Workflow", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/workflow"}, + "CreateWorkflowVersion": {Verb: "Create", Resource: "WorkflowVersion", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/workflow/{workflowId}/version"}, + "DeleteAnnotationStore": {Verb: "Delete", Resource: "AnnotationStore", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/annotationStore/{name}"}, + "DeleteAnnotationStoreVersions": {Verb: "Delete", Resource: "AnnotationStoreVersion", OutputListKey: "errors", OutputItemKey: "", Method: "POST", URI: "/annotationStore/{name}/versions/delete"}, + "DeleteBatch": {Verb: "Delete", Resource: "Batch", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/runBatch/{batchId}"}, + "DeleteConfiguration": {Verb: "Delete", Resource: "Configuration", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/configuration/{name}"}, + "DeleteReference": {Verb: "Delete", Resource: "Reference", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/referencestore/{referenceStoreId}/reference/{id}"}, + "DeleteReferenceStore": {Verb: "Delete", Resource: "ReferenceStore", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/referencestore/{id}"}, + "DeleteRun": {Verb: "Delete", Resource: "Run", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/run/{id}"}, + "DeleteRunBatch": {Verb: "Delete", Resource: "RunBatch", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/runBatch/delete"}, + "DeleteRunCache": {Verb: "Delete", Resource: "RunCache", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/runCache/{id}"}, + "DeleteRunGroup": {Verb: "Delete", Resource: "RunGroup", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/runGroup/{id}"}, + "DeleteS3AccessPolicy": {Verb: "Delete", Resource: "S3AccessPolicy", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/s3accesspolicy/{s3AccessPointArn}"}, + "DeleteSequenceStore": {Verb: "Delete", Resource: "SequenceStore", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/sequencestore/{id}"}, + "DeleteShare": {Verb: "Delete", Resource: "Share", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/share/{shareId}"}, + "DeleteVariantStore": {Verb: "Delete", Resource: "VariantStore", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/variantStore/{name}"}, + "DeleteWorkflow": {Verb: "Delete", Resource: "Workflow", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/workflow/{id}"}, + "DeleteWorkflowVersion": {Verb: "Delete", Resource: "WorkflowVersion", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/workflow/{workflowId}/version/{versionName}"}, + "GetAnnotationImportJob": {Verb: "Get", Resource: "AnnotationImportJob", OutputListKey: "items", OutputItemKey: "", Method: "GET", URI: "/import/annotation/{jobId}"}, + "GetAnnotationStore": {Verb: "Get", Resource: "AnnotationStore", OutputListKey: "", OutputItemKey: "sseConfig", Method: "GET", URI: "/annotationStore/{name}"}, + "GetAnnotationStoreVersion": {Verb: "Get", Resource: "AnnotationStoreVersion", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/annotationStore/{name}/version/{versionName}"}, + "GetBatch": {Verb: "Get", Resource: "Batch", OutputListKey: "", OutputItemKey: "defaultRunSetting", Method: "GET", URI: "/runBatch/{batchId}"}, + "GetConfiguration": {Verb: "Get", Resource: "Configuration", OutputListKey: "", OutputItemKey: "runConfigurations", Method: "GET", URI: "/configuration/{name}"}, + "GetReadSet": {Verb: "Get", Resource: "ReadSet", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/sequencestore/{sequenceStoreId}/readset/{id}"}, + "GetReadSetActivationJob": {Verb: "Get", Resource: "ReadSetActivationJob", OutputListKey: "sources", OutputItemKey: "", Method: "GET", URI: "/sequencestore/{sequenceStoreId}/activationjob/{id}"}, + "GetReadSetExportJob": {Verb: "Get", Resource: "ReadSetExportJob", OutputListKey: "readSets", OutputItemKey: "", Method: "GET", URI: "/sequencestore/{sequenceStoreId}/exportjob/{id}"}, + "GetReadSetImportJob": {Verb: "Get", Resource: "ReadSetImportJob", OutputListKey: "sources", OutputItemKey: "", Method: "GET", URI: "/sequencestore/{sequenceStoreId}/importjob/{id}"}, + "GetReadSetMetadata": {Verb: "Get", Resource: "ReadSetMetadata", OutputListKey: "", OutputItemKey: "etag", Method: "GET", URI: "/sequencestore/{sequenceStoreId}/readset/{id}/metadata"}, + "GetReference": {Verb: "Get", Resource: "Reference", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/referencestore/{referenceStoreId}/reference/{id}"}, + "GetReferenceImportJob": {Verb: "Get", Resource: "ReferenceImportJob", OutputListKey: "sources", OutputItemKey: "", Method: "GET", URI: "/referencestore/{referenceStoreId}/importjob/{id}"}, + "GetReferenceMetadata": {Verb: "Get", Resource: "ReferenceMetadata", OutputListKey: "", OutputItemKey: "files", Method: "GET", URI: "/referencestore/{referenceStoreId}/reference/{id}/metadata"}, + "GetReferenceStore": {Verb: "Get", Resource: "ReferenceStore", OutputListKey: "", OutputItemKey: "sseConfig", Method: "GET", URI: "/referencestore/{id}"}, + "GetRun": {Verb: "Get", Resource: "Run", OutputListKey: "", OutputItemKey: "configuration", Method: "GET", URI: "/run/{id}"}, + "GetRunCache": {Verb: "Get", Resource: "RunCache", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/runCache/{id}"}, + "GetRunGroup": {Verb: "Get", Resource: "RunGroup", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/runGroup/{id}"}, + "GetRunTask": {Verb: "Get", Resource: "RunTask", OutputListKey: "", OutputItemKey: "imageDetails", Method: "GET", URI: "/run/{id}/task/{taskId}"}, + "GetS3AccessPolicy": {Verb: "Get", Resource: "S3AccessPolicy", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/s3accesspolicy/{s3AccessPointArn}"}, + "GetSequenceStore": {Verb: "Get", Resource: "SequenceStore", OutputListKey: "propagatedSetLevelTags", OutputItemKey: "s3Access", Method: "GET", URI: "/sequencestore/{id}"}, + "GetShare": {Verb: "Get", Resource: "Share", OutputListKey: "", OutputItemKey: "share", Method: "GET", URI: "/share/{shareId}"}, + "GetVariantImportJob": {Verb: "Get", Resource: "VariantImportJob", OutputListKey: "items", OutputItemKey: "", Method: "GET", URI: "/import/variant/{jobId}"}, + "GetVariantStore": {Verb: "Get", Resource: "VariantStore", OutputListKey: "", OutputItemKey: "sseConfig", Method: "GET", URI: "/variantStore/{name}"}, + "GetWorkflow": {Verb: "Get", Resource: "Workflow", OutputListKey: "profiles", OutputItemKey: "containerRegistryMap", Method: "GET", URI: "/workflow/{id}"}, + "GetWorkflowVersion": {Verb: "Get", Resource: "WorkflowVersion", OutputListKey: "profiles", OutputItemKey: "containerRegistryMap", Method: "GET", URI: "/workflow/{workflowId}/version/{versionName}"}, + "ListAnnotationImportJobs": {Verb: "List", Resource: "AnnotationImportJob", OutputListKey: "annotationImportJobs", OutputItemKey: "", Method: "POST", URI: "/import/annotations"}, + "ListAnnotationStoreVersions": {Verb: "List", Resource: "AnnotationStoreVersion", OutputListKey: "annotationStoreVersions", OutputItemKey: "", Method: "POST", URI: "/annotationStore/{name}/versions"}, + "ListAnnotationStores": {Verb: "List", Resource: "AnnotationStore", OutputListKey: "annotationStores", OutputItemKey: "", Method: "POST", URI: "/annotationStores"}, + "ListBatch": {Verb: "List", Resource: "Batch", OutputListKey: "items", OutputItemKey: "", Method: "GET", URI: "/runBatch"}, + "ListConfigurations": {Verb: "List", Resource: "Configuration", OutputListKey: "items", OutputItemKey: "", Method: "GET", URI: "/configuration"}, + "ListMultipartReadSetUploads": {Verb: "List", Resource: "MultipartReadSetUpload", OutputListKey: "uploads", OutputItemKey: "", Method: "POST", URI: "/sequencestore/{sequenceStoreId}/uploads"}, + "ListReadSetActivationJobs": {Verb: "List", Resource: "ReadSetActivationJob", OutputListKey: "activationJobs", OutputItemKey: "", Method: "POST", URI: "/sequencestore/{sequenceStoreId}/activationjobs"}, + "ListReadSetExportJobs": {Verb: "List", Resource: "ReadSetExportJob", OutputListKey: "exportJobs", OutputItemKey: "", Method: "POST", URI: "/sequencestore/{sequenceStoreId}/exportjobs"}, + "ListReadSetImportJobs": {Verb: "List", Resource: "ReadSetImportJob", OutputListKey: "importJobs", OutputItemKey: "", Method: "POST", URI: "/sequencestore/{sequenceStoreId}/importjobs"}, + "ListReadSetUploadParts": {Verb: "List", Resource: "ReadSetUploadPart", OutputListKey: "parts", OutputItemKey: "", Method: "POST", URI: "/sequencestore/{sequenceStoreId}/upload/{uploadId}/parts"}, + "ListReadSets": {Verb: "List", Resource: "ReadSet", OutputListKey: "readSets", OutputItemKey: "", Method: "POST", URI: "/sequencestore/{sequenceStoreId}/readsets"}, + "ListReferenceImportJobs": {Verb: "List", Resource: "ReferenceImportJob", OutputListKey: "importJobs", OutputItemKey: "", Method: "POST", URI: "/referencestore/{referenceStoreId}/importjobs"}, + "ListReferenceStores": {Verb: "List", Resource: "ReferenceStore", OutputListKey: "referenceStores", OutputItemKey: "", Method: "POST", URI: "/referencestores"}, + "ListReferences": {Verb: "List", Resource: "Reference", OutputListKey: "references", OutputItemKey: "", Method: "POST", URI: "/referencestore/{referenceStoreId}/references"}, + "ListRunCaches": {Verb: "List", Resource: "RunCache", OutputListKey: "items", OutputItemKey: "", Method: "GET", URI: "/runCache"}, + "ListRunGroups": {Verb: "List", Resource: "RunGroup", OutputListKey: "items", OutputItemKey: "", Method: "GET", URI: "/runGroup"}, + "ListRunTasks": {Verb: "List", Resource: "RunTask", OutputListKey: "items", OutputItemKey: "", Method: "GET", URI: "/run/{id}/task"}, + "ListRuns": {Verb: "List", Resource: "Run", OutputListKey: "items", OutputItemKey: "", Method: "GET", URI: "/run"}, + "ListRunsInBatch": {Verb: "List", Resource: "RunsInBatch", OutputListKey: "runs", OutputItemKey: "", Method: "GET", URI: "/runBatch/{batchId}/run"}, + "ListSequenceStores": {Verb: "List", Resource: "SequenceStore", OutputListKey: "sequenceStores", OutputItemKey: "", Method: "POST", URI: "/sequencestores"}, + "ListShares": {Verb: "List", Resource: "Share", OutputListKey: "shares", OutputItemKey: "", Method: "POST", URI: "/shares"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/tags/{resourceArn}"}, + "ListVariantImportJobs": {Verb: "List", Resource: "VariantImportJob", OutputListKey: "variantImportJobs", OutputItemKey: "", Method: "POST", URI: "/import/variants"}, + "ListVariantStores": {Verb: "List", Resource: "VariantStore", OutputListKey: "variantStores", OutputItemKey: "", Method: "POST", URI: "/variantStores"}, + "ListWorkflowVersions": {Verb: "List", Resource: "WorkflowVersion", OutputListKey: "items", OutputItemKey: "", Method: "GET", URI: "/workflow/{workflowId}/version"}, + "ListWorkflows": {Verb: "List", Resource: "Workflow", OutputListKey: "items", OutputItemKey: "", Method: "GET", URI: "/workflow"}, + "PutS3AccessPolicy": {Verb: "Update", Resource: "S3AccessPolicy", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/s3accesspolicy/{s3AccessPointArn}"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/tags/{resourceArn}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/tags/{resourceArn}"}, + "UpdateAnnotationStore": {Verb: "Update", Resource: "AnnotationStore", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/annotationStore/{name}"}, + "UpdateAnnotationStoreVersion": {Verb: "Update", Resource: "AnnotationStoreVersion", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/annotationStore/{name}/version/{versionName}"}, + "UpdateRunCache": {Verb: "Update", Resource: "RunCache", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/runCache/{id}"}, + "UpdateRunGroup": {Verb: "Update", Resource: "RunGroup", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/runGroup/{id}"}, + "UpdateSequenceStore": {Verb: "Update", Resource: "SequenceStore", OutputListKey: "propagatedSetLevelTags", OutputItemKey: "s3Access", Method: "PATCH", URI: "/sequencestore/{id}"}, + "UpdateVariantStore": {Verb: "Update", Resource: "VariantStore", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/variantStore/{name}"}, + "UpdateWorkflow": {Verb: "Update", Resource: "Workflow", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/workflow/{id}"}, + "UpdateWorkflowVersion": {Verb: "Update", Resource: "WorkflowVersion", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/workflow/{workflowId}/version/{versionName}"}, + }) + crud.Register("opensearch", map[string]crud.OpMeta{ + "CreateApplication": {Verb: "Create", Resource: "Application", OutputListKey: "appConfigs", OutputItemKey: "iamIdentityCenterOptions", Method: "POST", URI: "/2021-01-01/opensearch/application"}, + "CreateDomain": {Verb: "Create", Resource: "Domain", OutputListKey: "", OutputItemKey: "DomainStatus", Method: "POST", URI: "/2021-01-01/opensearch/domain"}, + "CreateIndex": {Verb: "Create", Resource: "Index", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/2021-01-01/opensearch/domain/{DomainName}/index"}, + "CreateOutboundConnection": {Verb: "Create", Resource: "OutboundConnection", OutputListKey: "", OutputItemKey: "ConnectionProperties", Method: "POST", URI: "/2021-01-01/opensearch/cc/outboundConnection"}, + "CreatePackage": {Verb: "Create", Resource: "Package", OutputListKey: "", OutputItemKey: "PackageDetails", Method: "POST", URI: "/2021-01-01/packages"}, + "CreateVpcEndpoint": {Verb: "Create", Resource: "VpcEndpoint", OutputListKey: "", OutputItemKey: "VpcEndpoint", Method: "POST", URI: "/2021-01-01/opensearch/vpcEndpoints"}, + "DeleteApplication": {Verb: "Delete", Resource: "Application", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2021-01-01/opensearch/application/{id}"}, + "DeleteDataSource": {Verb: "Delete", Resource: "DataSource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2021-01-01/opensearch/domain/{DomainName}/dataSource/{Name}"}, + "DeleteDirectQueryDataSource": {Verb: "Delete", Resource: "DirectQueryDataSource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2021-01-01/opensearch/directQueryDataSource/{DataSourceName}"}, + "DeleteDomain": {Verb: "Delete", Resource: "Domain", OutputListKey: "", OutputItemKey: "DomainStatus", Method: "DELETE", URI: "/2021-01-01/opensearch/domain/{DomainName}"}, + "DeleteInboundConnection": {Verb: "Delete", Resource: "InboundConnection", OutputListKey: "", OutputItemKey: "Connection", Method: "DELETE", URI: "/2021-01-01/opensearch/cc/inboundConnection/{ConnectionId}"}, + "DeleteIndex": {Verb: "Delete", Resource: "Index", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2021-01-01/opensearch/domain/{DomainName}/index/{IndexName}"}, + "DeleteOutboundConnection": {Verb: "Delete", Resource: "OutboundConnection", OutputListKey: "", OutputItemKey: "Connection", Method: "DELETE", URI: "/2021-01-01/opensearch/cc/outboundConnection/{ConnectionId}"}, + "DeletePackage": {Verb: "Delete", Resource: "Package", OutputListKey: "", OutputItemKey: "PackageDetails", Method: "DELETE", URI: "/2021-01-01/packages/{PackageID}"}, + "DeleteVpcEndpoint": {Verb: "Delete", Resource: "VpcEndpoint", OutputListKey: "", OutputItemKey: "VpcEndpointSummary", Method: "DELETE", URI: "/2021-01-01/opensearch/vpcEndpoints/{VpcEndpointId}"}, + "DeregisterCapability": {Verb: "Delete", Resource: "Capability", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2021-01-01/opensearch/application/{applicationId}/capability/deregister/{capabilityName}"}, + "DescribeDomain": {Verb: "Get", Resource: "Domain", OutputListKey: "", OutputItemKey: "DomainStatus", Method: "GET", URI: "/2021-01-01/opensearch/domain/{DomainName}"}, + "DescribeDomainAutoTunes": {Verb: "Get", Resource: "DomainAutoTune", OutputListKey: "AutoTunes", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/opensearch/domain/{DomainName}/autoTunes"}, + "DescribeDomainChangeProgress": {Verb: "Get", Resource: "DomainChangeProgress", OutputListKey: "", OutputItemKey: "ChangeProgressStatus", Method: "GET", URI: "/2021-01-01/opensearch/domain/{DomainName}/progress"}, + "DescribeDomainConfig": {Verb: "Get", Resource: "DomainConfig", OutputListKey: "", OutputItemKey: "DomainConfig", Method: "GET", URI: "/2021-01-01/opensearch/domain/{DomainName}/config"}, + "DescribeDomainHealth": {Verb: "Get", Resource: "DomainHealth", OutputListKey: "EnvironmentInformation", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/opensearch/domain/{DomainName}/health"}, + "DescribeDomainNodes": {Verb: "Get", Resource: "DomainNode", OutputListKey: "DomainNodesStatusList", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/opensearch/domain/{DomainName}/nodes"}, + "DescribeDomains": {Verb: "Get", Resource: "Domain", OutputListKey: "DomainStatusList", OutputItemKey: "", Method: "POST", URI: "/2021-01-01/opensearch/domain-info"}, + "DescribeDryRunProgress": {Verb: "Get", Resource: "DryRunProgress", OutputListKey: "", OutputItemKey: "DryRunConfig", Method: "GET", URI: "/2021-01-01/opensearch/domain/{DomainName}/dryRun"}, + "DescribeInboundConnections": {Verb: "Get", Resource: "InboundConnection", OutputListKey: "Connections", OutputItemKey: "", Method: "POST", URI: "/2021-01-01/opensearch/cc/inboundConnection/search"}, + "DescribeInsightDetails": {Verb: "Get", Resource: "InsightDetail", OutputListKey: "Fields", OutputItemKey: "", Method: "POST", URI: "/2021-01-01/opensearch/insight-details"}, + "DescribeInstanceTypeLimits": {Verb: "Get", Resource: "InstanceTypeLimit", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/opensearch/instanceTypeLimits/{EngineVersion}/{InstanceType}"}, + "DescribeOutboundConnections": {Verb: "Get", Resource: "OutboundConnection", OutputListKey: "Connections", OutputItemKey: "", Method: "POST", URI: "/2021-01-01/opensearch/cc/outboundConnection/search"}, + "DescribePackages": {Verb: "Get", Resource: "Package", OutputListKey: "PackageDetailsList", OutputItemKey: "", Method: "POST", URI: "/2021-01-01/packages/describe"}, + "DescribeReservedInstanceOfferings": {Verb: "Get", Resource: "ReservedInstanceOffering", OutputListKey: "ReservedInstanceOfferings", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/opensearch/reservedInstanceOfferings"}, + "DescribeReservedInstances": {Verb: "Get", Resource: "ReservedInstance", OutputListKey: "ReservedInstances", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/opensearch/reservedInstances"}, + "DescribeVpcEndpoints": {Verb: "Get", Resource: "VpcEndpoint", OutputListKey: "VpcEndpointErrors", OutputItemKey: "", Method: "POST", URI: "/2021-01-01/opensearch/vpcEndpoints/describe"}, + "GetApplication": {Verb: "Get", Resource: "Application", OutputListKey: "appConfigs", OutputItemKey: "iamIdentityCenterOptions", Method: "GET", URI: "/2021-01-01/opensearch/application/{id}"}, + "GetCapability": {Verb: "Get", Resource: "Capability", OutputListKey: "failures", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/opensearch/application/{applicationId}/capability/{capabilityName}"}, + "GetCompatibleVersions": {Verb: "Get", Resource: "CompatibleVersion", OutputListKey: "CompatibleVersions", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/opensearch/compatibleVersions"}, + "GetDataSource": {Verb: "Get", Resource: "DataSource", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/opensearch/domain/{DomainName}/dataSource/{Name}"}, + "GetDefaultApplicationSetting": {Verb: "Get", Resource: "DefaultApplicationSetting", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/opensearch/defaultApplicationSetting"}, + "GetDirectQueryDataSource": {Verb: "Get", Resource: "DirectQueryDataSource", OutputListKey: "OpenSearchArns", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/opensearch/directQueryDataSource/{DataSourceName}"}, + "GetDomainMaintenanceStatus": {Verb: "Get", Resource: "DomainMaintenanceStatu", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/opensearch/domain/{DomainName}/domainMaintenance"}, + "GetIndex": {Verb: "Get", Resource: "Index", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/opensearch/domain/{DomainName}/index/{IndexName}"}, + "GetPackageVersionHistory": {Verb: "Get", Resource: "PackageVersionHistory", OutputListKey: "PackageVersionHistoryList", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/packages/{PackageID}/history"}, + "GetUpgradeHistory": {Verb: "Get", Resource: "UpgradeHistory", OutputListKey: "UpgradeHistories", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/opensearch/upgradeDomain/{DomainName}/history"}, + "GetUpgradeStatus": {Verb: "Get", Resource: "UpgradeStatu", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/opensearch/upgradeDomain/{DomainName}/status"}, + "ListApplications": {Verb: "List", Resource: "Application", OutputListKey: "ApplicationSummaries", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/opensearch/list-applications"}, + "ListDataSources": {Verb: "List", Resource: "DataSource", OutputListKey: "DataSources", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/opensearch/domain/{DomainName}/dataSource"}, + "ListDirectQueryDataSources": {Verb: "List", Resource: "DirectQueryDataSource", OutputListKey: "DirectQueryDataSources", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/opensearch/directQueryDataSource"}, + "ListDomainMaintenances": {Verb: "List", Resource: "DomainMaintenance", OutputListKey: "DomainMaintenances", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/opensearch/domain/{DomainName}/domainMaintenances"}, + "ListDomainNames": {Verb: "List", Resource: "DomainName", OutputListKey: "DomainNames", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/domain"}, + "ListDomainsForPackage": {Verb: "List", Resource: "DomainsForPackage", OutputListKey: "DomainPackageDetailsList", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/packages/{PackageID}/domains"}, + "ListInsights": {Verb: "List", Resource: "Insight", OutputListKey: "Insights", OutputItemKey: "", Method: "POST", URI: "/2021-01-01/opensearch/insights"}, + "ListInstanceTypeDetails": {Verb: "List", Resource: "InstanceTypeDetail", OutputListKey: "InstanceTypeDetails", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/opensearch/instanceTypeDetails/{EngineVersion}"}, + "ListPackagesForDomain": {Verb: "List", Resource: "PackagesForDomain", OutputListKey: "DomainPackageDetailsList", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/domain/{DomainName}/packages"}, + "ListScheduledActions": {Verb: "List", Resource: "ScheduledAction", OutputListKey: "ScheduledActions", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/opensearch/domain/{DomainName}/scheduledActions"}, + "ListTags": {Verb: "List", Resource: "Tag", OutputListKey: "TagList", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/tags"}, + "ListVersions": {Verb: "List", Resource: "Version", OutputListKey: "Versions", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/opensearch/versions"}, + "ListVpcEndpointAccess": {Verb: "List", Resource: "VpcEndpointAccess", OutputListKey: "AuthorizedPrincipalList", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/opensearch/domain/{DomainName}/listVpcEndpointAccess"}, + "ListVpcEndpoints": {Verb: "List", Resource: "VpcEndpoint", OutputListKey: "VpcEndpointSummaryList", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/opensearch/vpcEndpoints"}, + "ListVpcEndpointsForDomain": {Verb: "List", Resource: "VpcEndpointsForDomain", OutputListKey: "VpcEndpointSummaryList", OutputItemKey: "", Method: "GET", URI: "/2021-01-01/opensearch/domain/{DomainName}/vpcEndpoints"}, + "PutDefaultApplicationSetting": {Verb: "Update", Resource: "DefaultApplicationSetting", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/2021-01-01/opensearch/defaultApplicationSetting"}, + "RegisterCapability": {Verb: "Create", Resource: "Capability", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/2021-01-01/opensearch/application/{applicationId}/capability/register"}, + "UpdateApplication": {Verb: "Update", Resource: "Application", OutputListKey: "appConfigs", OutputItemKey: "iamIdentityCenterOptions", Method: "PUT", URI: "/2021-01-01/opensearch/application/{id}"}, + "UpdateDataSource": {Verb: "Update", Resource: "DataSource", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/2021-01-01/opensearch/domain/{DomainName}/dataSource/{Name}"}, + "UpdateDirectQueryDataSource": {Verb: "Update", Resource: "DirectQueryDataSource", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/2021-01-01/opensearch/directQueryDataSource/{DataSourceName}"}, + "UpdateDomainConfig": {Verb: "Update", Resource: "DomainConfig", OutputListKey: "", OutputItemKey: "DomainConfig", Method: "POST", URI: "/2021-01-01/opensearch/domain/{DomainName}/config"}, + "UpdateIndex": {Verb: "Update", Resource: "Index", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/2021-01-01/opensearch/domain/{DomainName}/index/{IndexName}"}, + "UpdatePackage": {Verb: "Update", Resource: "Package", OutputListKey: "", OutputItemKey: "PackageDetails", Method: "POST", URI: "/2021-01-01/packages/update"}, + "UpdatePackageScope": {Verb: "Update", Resource: "PackageScope", OutputListKey: "PackageUserList", OutputItemKey: "", Method: "POST", URI: "/2021-01-01/packages/updateScope"}, + "UpdateScheduledAction": {Verb: "Update", Resource: "ScheduledAction", OutputListKey: "", OutputItemKey: "ScheduledAction", Method: "PUT", URI: "/2021-01-01/opensearch/domain/{DomainName}/scheduledAction/update"}, + "UpdateVpcEndpoint": {Verb: "Update", Resource: "VpcEndpoint", OutputListKey: "", OutputItemKey: "VpcEndpoint", Method: "POST", URI: "/2021-01-01/opensearch/vpcEndpoints/update"}, + }) crud.Register("organizations", map[string]crud.OpMeta{ "CreateAccount": {Verb: "Create", Resource: "Account", OutputListKey: "", OutputItemKey: "CreateAccountStatus"}, "CreateGovCloudAccount": {Verb: "Create", Resource: "GovCloudAccount", OutputListKey: "", OutputItemKey: "CreateAccountStatus"}, @@ -1800,6 +3826,270 @@ func init() { "UpdateRecommender": {Verb: "Update", Resource: "Recommender", OutputListKey: "", OutputItemKey: ""}, "UpdateSolution": {Verb: "Update", Resource: "Solution", OutputListKey: "", OutputItemKey: ""}, }) + crud.Register("personalizeevents", map[string]crud.OpMeta{ + "PutActionInteractions": {Verb: "Update", Resource: "ActionInteraction", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/action-interactions"}, + "PutActions": {Verb: "Update", Resource: "Action", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/actions"}, + "PutEvents": {Verb: "Update", Resource: "Event", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/events"}, + "PutItems": {Verb: "Update", Resource: "Item", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/items"}, + "PutUsers": {Verb: "Update", Resource: "User", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/users"}, + }) + crud.Register("personalizeruntime", map[string]crud.OpMeta{ + "GetActionRecommendations": {Verb: "Get", Resource: "ActionRecommendation", OutputListKey: "actionList", OutputItemKey: "", Method: "POST", URI: "/action-recommendations"}, + "GetPersonalizedRanking": {Verb: "Get", Resource: "PersonalizedRanking", OutputListKey: "personalizedRanking", OutputItemKey: "", Method: "POST", URI: "/personalize-ranking"}, + "GetRecommendations": {Verb: "Get", Resource: "Recommendation", OutputListKey: "itemList", OutputItemKey: "", Method: "POST", URI: "/recommendations"}, + }) + crud.Register("pinpoint", map[string]crud.OpMeta{ + "CreateApp": {Verb: "Create", Resource: "App", OutputListKey: "", OutputItemKey: "ApplicationResponse", Method: "POST", URI: "/v1/apps"}, + "CreateCampaign": {Verb: "Create", Resource: "Campaign", OutputListKey: "", OutputItemKey: "CampaignResponse", Method: "POST", URI: "/v1/apps/{ApplicationId}/campaigns"}, + "CreateEmailTemplate": {Verb: "Create", Resource: "EmailTemplate", OutputListKey: "", OutputItemKey: "CreateTemplateMessageBody", Method: "POST", URI: "/v1/templates/{TemplateName}/email"}, + "CreateExportJob": {Verb: "Create", Resource: "ExportJob", OutputListKey: "", OutputItemKey: "ExportJobResponse", Method: "POST", URI: "/v1/apps/{ApplicationId}/jobs/export"}, + "CreateImportJob": {Verb: "Create", Resource: "ImportJob", OutputListKey: "", OutputItemKey: "ImportJobResponse", Method: "POST", URI: "/v1/apps/{ApplicationId}/jobs/import"}, + "CreateInAppTemplate": {Verb: "Create", Resource: "InAppTemplate", OutputListKey: "", OutputItemKey: "TemplateCreateMessageBody", Method: "POST", URI: "/v1/templates/{TemplateName}/inapp"}, + "CreateJourney": {Verb: "Create", Resource: "Journey", OutputListKey: "", OutputItemKey: "JourneyResponse", Method: "POST", URI: "/v1/apps/{ApplicationId}/journeys"}, + "CreatePushTemplate": {Verb: "Create", Resource: "PushTemplate", OutputListKey: "", OutputItemKey: "CreateTemplateMessageBody", Method: "POST", URI: "/v1/templates/{TemplateName}/push"}, + "CreateRecommenderConfiguration": {Verb: "Create", Resource: "RecommenderConfiguration", OutputListKey: "", OutputItemKey: "RecommenderConfigurationResponse", Method: "POST", URI: "/v1/recommenders"}, + "CreateSegment": {Verb: "Create", Resource: "Segment", OutputListKey: "", OutputItemKey: "SegmentResponse", Method: "POST", URI: "/v1/apps/{ApplicationId}/segments"}, + "CreateSmsTemplate": {Verb: "Create", Resource: "SmsTemplate", OutputListKey: "", OutputItemKey: "CreateTemplateMessageBody", Method: "POST", URI: "/v1/templates/{TemplateName}/sms"}, + "CreateVoiceTemplate": {Verb: "Create", Resource: "VoiceTemplate", OutputListKey: "", OutputItemKey: "CreateTemplateMessageBody", Method: "POST", URI: "/v1/templates/{TemplateName}/voice"}, + "DeleteAdmChannel": {Verb: "Delete", Resource: "AdmChannel", OutputListKey: "", OutputItemKey: "ADMChannelResponse", Method: "DELETE", URI: "/v1/apps/{ApplicationId}/channels/adm"}, + "DeleteApnsChannel": {Verb: "Delete", Resource: "ApnsChannel", OutputListKey: "", OutputItemKey: "APNSChannelResponse", Method: "DELETE", URI: "/v1/apps/{ApplicationId}/channels/apns"}, + "DeleteApnsSandboxChannel": {Verb: "Delete", Resource: "ApnsSandboxChannel", OutputListKey: "", OutputItemKey: "APNSSandboxChannelResponse", Method: "DELETE", URI: "/v1/apps/{ApplicationId}/channels/apns_sandbox"}, + "DeleteApnsVoipChannel": {Verb: "Delete", Resource: "ApnsVoipChannel", OutputListKey: "", OutputItemKey: "APNSVoipChannelResponse", Method: "DELETE", URI: "/v1/apps/{ApplicationId}/channels/apns_voip"}, + "DeleteApnsVoipSandboxChannel": {Verb: "Delete", Resource: "ApnsVoipSandboxChannel", OutputListKey: "", OutputItemKey: "APNSVoipSandboxChannelResponse", Method: "DELETE", URI: "/v1/apps/{ApplicationId}/channels/apns_voip_sandbox"}, + "DeleteApp": {Verb: "Delete", Resource: "App", OutputListKey: "", OutputItemKey: "ApplicationResponse", Method: "DELETE", URI: "/v1/apps/{ApplicationId}"}, + "DeleteBaiduChannel": {Verb: "Delete", Resource: "BaiduChannel", OutputListKey: "", OutputItemKey: "BaiduChannelResponse", Method: "DELETE", URI: "/v1/apps/{ApplicationId}/channels/baidu"}, + "DeleteCampaign": {Verb: "Delete", Resource: "Campaign", OutputListKey: "", OutputItemKey: "CampaignResponse", Method: "DELETE", URI: "/v1/apps/{ApplicationId}/campaigns/{CampaignId}"}, + "DeleteEmailChannel": {Verb: "Delete", Resource: "EmailChannel", OutputListKey: "", OutputItemKey: "EmailChannelResponse", Method: "DELETE", URI: "/v1/apps/{ApplicationId}/channels/email"}, + "DeleteEmailTemplate": {Verb: "Delete", Resource: "EmailTemplate", OutputListKey: "", OutputItemKey: "MessageBody", Method: "DELETE", URI: "/v1/templates/{TemplateName}/email"}, + "DeleteEndpoint": {Verb: "Delete", Resource: "Endpoint", OutputListKey: "", OutputItemKey: "EndpointResponse", Method: "DELETE", URI: "/v1/apps/{ApplicationId}/endpoints/{EndpointId}"}, + "DeleteEventStream": {Verb: "Delete", Resource: "EventStream", OutputListKey: "", OutputItemKey: "EventStream", Method: "DELETE", URI: "/v1/apps/{ApplicationId}/eventstream"}, + "DeleteGcmChannel": {Verb: "Delete", Resource: "GcmChannel", OutputListKey: "", OutputItemKey: "GCMChannelResponse", Method: "DELETE", URI: "/v1/apps/{ApplicationId}/channels/gcm"}, + "DeleteInAppTemplate": {Verb: "Delete", Resource: "InAppTemplate", OutputListKey: "", OutputItemKey: "MessageBody", Method: "DELETE", URI: "/v1/templates/{TemplateName}/inapp"}, + "DeleteJourney": {Verb: "Delete", Resource: "Journey", OutputListKey: "", OutputItemKey: "JourneyResponse", Method: "DELETE", URI: "/v1/apps/{ApplicationId}/journeys/{JourneyId}"}, + "DeletePushTemplate": {Verb: "Delete", Resource: "PushTemplate", OutputListKey: "", OutputItemKey: "MessageBody", Method: "DELETE", URI: "/v1/templates/{TemplateName}/push"}, + "DeleteRecommenderConfiguration": {Verb: "Delete", Resource: "RecommenderConfiguration", OutputListKey: "", OutputItemKey: "RecommenderConfigurationResponse", Method: "DELETE", URI: "/v1/recommenders/{RecommenderId}"}, + "DeleteSegment": {Verb: "Delete", Resource: "Segment", OutputListKey: "", OutputItemKey: "SegmentResponse", Method: "DELETE", URI: "/v1/apps/{ApplicationId}/segments/{SegmentId}"}, + "DeleteSmsChannel": {Verb: "Delete", Resource: "SmsChannel", OutputListKey: "", OutputItemKey: "SMSChannelResponse", Method: "DELETE", URI: "/v1/apps/{ApplicationId}/channels/sms"}, + "DeleteSmsTemplate": {Verb: "Delete", Resource: "SmsTemplate", OutputListKey: "", OutputItemKey: "MessageBody", Method: "DELETE", URI: "/v1/templates/{TemplateName}/sms"}, + "DeleteUserEndpoints": {Verb: "Delete", Resource: "UserEndpoint", OutputListKey: "", OutputItemKey: "EndpointsResponse", Method: "DELETE", URI: "/v1/apps/{ApplicationId}/users/{UserId}"}, + "DeleteVoiceChannel": {Verb: "Delete", Resource: "VoiceChannel", OutputListKey: "", OutputItemKey: "VoiceChannelResponse", Method: "DELETE", URI: "/v1/apps/{ApplicationId}/channels/voice"}, + "DeleteVoiceTemplate": {Verb: "Delete", Resource: "VoiceTemplate", OutputListKey: "", OutputItemKey: "MessageBody", Method: "DELETE", URI: "/v1/templates/{TemplateName}/voice"}, + "GetAdmChannel": {Verb: "Get", Resource: "AdmChannel", OutputListKey: "", OutputItemKey: "ADMChannelResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/channels/adm"}, + "GetApnsChannel": {Verb: "Get", Resource: "ApnsChannel", OutputListKey: "", OutputItemKey: "APNSChannelResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/channels/apns"}, + "GetApnsSandboxChannel": {Verb: "Get", Resource: "ApnsSandboxChannel", OutputListKey: "", OutputItemKey: "APNSSandboxChannelResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/channels/apns_sandbox"}, + "GetApnsVoipChannel": {Verb: "Get", Resource: "ApnsVoipChannel", OutputListKey: "", OutputItemKey: "APNSVoipChannelResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/channels/apns_voip"}, + "GetApnsVoipSandboxChannel": {Verb: "Get", Resource: "ApnsVoipSandboxChannel", OutputListKey: "", OutputItemKey: "APNSVoipSandboxChannelResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/channels/apns_voip_sandbox"}, + "GetApp": {Verb: "Get", Resource: "App", OutputListKey: "", OutputItemKey: "ApplicationResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}"}, + "GetApplicationDateRangeKpi": {Verb: "Get", Resource: "ApplicationDateRangeKpi", OutputListKey: "", OutputItemKey: "ApplicationDateRangeKpiResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/kpis/daterange/{KpiName}"}, + "GetApplicationSettings": {Verb: "Get", Resource: "ApplicationSetting", OutputListKey: "", OutputItemKey: "ApplicationSettingsResource", Method: "GET", URI: "/v1/apps/{ApplicationId}/settings"}, + "GetApps": {Verb: "Get", Resource: "App", OutputListKey: "", OutputItemKey: "ApplicationsResponse", Method: "GET", URI: "/v1/apps"}, + "GetBaiduChannel": {Verb: "Get", Resource: "BaiduChannel", OutputListKey: "", OutputItemKey: "BaiduChannelResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/channels/baidu"}, + "GetCampaign": {Verb: "Get", Resource: "Campaign", OutputListKey: "", OutputItemKey: "CampaignResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/campaigns/{CampaignId}"}, + "GetCampaignActivities": {Verb: "Get", Resource: "CampaignActivity", OutputListKey: "", OutputItemKey: "ActivitiesResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/campaigns/{CampaignId}/activities"}, + "GetCampaignDateRangeKpi": {Verb: "Get", Resource: "CampaignDateRangeKpi", OutputListKey: "", OutputItemKey: "CampaignDateRangeKpiResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/campaigns/{CampaignId}/kpis/daterange/{KpiName}"}, + "GetCampaignVersion": {Verb: "Get", Resource: "CampaignVersion", OutputListKey: "", OutputItemKey: "CampaignResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/campaigns/{CampaignId}/versions/{Version}"}, + "GetCampaignVersions": {Verb: "Get", Resource: "CampaignVersion", OutputListKey: "", OutputItemKey: "CampaignsResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/campaigns/{CampaignId}/versions"}, + "GetCampaigns": {Verb: "Get", Resource: "Campaign", OutputListKey: "", OutputItemKey: "CampaignsResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/campaigns"}, + "GetChannels": {Verb: "Get", Resource: "Channel", OutputListKey: "", OutputItemKey: "ChannelsResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/channels"}, + "GetEmailChannel": {Verb: "Get", Resource: "EmailChannel", OutputListKey: "", OutputItemKey: "EmailChannelResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/channels/email"}, + "GetEmailTemplate": {Verb: "Get", Resource: "EmailTemplate", OutputListKey: "", OutputItemKey: "EmailTemplateResponse", Method: "GET", URI: "/v1/templates/{TemplateName}/email"}, + "GetEndpoint": {Verb: "Get", Resource: "Endpoint", OutputListKey: "", OutputItemKey: "EndpointResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/endpoints/{EndpointId}"}, + "GetEventStream": {Verb: "Get", Resource: "EventStream", OutputListKey: "", OutputItemKey: "EventStream", Method: "GET", URI: "/v1/apps/{ApplicationId}/eventstream"}, + "GetExportJob": {Verb: "Get", Resource: "ExportJob", OutputListKey: "", OutputItemKey: "ExportJobResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/jobs/export/{JobId}"}, + "GetExportJobs": {Verb: "Get", Resource: "ExportJob", OutputListKey: "", OutputItemKey: "ExportJobsResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/jobs/export"}, + "GetGcmChannel": {Verb: "Get", Resource: "GcmChannel", OutputListKey: "", OutputItemKey: "GCMChannelResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/channels/gcm"}, + "GetImportJob": {Verb: "Get", Resource: "ImportJob", OutputListKey: "", OutputItemKey: "ImportJobResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/jobs/import/{JobId}"}, + "GetImportJobs": {Verb: "Get", Resource: "ImportJob", OutputListKey: "", OutputItemKey: "ImportJobsResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/jobs/import"}, + "GetInAppMessages": {Verb: "Get", Resource: "InAppMessage", OutputListKey: "", OutputItemKey: "InAppMessagesResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/endpoints/{EndpointId}/inappmessages"}, + "GetInAppTemplate": {Verb: "Get", Resource: "InAppTemplate", OutputListKey: "", OutputItemKey: "InAppTemplateResponse", Method: "GET", URI: "/v1/templates/{TemplateName}/inapp"}, + "GetJourney": {Verb: "Get", Resource: "Journey", OutputListKey: "", OutputItemKey: "JourneyResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/journeys/{JourneyId}"}, + "GetJourneyDateRangeKpi": {Verb: "Get", Resource: "JourneyDateRangeKpi", OutputListKey: "", OutputItemKey: "JourneyDateRangeKpiResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/journeys/{JourneyId}/kpis/daterange/{KpiName}"}, + "GetJourneyExecutionActivityMetrics": {Verb: "Get", Resource: "JourneyExecutionActivityMetric", OutputListKey: "", OutputItemKey: "JourneyExecutionActivityMetricsResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/journeys/{JourneyId}/activities/{JourneyActivityId}/execution-metrics"}, + "GetJourneyExecutionMetrics": {Verb: "Get", Resource: "JourneyExecutionMetric", OutputListKey: "", OutputItemKey: "JourneyExecutionMetricsResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/journeys/{JourneyId}/execution-metrics"}, + "GetJourneyRunExecutionActivityMetrics": {Verb: "Get", Resource: "JourneyRunExecutionActivityMetric", OutputListKey: "", OutputItemKey: "JourneyRunExecutionActivityMetricsResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/journeys/{JourneyId}/runs/{RunId}/activities/{JourneyActivityId}/execution-metrics"}, + "GetJourneyRunExecutionMetrics": {Verb: "Get", Resource: "JourneyRunExecutionMetric", OutputListKey: "", OutputItemKey: "JourneyRunExecutionMetricsResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/journeys/{JourneyId}/runs/{RunId}/execution-metrics"}, + "GetJourneyRuns": {Verb: "Get", Resource: "JourneyRun", OutputListKey: "", OutputItemKey: "JourneyRunsResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/journeys/{JourneyId}/runs"}, + "GetPushTemplate": {Verb: "Get", Resource: "PushTemplate", OutputListKey: "", OutputItemKey: "PushNotificationTemplateResponse", Method: "GET", URI: "/v1/templates/{TemplateName}/push"}, + "GetRecommenderConfiguration": {Verb: "Get", Resource: "RecommenderConfiguration", OutputListKey: "", OutputItemKey: "RecommenderConfigurationResponse", Method: "GET", URI: "/v1/recommenders/{RecommenderId}"}, + "GetRecommenderConfigurations": {Verb: "Get", Resource: "RecommenderConfiguration", OutputListKey: "", OutputItemKey: "ListRecommenderConfigurationsResponse", Method: "GET", URI: "/v1/recommenders"}, + "GetSegment": {Verb: "Get", Resource: "Segment", OutputListKey: "", OutputItemKey: "SegmentResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/segments/{SegmentId}"}, + "GetSegmentExportJobs": {Verb: "Get", Resource: "SegmentExportJob", OutputListKey: "", OutputItemKey: "ExportJobsResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/segments/{SegmentId}/jobs/export"}, + "GetSegmentImportJobs": {Verb: "Get", Resource: "SegmentImportJob", OutputListKey: "", OutputItemKey: "ImportJobsResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/segments/{SegmentId}/jobs/import"}, + "GetSegmentVersion": {Verb: "Get", Resource: "SegmentVersion", OutputListKey: "", OutputItemKey: "SegmentResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/segments/{SegmentId}/versions/{Version}"}, + "GetSegmentVersions": {Verb: "Get", Resource: "SegmentVersion", OutputListKey: "", OutputItemKey: "SegmentsResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/segments/{SegmentId}/versions"}, + "GetSegments": {Verb: "Get", Resource: "Segment", OutputListKey: "", OutputItemKey: "SegmentsResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/segments"}, + "GetSmsChannel": {Verb: "Get", Resource: "SmsChannel", OutputListKey: "", OutputItemKey: "SMSChannelResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/channels/sms"}, + "GetSmsTemplate": {Verb: "Get", Resource: "SmsTemplate", OutputListKey: "", OutputItemKey: "SMSTemplateResponse", Method: "GET", URI: "/v1/templates/{TemplateName}/sms"}, + "GetUserEndpoints": {Verb: "Get", Resource: "UserEndpoint", OutputListKey: "", OutputItemKey: "EndpointsResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/users/{UserId}"}, + "GetVoiceChannel": {Verb: "Get", Resource: "VoiceChannel", OutputListKey: "", OutputItemKey: "VoiceChannelResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/channels/voice"}, + "GetVoiceTemplate": {Verb: "Get", Resource: "VoiceTemplate", OutputListKey: "", OutputItemKey: "VoiceTemplateResponse", Method: "GET", URI: "/v1/templates/{TemplateName}/voice"}, + "ListJourneys": {Verb: "List", Resource: "Journey", OutputListKey: "", OutputItemKey: "JourneysResponse", Method: "GET", URI: "/v1/apps/{ApplicationId}/journeys"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "", OutputItemKey: "TagsModel", Method: "GET", URI: "/v1/tags/{ResourceArn}"}, + "ListTemplateVersions": {Verb: "List", Resource: "TemplateVersion", OutputListKey: "", OutputItemKey: "TemplateVersionsResponse", Method: "GET", URI: "/v1/templates/{TemplateName}/{TemplateType}/versions"}, + "ListTemplates": {Verb: "List", Resource: "Template", OutputListKey: "", OutputItemKey: "TemplatesResponse", Method: "GET", URI: "/v1/templates"}, + "PutEventStream": {Verb: "Update", Resource: "EventStream", OutputListKey: "", OutputItemKey: "EventStream", Method: "POST", URI: "/v1/apps/{ApplicationId}/eventstream"}, + "PutEvents": {Verb: "Update", Resource: "Event", OutputListKey: "", OutputItemKey: "EventsResponse", Method: "POST", URI: "/v1/apps/{ApplicationId}/events"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/tags/{ResourceArn}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v1/tags/{ResourceArn}"}, + "UpdateAdmChannel": {Verb: "Update", Resource: "AdmChannel", OutputListKey: "", OutputItemKey: "ADMChannelResponse", Method: "PUT", URI: "/v1/apps/{ApplicationId}/channels/adm"}, + "UpdateApnsChannel": {Verb: "Update", Resource: "ApnsChannel", OutputListKey: "", OutputItemKey: "APNSChannelResponse", Method: "PUT", URI: "/v1/apps/{ApplicationId}/channels/apns"}, + "UpdateApnsSandboxChannel": {Verb: "Update", Resource: "ApnsSandboxChannel", OutputListKey: "", OutputItemKey: "APNSSandboxChannelResponse", Method: "PUT", URI: "/v1/apps/{ApplicationId}/channels/apns_sandbox"}, + "UpdateApnsVoipChannel": {Verb: "Update", Resource: "ApnsVoipChannel", OutputListKey: "", OutputItemKey: "APNSVoipChannelResponse", Method: "PUT", URI: "/v1/apps/{ApplicationId}/channels/apns_voip"}, + "UpdateApnsVoipSandboxChannel": {Verb: "Update", Resource: "ApnsVoipSandboxChannel", OutputListKey: "", OutputItemKey: "APNSVoipSandboxChannelResponse", Method: "PUT", URI: "/v1/apps/{ApplicationId}/channels/apns_voip_sandbox"}, + "UpdateApplicationSettings": {Verb: "Update", Resource: "ApplicationSetting", OutputListKey: "", OutputItemKey: "ApplicationSettingsResource", Method: "PUT", URI: "/v1/apps/{ApplicationId}/settings"}, + "UpdateBaiduChannel": {Verb: "Update", Resource: "BaiduChannel", OutputListKey: "", OutputItemKey: "BaiduChannelResponse", Method: "PUT", URI: "/v1/apps/{ApplicationId}/channels/baidu"}, + "UpdateCampaign": {Verb: "Update", Resource: "Campaign", OutputListKey: "", OutputItemKey: "CampaignResponse", Method: "PUT", URI: "/v1/apps/{ApplicationId}/campaigns/{CampaignId}"}, + "UpdateEmailChannel": {Verb: "Update", Resource: "EmailChannel", OutputListKey: "", OutputItemKey: "EmailChannelResponse", Method: "PUT", URI: "/v1/apps/{ApplicationId}/channels/email"}, + "UpdateEmailTemplate": {Verb: "Update", Resource: "EmailTemplate", OutputListKey: "", OutputItemKey: "MessageBody", Method: "PUT", URI: "/v1/templates/{TemplateName}/email"}, + "UpdateEndpoint": {Verb: "Update", Resource: "Endpoint", OutputListKey: "", OutputItemKey: "MessageBody", Method: "PUT", URI: "/v1/apps/{ApplicationId}/endpoints/{EndpointId}"}, + "UpdateEndpointsBatch": {Verb: "Update", Resource: "EndpointsBatch", OutputListKey: "", OutputItemKey: "MessageBody", Method: "PUT", URI: "/v1/apps/{ApplicationId}/endpoints"}, + "UpdateGcmChannel": {Verb: "Update", Resource: "GcmChannel", OutputListKey: "", OutputItemKey: "GCMChannelResponse", Method: "PUT", URI: "/v1/apps/{ApplicationId}/channels/gcm"}, + "UpdateInAppTemplate": {Verb: "Update", Resource: "InAppTemplate", OutputListKey: "", OutputItemKey: "MessageBody", Method: "PUT", URI: "/v1/templates/{TemplateName}/inapp"}, + "UpdateJourney": {Verb: "Update", Resource: "Journey", OutputListKey: "", OutputItemKey: "JourneyResponse", Method: "PUT", URI: "/v1/apps/{ApplicationId}/journeys/{JourneyId}"}, + "UpdateJourneyState": {Verb: "Update", Resource: "JourneyState", OutputListKey: "", OutputItemKey: "JourneyResponse", Method: "PUT", URI: "/v1/apps/{ApplicationId}/journeys/{JourneyId}/state"}, + "UpdatePushTemplate": {Verb: "Update", Resource: "PushTemplate", OutputListKey: "", OutputItemKey: "MessageBody", Method: "PUT", URI: "/v1/templates/{TemplateName}/push"}, + "UpdateRecommenderConfiguration": {Verb: "Update", Resource: "RecommenderConfiguration", OutputListKey: "", OutputItemKey: "RecommenderConfigurationResponse", Method: "PUT", URI: "/v1/recommenders/{RecommenderId}"}, + "UpdateSegment": {Verb: "Update", Resource: "Segment", OutputListKey: "", OutputItemKey: "SegmentResponse", Method: "PUT", URI: "/v1/apps/{ApplicationId}/segments/{SegmentId}"}, + "UpdateSmsChannel": {Verb: "Update", Resource: "SmsChannel", OutputListKey: "", OutputItemKey: "SMSChannelResponse", Method: "PUT", URI: "/v1/apps/{ApplicationId}/channels/sms"}, + "UpdateSmsTemplate": {Verb: "Update", Resource: "SmsTemplate", OutputListKey: "", OutputItemKey: "MessageBody", Method: "PUT", URI: "/v1/templates/{TemplateName}/sms"}, + "UpdateTemplateActiveVersion": {Verb: "Update", Resource: "TemplateActiveVersion", OutputListKey: "", OutputItemKey: "MessageBody", Method: "PUT", URI: "/v1/templates/{TemplateName}/{TemplateType}/active-version"}, + "UpdateVoiceChannel": {Verb: "Update", Resource: "VoiceChannel", OutputListKey: "", OutputItemKey: "VoiceChannelResponse", Method: "PUT", URI: "/v1/apps/{ApplicationId}/channels/voice"}, + "UpdateVoiceTemplate": {Verb: "Update", Resource: "VoiceTemplate", OutputListKey: "", OutputItemKey: "MessageBody", Method: "PUT", URI: "/v1/templates/{TemplateName}/voice"}, + }) + crud.Register("polly", map[string]crud.OpMeta{ + "DeleteLexicon": {Verb: "Delete", Resource: "Lexicon", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v1/lexicons/{Name}"}, + "DescribeVoices": {Verb: "Get", Resource: "Voice", OutputListKey: "Voices", OutputItemKey: "", Method: "GET", URI: "/v1/voices"}, + "GetLexicon": {Verb: "Get", Resource: "Lexicon", OutputListKey: "", OutputItemKey: "Lexicon", Method: "GET", URI: "/v1/lexicons/{Name}"}, + "GetSpeechSynthesisTask": {Verb: "Get", Resource: "SpeechSynthesisTask", OutputListKey: "", OutputItemKey: "SynthesisTask", Method: "GET", URI: "/v1/synthesisTasks/{TaskId}"}, + "ListLexicons": {Verb: "List", Resource: "Lexicon", OutputListKey: "Lexicons", OutputItemKey: "", Method: "GET", URI: "/v1/lexicons"}, + "ListSpeechSynthesisTasks": {Verb: "List", Resource: "SpeechSynthesisTask", OutputListKey: "SynthesisTasks", OutputItemKey: "", Method: "GET", URI: "/v1/synthesisTasks"}, + "PutLexicon": {Verb: "Update", Resource: "Lexicon", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v1/lexicons/{Name}"}, + }) + crud.Register("qapps", map[string]crud.OpMeta{ + "CreateLibraryItem": {Verb: "Create", Resource: "LibraryItem", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/catalog.createItem"}, + "CreatePresignedUrl": {Verb: "Create", Resource: "PresignedUrl", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/apps.createPresignedUrl"}, + "CreateQApp": {Verb: "Create", Resource: "QApp", OutputListKey: "requiredCapabilities", OutputItemKey: "", Method: "POST", URI: "/apps.create"}, + "DeleteLibraryItem": {Verb: "Delete", Resource: "LibraryItem", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/catalog.deleteItem"}, + "DeleteQApp": {Verb: "Delete", Resource: "QApp", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/apps.delete"}, + "DescribeQAppPermissions": {Verb: "Get", Resource: "QAppPermission", OutputListKey: "permissions", OutputItemKey: "", Method: "GET", URI: "/apps.describeQAppPermissions"}, + "GetLibraryItem": {Verb: "Get", Resource: "LibraryItem", OutputListKey: "categories", OutputItemKey: "", Method: "GET", URI: "/catalog.getItem"}, + "GetQApp": {Verb: "Get", Resource: "QApp", OutputListKey: "requiredCapabilities", OutputItemKey: "appDefinition", Method: "GET", URI: "/apps.get"}, + "GetQAppSession": {Verb: "Get", Resource: "QAppSession", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/runtime.getQAppSession"}, + "GetQAppSessionMetadata": {Verb: "Get", Resource: "QAppSessionMetadata", OutputListKey: "", OutputItemKey: "sharingConfiguration", Method: "GET", URI: "/runtime.getQAppSessionMetadata"}, + "ListCategories": {Verb: "List", Resource: "Category", OutputListKey: "categories", OutputItemKey: "", Method: "GET", URI: "/catalog.listCategories"}, + "ListLibraryItems": {Verb: "List", Resource: "LibraryItem", OutputListKey: "libraryItems", OutputItemKey: "", Method: "GET", URI: "/catalog.list"}, + "ListQAppSessionData": {Verb: "List", Resource: "QAppSessionData", OutputListKey: "sessionData", OutputItemKey: "", Method: "GET", URI: "/runtime.listQAppSessionData"}, + "ListQApps": {Verb: "List", Resource: "QApp", OutputListKey: "apps", OutputItemKey: "", Method: "GET", URI: "/apps.list"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/tags/{resourceARN}"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/tags/{resourceARN}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/tags/{resourceARN}"}, + "UpdateLibraryItem": {Verb: "Update", Resource: "LibraryItem", OutputListKey: "categories", OutputItemKey: "", Method: "POST", URI: "/catalog.updateItem"}, + "UpdateLibraryItemMetadata": {Verb: "Update", Resource: "LibraryItemMetadata", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/catalog.updateItemMetadata"}, + "UpdateQApp": {Verb: "Update", Resource: "QApp", OutputListKey: "requiredCapabilities", OutputItemKey: "", Method: "POST", URI: "/apps.update"}, + "UpdateQAppPermissions": {Verb: "Update", Resource: "QAppPermission", OutputListKey: "permissions", OutputItemKey: "", Method: "POST", URI: "/apps.updateQAppPermissions"}, + "UpdateQAppSession": {Verb: "Update", Resource: "QAppSession", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/runtime.updateQAppSession"}, + "UpdateQAppSessionMetadata": {Verb: "Update", Resource: "QAppSessionMetadata", OutputListKey: "", OutputItemKey: "sharingConfiguration", Method: "POST", URI: "/runtime.updateQAppSessionMetadata"}, + }) + crud.Register("qbusiness", map[string]crud.OpMeta{ + "CreateAnonymousWebExperienceUrl": {Verb: "Create", Resource: "AnonymousWebExperienceUrl", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/applications/{applicationId}/experiences/{webExperienceId}/anonymous-url"}, + "CreateApplication": {Verb: "Create", Resource: "Application", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/applications"}, + "CreateChatResponseConfiguration": {Verb: "Create", Resource: "ChatResponseConfiguration", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/applications/{applicationId}/chatresponseconfigurations"}, + "CreateDataAccessor": {Verb: "Create", Resource: "DataAccessor", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/applications/{applicationId}/dataaccessors"}, + "CreateDataSource": {Verb: "Create", Resource: "DataSource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/applications/{applicationId}/indices/{indexId}/datasources"}, + "CreateIndex": {Verb: "Create", Resource: "Index", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/applications/{applicationId}/indices"}, + "CreatePlugin": {Verb: "Create", Resource: "Plugin", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/applications/{applicationId}/plugins"}, + "CreateRetriever": {Verb: "Create", Resource: "Retriever", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/applications/{applicationId}/retrievers"}, + "CreateSubscription": {Verb: "Create", Resource: "Subscription", OutputListKey: "", OutputItemKey: "currentSubscription", Method: "POST", URI: "/applications/{applicationId}/subscriptions"}, + "CreateUser": {Verb: "Create", Resource: "User", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/applications/{applicationId}/users"}, + "CreateWebExperience": {Verb: "Create", Resource: "WebExperience", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/applications/{applicationId}/experiences"}, + "DeleteApplication": {Verb: "Delete", Resource: "Application", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/applications/{applicationId}"}, + "DeleteAttachment": {Verb: "Delete", Resource: "Attachment", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/applications/{applicationId}/conversations/{conversationId}/attachments/{attachmentId}"}, + "DeleteChatControlsConfiguration": {Verb: "Delete", Resource: "ChatControlsConfiguration", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/applications/{applicationId}/chatcontrols"}, + "DeleteChatResponseConfiguration": {Verb: "Delete", Resource: "ChatResponseConfiguration", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/applications/{applicationId}/chatresponseconfigurations/{chatResponseConfigurationId}"}, + "DeleteConversation": {Verb: "Delete", Resource: "Conversation", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/applications/{applicationId}/conversations/{conversationId}"}, + "DeleteDataAccessor": {Verb: "Delete", Resource: "DataAccessor", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/applications/{applicationId}/dataaccessors/{dataAccessorId}"}, + "DeleteDataSource": {Verb: "Delete", Resource: "DataSource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/applications/{applicationId}/indices/{indexId}/datasources/{dataSourceId}"}, + "DeleteGroup": {Verb: "Delete", Resource: "Group", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/applications/{applicationId}/indices/{indexId}/groups/{groupName}"}, + "DeleteIndex": {Verb: "Delete", Resource: "Index", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/applications/{applicationId}/indices/{indexId}"}, + "DeletePlugin": {Verb: "Delete", Resource: "Plugin", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/applications/{applicationId}/plugins/{pluginId}"}, + "DeleteRetriever": {Verb: "Delete", Resource: "Retriever", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/applications/{applicationId}/retrievers/{retrieverId}"}, + "DeleteUser": {Verb: "Delete", Resource: "User", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/applications/{applicationId}/users/{userId}"}, + "DeleteWebExperience": {Verb: "Delete", Resource: "WebExperience", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/applications/{applicationId}/experiences/{webExperienceId}"}, + "GetApplication": {Verb: "Get", Resource: "Application", OutputListKey: "clientIdsForOIDC", OutputItemKey: "attachmentsConfiguration", Method: "GET", URI: "/applications/{applicationId}"}, + "GetChatControlsConfiguration": {Verb: "Get", Resource: "ChatControlsConfiguration", OutputListKey: "topicConfigurations", OutputItemKey: "blockedPhrases", Method: "GET", URI: "/applications/{applicationId}/chatcontrols"}, + "GetChatResponseConfiguration": {Verb: "Get", Resource: "ChatResponseConfiguration", OutputListKey: "", OutputItemKey: "inUseConfiguration", Method: "GET", URI: "/applications/{applicationId}/chatresponseconfigurations/{chatResponseConfigurationId}"}, + "GetDataAccessor": {Verb: "Get", Resource: "DataAccessor", OutputListKey: "actionConfigurations", OutputItemKey: "authenticationDetail", Method: "GET", URI: "/applications/{applicationId}/dataaccessors/{dataAccessorId}"}, + "GetDataSource": {Verb: "Get", Resource: "DataSource", OutputListKey: "", OutputItemKey: "documentEnrichmentConfiguration", Method: "GET", URI: "/applications/{applicationId}/indices/{indexId}/datasources/{dataSourceId}"}, + "GetDocumentContent": {Verb: "Get", Resource: "DocumentContent", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/applications/{applicationId}/index/{indexId}/documents/{documentId}/content"}, + "GetGroup": {Verb: "Get", Resource: "Group", OutputListKey: "statusHistory", OutputItemKey: "status", Method: "GET", URI: "/applications/{applicationId}/indices/{indexId}/groups/{groupName}"}, + "GetIndex": {Verb: "Get", Resource: "Index", OutputListKey: "documentAttributeConfigurations", OutputItemKey: "capacityConfiguration", Method: "GET", URI: "/applications/{applicationId}/indices/{indexId}"}, + "GetMedia": {Verb: "Get", Resource: "Media", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/applications/{applicationId}/conversations/{conversationId}/messages/{messageId}/media/{mediaId}"}, + "GetPlugin": {Verb: "Get", Resource: "Plugin", OutputListKey: "", OutputItemKey: "customPluginConfiguration", Method: "GET", URI: "/applications/{applicationId}/plugins/{pluginId}"}, + "GetPolicy": {Verb: "Get", Resource: "Policy", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/applications/{applicationId}/policy"}, + "GetRetriever": {Verb: "Get", Resource: "Retriever", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/applications/{applicationId}/retrievers/{retrieverId}"}, + "GetUser": {Verb: "Get", Resource: "User", OutputListKey: "userAliases", OutputItemKey: "", Method: "GET", URI: "/applications/{applicationId}/users/{userId}"}, + "GetWebExperience": {Verb: "Get", Resource: "WebExperience", OutputListKey: "origins", OutputItemKey: "browserExtensionConfiguration", Method: "GET", URI: "/applications/{applicationId}/experiences/{webExperienceId}"}, + "ListApplications": {Verb: "List", Resource: "Application", OutputListKey: "applications", OutputItemKey: "", Method: "GET", URI: "/applications"}, + "ListAttachments": {Verb: "List", Resource: "Attachment", OutputListKey: "attachments", OutputItemKey: "", Method: "GET", URI: "/applications/{applicationId}/attachments"}, + "ListChatResponseConfigurations": {Verb: "List", Resource: "ChatResponseConfiguration", OutputListKey: "chatResponseConfigurations", OutputItemKey: "", Method: "GET", URI: "/applications/{applicationId}/chatresponseconfigurations"}, + "ListConversations": {Verb: "List", Resource: "Conversation", OutputListKey: "conversations", OutputItemKey: "", Method: "GET", URI: "/applications/{applicationId}/conversations"}, + "ListDataAccessors": {Verb: "List", Resource: "DataAccessor", OutputListKey: "dataAccessors", OutputItemKey: "", Method: "GET", URI: "/applications/{applicationId}/dataaccessors"}, + "ListDataSourceSyncJobs": {Verb: "List", Resource: "DataSourceSyncJob", OutputListKey: "history", OutputItemKey: "", Method: "GET", URI: "/applications/{applicationId}/indices/{indexId}/datasources/{dataSourceId}/syncjobs"}, + "ListDataSources": {Verb: "List", Resource: "DataSource", OutputListKey: "dataSources", OutputItemKey: "", Method: "GET", URI: "/applications/{applicationId}/indices/{indexId}/datasources"}, + "ListDocuments": {Verb: "List", Resource: "Document", OutputListKey: "documentDetailList", OutputItemKey: "", Method: "GET", URI: "/applications/{applicationId}/index/{indexId}/documents"}, + "ListGroups": {Verb: "List", Resource: "Group", OutputListKey: "items", OutputItemKey: "", Method: "GET", URI: "/applications/{applicationId}/indices/{indexId}/groups"}, + "ListIndices": {Verb: "List", Resource: "Indice", OutputListKey: "indices", OutputItemKey: "", Method: "GET", URI: "/applications/{applicationId}/indices"}, + "ListMessages": {Verb: "List", Resource: "Message", OutputListKey: "messages", OutputItemKey: "", Method: "GET", URI: "/applications/{applicationId}/conversations/{conversationId}"}, + "ListPluginActions": {Verb: "List", Resource: "PluginAction", OutputListKey: "items", OutputItemKey: "", Method: "GET", URI: "/applications/{applicationId}/plugins/{pluginId}/actions"}, + "ListPluginTypeActions": {Verb: "List", Resource: "PluginTypeAction", OutputListKey: "items", OutputItemKey: "", Method: "GET", URI: "/pluginTypes/{pluginType}/actions"}, + "ListPluginTypeMetadata": {Verb: "List", Resource: "PluginTypeMetadata", OutputListKey: "items", OutputItemKey: "", Method: "GET", URI: "/pluginTypeMetadata"}, + "ListPlugins": {Verb: "List", Resource: "Plugin", OutputListKey: "plugins", OutputItemKey: "", Method: "GET", URI: "/applications/{applicationId}/plugins"}, + "ListRetrievers": {Verb: "List", Resource: "Retriever", OutputListKey: "retrievers", OutputItemKey: "", Method: "GET", URI: "/applications/{applicationId}/retrievers"}, + "ListSubscriptions": {Verb: "List", Resource: "Subscription", OutputListKey: "subscriptions", OutputItemKey: "", Method: "GET", URI: "/applications/{applicationId}/subscriptions"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "tags", OutputItemKey: "", Method: "GET", URI: "/v1/tags/{resourceARN}"}, + "ListWebExperiences": {Verb: "List", Resource: "WebExperience", OutputListKey: "webExperiences", OutputItemKey: "", Method: "GET", URI: "/applications/{applicationId}/experiences"}, + "PutFeedback": {Verb: "Update", Resource: "Feedback", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/applications/{applicationId}/conversations/{conversationId}/messages/{messageId}/feedback"}, + "PutGroup": {Verb: "Update", Resource: "Group", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/applications/{applicationId}/indices/{indexId}/groups"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v1/tags/{resourceARN}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v1/tags/{resourceARN}"}, + "UpdateApplication": {Verb: "Update", Resource: "Application", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/applications/{applicationId}"}, + "UpdateChatControlsConfiguration": {Verb: "Update", Resource: "ChatControlsConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/applications/{applicationId}/chatcontrols"}, + "UpdateChatResponseConfiguration": {Verb: "Update", Resource: "ChatResponseConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/applications/{applicationId}/chatresponseconfigurations/{chatResponseConfigurationId}"}, + "UpdateDataAccessor": {Verb: "Update", Resource: "DataAccessor", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/applications/{applicationId}/dataaccessors/{dataAccessorId}"}, + "UpdateDataSource": {Verb: "Update", Resource: "DataSource", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/applications/{applicationId}/indices/{indexId}/datasources/{dataSourceId}"}, + "UpdateIndex": {Verb: "Update", Resource: "Index", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/applications/{applicationId}/indices/{indexId}"}, + "UpdatePlugin": {Verb: "Update", Resource: "Plugin", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/applications/{applicationId}/plugins/{pluginId}"}, + "UpdateRetriever": {Verb: "Update", Resource: "Retriever", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/applications/{applicationId}/retrievers/{retrieverId}"}, + "UpdateSubscription": {Verb: "Update", Resource: "Subscription", OutputListKey: "", OutputItemKey: "currentSubscription", Method: "PUT", URI: "/applications/{applicationId}/subscriptions/{subscriptionId}"}, + "UpdateUser": {Verb: "Update", Resource: "User", OutputListKey: "userAliasesAdded", OutputItemKey: "", Method: "PUT", URI: "/applications/{applicationId}/users/{userId}"}, + "UpdateWebExperience": {Verb: "Update", Resource: "WebExperience", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/applications/{applicationId}/experiences/{webExperienceId}"}, + }) + crud.Register("ram", map[string]crud.OpMeta{ + "CreatePermission": {Verb: "Create", Resource: "Permission", OutputListKey: "", OutputItemKey: "permission", Method: "POST", URI: "/createpermission"}, + "CreatePermissionVersion": {Verb: "Create", Resource: "PermissionVersion", OutputListKey: "", OutputItemKey: "permission", Method: "POST", URI: "/createpermissionversion"}, + "CreateResourceShare": {Verb: "Create", Resource: "ResourceShare", OutputListKey: "", OutputItemKey: "resourceShare", Method: "POST", URI: "/createresourceshare"}, + "DeletePermission": {Verb: "Delete", Resource: "Permission", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/deletepermission"}, + "DeletePermissionVersion": {Verb: "Delete", Resource: "PermissionVersion", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/deletepermissionversion"}, + "DeleteResourceShare": {Verb: "Delete", Resource: "ResourceShare", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/deleteresourceshare"}, + "GetPermission": {Verb: "Get", Resource: "Permission", OutputListKey: "", OutputItemKey: "permission", Method: "POST", URI: "/getpermission"}, + "GetResourcePolicies": {Verb: "Get", Resource: "ResourcePolicy", OutputListKey: "policies", OutputItemKey: "", Method: "POST", URI: "/getresourcepolicies"}, + "GetResourceShareAssociations": {Verb: "Get", Resource: "ResourceShareAssociation", OutputListKey: "resourceShareAssociations", OutputItemKey: "", Method: "POST", URI: "/getresourceshareassociations"}, + "GetResourceShareInvitations": {Verb: "Get", Resource: "ResourceShareInvitation", OutputListKey: "resourceShareInvitations", OutputItemKey: "", Method: "POST", URI: "/getresourceshareinvitations"}, + "GetResourceShares": {Verb: "Get", Resource: "ResourceShare", OutputListKey: "resourceShares", OutputItemKey: "", Method: "POST", URI: "/getresourceshares"}, + "ListPendingInvitationResources": {Verb: "List", Resource: "PendingInvitationResource", OutputListKey: "resources", OutputItemKey: "", Method: "POST", URI: "/listpendinginvitationresources"}, + "ListPermissionAssociations": {Verb: "List", Resource: "PermissionAssociation", OutputListKey: "permissions", OutputItemKey: "", Method: "POST", URI: "/listpermissionassociations"}, + "ListPermissionVersions": {Verb: "List", Resource: "PermissionVersion", OutputListKey: "permissions", OutputItemKey: "", Method: "POST", URI: "/listpermissionversions"}, + "ListPermissions": {Verb: "List", Resource: "Permission", OutputListKey: "permissions", OutputItemKey: "", Method: "POST", URI: "/listpermissions"}, + "ListPrincipals": {Verb: "List", Resource: "Principal", OutputListKey: "principals", OutputItemKey: "", Method: "POST", URI: "/listprincipals"}, + "ListReplacePermissionAssociationsWork": {Verb: "List", Resource: "ReplacePermissionAssociationsWork", OutputListKey: "replacePermissionAssociationsWorks", OutputItemKey: "", Method: "POST", URI: "/listreplacepermissionassociationswork"}, + "ListResourceSharePermissions": {Verb: "List", Resource: "ResourceSharePermission", OutputListKey: "permissions", OutputItemKey: "", Method: "POST", URI: "/listresourcesharepermissions"}, + "ListResourceTypes": {Verb: "List", Resource: "ResourceType", OutputListKey: "resourceTypes", OutputItemKey: "", Method: "POST", URI: "/listresourcetypes"}, + "ListResources": {Verb: "List", Resource: "Resource", OutputListKey: "resources", OutputItemKey: "", Method: "POST", URI: "/listresources"}, + "ListSourceAssociations": {Verb: "List", Resource: "SourceAssociation", OutputListKey: "sourceAssociations", OutputItemKey: "", Method: "POST", URI: "/listsourceassociations"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/tagresource"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/untagresource"}, + "UpdateResourceShare": {Verb: "Update", Resource: "ResourceShare", OutputListKey: "", OutputItemKey: "resourceShare", Method: "POST", URI: "/updateresourceshare"}, + }) crud.Register("rekognition", map[string]crud.OpMeta{ "CreateCollection": {Verb: "Create", Resource: "Collection", OutputListKey: "", OutputItemKey: ""}, "CreateDataset": {Verb: "Create", Resource: "Dataset", OutputListKey: "", OutputItemKey: ""}, @@ -1847,15 +4137,33 @@ func init() { "UpdateDatasetEntries": {Verb: "Update", Resource: "DatasetEntry", OutputListKey: "", OutputItemKey: ""}, "UpdateStreamProcessor": {Verb: "Update", Resource: "StreamProcessor", OutputListKey: "", OutputItemKey: ""}, }) + crud.Register("resourcegroups", map[string]crud.OpMeta{ + "CreateGroup": {Verb: "Create", Resource: "Group", OutputListKey: "", OutputItemKey: "Group", Method: "POST", URI: "/groups"}, + "DeleteGroup": {Verb: "Delete", Resource: "Group", OutputListKey: "", OutputItemKey: "Group", Method: "POST", URI: "/delete-group"}, + "GetAccountSettings": {Verb: "Get", Resource: "AccountSetting", OutputListKey: "", OutputItemKey: "AccountSettings", Method: "POST", URI: "/get-account-settings"}, + "GetGroup": {Verb: "Get", Resource: "Group", OutputListKey: "", OutputItemKey: "Group", Method: "POST", URI: "/get-group"}, + "GetGroupConfiguration": {Verb: "Get", Resource: "GroupConfiguration", OutputListKey: "", OutputItemKey: "GroupConfiguration", Method: "POST", URI: "/get-group-configuration"}, + "GetGroupQuery": {Verb: "Get", Resource: "GroupQuery", OutputListKey: "", OutputItemKey: "GroupQuery", Method: "POST", URI: "/get-group-query"}, + "GetTagSyncTask": {Verb: "Get", Resource: "TagSyncTask", OutputListKey: "", OutputItemKey: "ResourceQuery", Method: "POST", URI: "/get-tag-sync-task"}, + "GetTags": {Verb: "Get", Resource: "Tag", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/resources/{Arn}/tags"}, + "ListGroupResources": {Verb: "List", Resource: "GroupResource", OutputListKey: "QueryErrors", OutputItemKey: "", Method: "POST", URI: "/list-group-resources"}, + "ListGroupingStatuses": {Verb: "List", Resource: "GroupingStatuse", OutputListKey: "GroupingStatuses", OutputItemKey: "", Method: "POST", URI: "/list-grouping-statuses"}, + "ListGroups": {Verb: "List", Resource: "Group", OutputListKey: "GroupIdentifiers", OutputItemKey: "", Method: "POST", URI: "/groups-list"}, + "ListTagSyncTasks": {Verb: "List", Resource: "TagSyncTask", OutputListKey: "TagSyncTasks", OutputItemKey: "", Method: "POST", URI: "/list-tag-sync-tasks"}, + "PutGroupConfiguration": {Verb: "Update", Resource: "GroupConfiguration", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/put-group-configuration"}, + "UpdateAccountSettings": {Verb: "Update", Resource: "AccountSetting", OutputListKey: "", OutputItemKey: "AccountSettings", Method: "POST", URI: "/update-account-settings"}, + "UpdateGroup": {Verb: "Update", Resource: "Group", OutputListKey: "", OutputItemKey: "Group", Method: "POST", URI: "/update-group"}, + "UpdateGroupQuery": {Verb: "Update", Resource: "GroupQuery", OutputListKey: "", OutputItemKey: "GroupQuery", Method: "POST", URI: "/update-group-query"}, + }) crud.Register("resourcegroupstaggingapi", map[string]crud.OpMeta{ - "DescribeReportCreation": {Verb: "Get", Resource: "ReportCreation", OutputListKey: "", OutputItemKey: ""}, - "GetComplianceSummary": {Verb: "Get", Resource: "ComplianceSummary", OutputListKey: "SummaryList", OutputItemKey: ""}, - "GetResources": {Verb: "Get", Resource: "Resource", OutputListKey: "ResourceTagMappingList", OutputItemKey: ""}, - "GetTagKeys": {Verb: "Get", Resource: "TagKey", OutputListKey: "TagKeys", OutputItemKey: ""}, - "GetTagValues": {Verb: "Get", Resource: "TagValue", OutputListKey: "TagValues", OutputItemKey: ""}, - "ListRequiredTags": {Verb: "List", Resource: "RequiredTag", OutputListKey: "RequiredTags", OutputItemKey: ""}, - "TagResources": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: ""}, - "UntagResources": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: ""}, + "DescribeReportCreation": {Verb: "Get", Resource: "ReportCreation", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/DescribeReportCreation"}, + "GetComplianceSummary": {Verb: "Get", Resource: "ComplianceSummary", OutputListKey: "SummaryList", OutputItemKey: "", Method: "POST", URI: "/GetComplianceSummary"}, + "GetResources": {Verb: "Get", Resource: "Resource", OutputListKey: "ResourceTagMappingList", OutputItemKey: "", Method: "POST", URI: "/GetResources"}, + "GetTagKeys": {Verb: "Get", Resource: "TagKey", OutputListKey: "TagKeys", OutputItemKey: "", Method: "POST", URI: "/GetTagKeys"}, + "GetTagValues": {Verb: "Get", Resource: "TagValue", OutputListKey: "TagValues", OutputItemKey: "", Method: "POST", URI: "/GetTagValues"}, + "ListRequiredTags": {Verb: "List", Resource: "RequiredTag", OutputListKey: "RequiredTags", OutputItemKey: "", Method: "POST", URI: "/ListRequiredTags"}, + "TagResources": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/TagResources"}, + "UntagResources": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/UntagResources"}, }) crud.Register("route53resolver", map[string]crud.OpMeta{ "CreateFirewallDomainList": {Verb: "Create", Resource: "FirewallDomainList", OutputListKey: "", OutputItemKey: "FirewallDomainList"}, @@ -2256,6 +4564,43 @@ func init() { "UpdateWorkforce": {Verb: "Update", Resource: "Workforce", OutputListKey: "", OutputItemKey: "Workforce"}, "UpdateWorkteam": {Verb: "Update", Resource: "Workteam", OutputListKey: "", OutputItemKey: "Workteam"}, }) + crud.Register("sagemakera2iruntime", map[string]crud.OpMeta{ + "DeleteHumanLoop": {Verb: "Delete", Resource: "HumanLoop", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/human-loops/{HumanLoopName}"}, + "DescribeHumanLoop": {Verb: "Get", Resource: "HumanLoop", OutputListKey: "", OutputItemKey: "HumanLoopOutput", Method: "GET", URI: "/human-loops/{HumanLoopName}"}, + "ListHumanLoops": {Verb: "List", Resource: "HumanLoop", OutputListKey: "HumanLoopSummaries", OutputItemKey: "", Method: "GET", URI: "/human-loops"}, + }) + crud.Register("sagemakeredge", map[string]crud.OpMeta{ + "GetDeployments": {Verb: "Get", Resource: "Deployment", OutputListKey: "Deployments", OutputItemKey: "", Method: "POST", URI: "/GetDeployments"}, + "GetDeviceRegistration": {Verb: "Get", Resource: "DeviceRegistration", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/GetDeviceRegistration"}, + }) + crud.Register("sagemakerfeaturestoreruntime", map[string]crud.OpMeta{ + "BatchGetRecord": {Verb: "List", Resource: "Record", OutputListKey: "Errors", OutputItemKey: "", Method: "POST", URI: "/BatchGetRecord"}, + "DeleteRecord": {Verb: "Delete", Resource: "Record", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/FeatureGroup/{FeatureGroupName}"}, + "GetRecord": {Verb: "Get", Resource: "Record", OutputListKey: "Record", OutputItemKey: "", Method: "GET", URI: "/FeatureGroup/{FeatureGroupName}"}, + "ListRecords": {Verb: "List", Resource: "Record", OutputListKey: "RecordIdentifiers", OutputItemKey: "", Method: "POST", URI: "/FeatureGroup/{FeatureGroupName}/ListRecords"}, + "PutRecord": {Verb: "Update", Resource: "Record", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/FeatureGroup/{FeatureGroupName}"}, + "UpdateRecord": {Verb: "Update", Resource: "Record", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/FeatureGroup/{FeatureGroupName}/Record"}, + }) + crud.Register("sagemakergeospatial", map[string]crud.OpMeta{ + "DeleteEarthObservationJob": {Verb: "Delete", Resource: "EarthObservationJob", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/earth-observation-jobs/{Arn}"}, + "DeleteVectorEnrichmentJob": {Verb: "Delete", Resource: "VectorEnrichmentJob", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/vector-enrichment-jobs/{Arn}"}, + "GetEarthObservationJob": {Verb: "Get", Resource: "EarthObservationJob", OutputListKey: "OutputBands", OutputItemKey: "ErrorDetails", Method: "GET", URI: "/earth-observation-jobs/{Arn}"}, + "GetRasterDataCollection": {Verb: "Get", Resource: "RasterDataCollection", OutputListKey: "ImageSourceBands", OutputItemKey: "", Method: "GET", URI: "/raster-data-collection/{Arn}"}, + "GetTile": {Verb: "Get", Resource: "Tile", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/tile/{z}/{x}/{y}"}, + "GetVectorEnrichmentJob": {Verb: "Get", Resource: "VectorEnrichmentJob", OutputListKey: "", OutputItemKey: "ErrorDetails", Method: "GET", URI: "/vector-enrichment-jobs/{Arn}"}, + "ListEarthObservationJobs": {Verb: "List", Resource: "EarthObservationJob", OutputListKey: "EarthObservationJobSummaries", OutputItemKey: "", Method: "POST", URI: "/list-earth-observation-jobs"}, + "ListRasterDataCollections": {Verb: "List", Resource: "RasterDataCollection", OutputListKey: "RasterDataCollectionSummaries", OutputItemKey: "", Method: "GET", URI: "/raster-data-collections"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/tags/{ResourceArn}"}, + "ListVectorEnrichmentJobs": {Verb: "List", Resource: "VectorEnrichmentJob", OutputListKey: "VectorEnrichmentJobSummaries", OutputItemKey: "", Method: "POST", URI: "/list-vector-enrichment-jobs"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/tags/{ResourceArn}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/tags/{ResourceArn}"}, + }) + crud.Register("sagemakerjobruntime", map[string]crud.OpMeta{ + "UpdateReward": {Verb: "Update", Resource: "Reward", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/update-reward"}, + }) + crud.Register("sagemakermetrics", map[string]crud.OpMeta{ + "BatchGetMetrics": {Verb: "List", Resource: "Metric", OutputListKey: "MetricQueryResults", OutputItemKey: "", Method: "POST", URI: "/BatchGetMetrics"}, + }) crud.Register("secretsmanager", map[string]crud.OpMeta{ "BatchGetSecretValue": {Verb: "List", Resource: "SecretValue", OutputListKey: "Errors", OutputItemKey: ""}, "CreateSecret": {Verb: "Create", Resource: "Secret", OutputListKey: "ReplicationStatus", OutputItemKey: ""}, @@ -2304,6 +4649,113 @@ func init() { "UpdateService": {Verb: "Update", Resource: "Service", OutputListKey: "", OutputItemKey: ""}, "UpdateServiceAttributes": {Verb: "Update", Resource: "ServiceAttribute", OutputListKey: "", OutputItemKey: ""}, }) + crud.Register("sesv2", map[string]crud.OpMeta{ + "BatchGetMetricData": {Verb: "List", Resource: "MetricData", OutputListKey: "Errors", OutputItemKey: "", Method: "POST", URI: "/v2/email/metrics/batch"}, + "CreateConfigurationSet": {Verb: "Create", Resource: "ConfigurationSet", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v2/email/configuration-sets"}, + "CreateConfigurationSetEventDestination": {Verb: "Create", Resource: "ConfigurationSetEventDestination", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v2/email/configuration-sets/{ConfigurationSetName}/event-destinations"}, + "CreateContact": {Verb: "Create", Resource: "Contact", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v2/email/contact-lists/{ContactListName}/contacts"}, + "CreateContactList": {Verb: "Create", Resource: "ContactList", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v2/email/contact-lists"}, + "CreateCustomVerificationEmailTemplate": {Verb: "Create", Resource: "CustomVerificationEmailTemplate", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v2/email/custom-verification-email-templates"}, + "CreateDedicatedIpPool": {Verb: "Create", Resource: "DedicatedIpPool", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v2/email/dedicated-ip-pools"}, + "CreateDeliverabilityTestReport": {Verb: "Create", Resource: "DeliverabilityTestReport", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v2/email/deliverability-dashboard/test"}, + "CreateEmailIdentity": {Verb: "Create", Resource: "EmailIdentity", OutputListKey: "", OutputItemKey: "DkimAttributes", Method: "POST", URI: "/v2/email/identities"}, + "CreateEmailIdentityPolicy": {Verb: "Create", Resource: "EmailIdentityPolicy", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v2/email/identities/{EmailIdentity}/policies/{PolicyName}"}, + "CreateEmailTemplate": {Verb: "Create", Resource: "EmailTemplate", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v2/email/templates"}, + "CreateExportJob": {Verb: "Create", Resource: "ExportJob", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v2/email/export-jobs"}, + "CreateImportJob": {Verb: "Create", Resource: "ImportJob", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v2/email/import-jobs"}, + "CreateMultiRegionEndpoint": {Verb: "Create", Resource: "MultiRegionEndpoint", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v2/email/multi-region-endpoints"}, + "CreateTenant": {Verb: "Create", Resource: "Tenant", OutputListKey: "Tags", OutputItemKey: "", Method: "POST", URI: "/v2/email/tenants"}, + "CreateTenantResourceAssociation": {Verb: "Create", Resource: "TenantResourceAssociation", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v2/email/tenants/resources"}, + "DeleteConfigurationSet": {Verb: "Delete", Resource: "ConfigurationSet", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/email/configuration-sets/{ConfigurationSetName}"}, + "DeleteConfigurationSetEventDestination": {Verb: "Delete", Resource: "ConfigurationSetEventDestination", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/email/configuration-sets/{ConfigurationSetName}/event-destinations/{EventDestinationName}"}, + "DeleteContact": {Verb: "Delete", Resource: "Contact", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/email/contact-lists/{ContactListName}/contacts/{EmailAddress}"}, + "DeleteContactList": {Verb: "Delete", Resource: "ContactList", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/email/contact-lists/{ContactListName}"}, + "DeleteCustomVerificationEmailTemplate": {Verb: "Delete", Resource: "CustomVerificationEmailTemplate", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/email/custom-verification-email-templates/{TemplateName}"}, + "DeleteDedicatedIpPool": {Verb: "Delete", Resource: "DedicatedIpPool", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/email/dedicated-ip-pools/{PoolName}"}, + "DeleteEmailIdentity": {Verb: "Delete", Resource: "EmailIdentity", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/email/identities/{EmailIdentity}"}, + "DeleteEmailIdentityPolicy": {Verb: "Delete", Resource: "EmailIdentityPolicy", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/email/identities/{EmailIdentity}/policies/{PolicyName}"}, + "DeleteEmailTemplate": {Verb: "Delete", Resource: "EmailTemplate", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/email/templates/{TemplateName}"}, + "DeleteMultiRegionEndpoint": {Verb: "Delete", Resource: "MultiRegionEndpoint", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/email/multi-region-endpoints/{EndpointName}"}, + "DeleteSuppressedDestination": {Verb: "Delete", Resource: "SuppressedDestination", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/email/suppression/addresses/{EmailAddress}"}, + "DeleteTenant": {Verb: "Delete", Resource: "Tenant", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v2/email/tenants/delete"}, + "DeleteTenantResourceAssociation": {Verb: "Delete", Resource: "TenantResourceAssociation", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v2/email/tenants/resources/delete"}, + "GetAccount": {Verb: "Get", Resource: "Account", OutputListKey: "", OutputItemKey: "Details", Method: "GET", URI: "/v2/email/account"}, + "GetBlacklistReports": {Verb: "Get", Resource: "BlacklistReport", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v2/email/deliverability-dashboard/blacklist-report"}, + "GetConfigurationSet": {Verb: "Get", Resource: "ConfigurationSet", OutputListKey: "Tags", OutputItemKey: "ArchivingOptions", Method: "GET", URI: "/v2/email/configuration-sets/{ConfigurationSetName}"}, + "GetConfigurationSetEventDestinations": {Verb: "Get", Resource: "ConfigurationSetEventDestination", OutputListKey: "EventDestinations", OutputItemKey: "", Method: "GET", URI: "/v2/email/configuration-sets/{ConfigurationSetName}/event-destinations"}, + "GetContact": {Verb: "Get", Resource: "Contact", OutputListKey: "TopicDefaultPreferences", OutputItemKey: "", Method: "GET", URI: "/v2/email/contact-lists/{ContactListName}/contacts/{EmailAddress}"}, + "GetContactList": {Verb: "Get", Resource: "ContactList", OutputListKey: "Tags", OutputItemKey: "", Method: "GET", URI: "/v2/email/contact-lists/{ContactListName}"}, + "GetCustomVerificationEmailTemplate": {Verb: "Get", Resource: "CustomVerificationEmailTemplate", OutputListKey: "Tags", OutputItemKey: "", Method: "GET", URI: "/v2/email/custom-verification-email-templates/{TemplateName}"}, + "GetDedicatedIp": {Verb: "Get", Resource: "DedicatedIp", OutputListKey: "", OutputItemKey: "DedicatedIp", Method: "GET", URI: "/v2/email/dedicated-ips/{Ip}"}, + "GetDedicatedIpPool": {Verb: "Get", Resource: "DedicatedIpPool", OutputListKey: "", OutputItemKey: "DedicatedIpPool", Method: "GET", URI: "/v2/email/dedicated-ip-pools/{PoolName}"}, + "GetDedicatedIps": {Verb: "Get", Resource: "DedicatedIp", OutputListKey: "DedicatedIps", OutputItemKey: "", Method: "GET", URI: "/v2/email/dedicated-ips"}, + "GetDeliverabilityDashboardOptions": {Verb: "Get", Resource: "DeliverabilityDashboardOption", OutputListKey: "ActiveSubscribedDomains", OutputItemKey: "", Method: "GET", URI: "/v2/email/deliverability-dashboard"}, + "GetDeliverabilityTestReport": {Verb: "Get", Resource: "DeliverabilityTestReport", OutputListKey: "IspPlacements", OutputItemKey: "DeliverabilityTestReport", Method: "GET", URI: "/v2/email/deliverability-dashboard/test-reports/{ReportId}"}, + "GetDomainDeliverabilityCampaign": {Verb: "Get", Resource: "DomainDeliverabilityCampaign", OutputListKey: "", OutputItemKey: "DomainDeliverabilityCampaign", Method: "GET", URI: "/v2/email/deliverability-dashboard/campaigns/{CampaignId}"}, + "GetDomainStatisticsReport": {Verb: "Get", Resource: "DomainStatisticsReport", OutputListKey: "DailyVolumes", OutputItemKey: "OverallVolume", Method: "GET", URI: "/v2/email/deliverability-dashboard/statistics-report/{Domain}"}, + "GetEmailAddressInsights": {Verb: "Get", Resource: "EmailAddressInsight", OutputListKey: "", OutputItemKey: "MailboxValidation", Method: "POST", URI: "/v2/email/email-address-insights"}, + "GetEmailIdentity": {Verb: "Get", Resource: "EmailIdentity", OutputListKey: "Tags", OutputItemKey: "DkimAttributes", Method: "GET", URI: "/v2/email/identities/{EmailIdentity}"}, + "GetEmailIdentityPolicies": {Verb: "Get", Resource: "EmailIdentityPolicy", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v2/email/identities/{EmailIdentity}/policies"}, + "GetEmailTemplate": {Verb: "Get", Resource: "EmailTemplate", OutputListKey: "Tags", OutputItemKey: "TemplateContent", Method: "GET", URI: "/v2/email/templates/{TemplateName}"}, + "GetExportJob": {Verb: "Get", Resource: "ExportJob", OutputListKey: "", OutputItemKey: "ExportDataSource", Method: "GET", URI: "/v2/email/export-jobs/{JobId}"}, + "GetImportJob": {Verb: "Get", Resource: "ImportJob", OutputListKey: "", OutputItemKey: "FailureInfo", Method: "GET", URI: "/v2/email/import-jobs/{JobId}"}, + "GetMessageInsights": {Verb: "Get", Resource: "MessageInsight", OutputListKey: "EmailTags", OutputItemKey: "", Method: "GET", URI: "/v2/email/insights/{MessageId}"}, + "GetMultiRegionEndpoint": {Verb: "Get", Resource: "MultiRegionEndpoint", OutputListKey: "Routes", OutputItemKey: "", Method: "GET", URI: "/v2/email/multi-region-endpoints/{EndpointName}"}, + "GetReputationEntity": {Verb: "Get", Resource: "ReputationEntity", OutputListKey: "", OutputItemKey: "ReputationEntity", Method: "GET", URI: "/v2/email/reputation/entities/{ReputationEntityType}/{ReputationEntityReference}"}, + "GetSuppressedDestination": {Verb: "Get", Resource: "SuppressedDestination", OutputListKey: "", OutputItemKey: "SuppressedDestination", Method: "GET", URI: "/v2/email/suppression/addresses/{EmailAddress}"}, + "GetTenant": {Verb: "Get", Resource: "Tenant", OutputListKey: "", OutputItemKey: "Tenant", Method: "POST", URI: "/v2/email/tenants/get"}, + "ListConfigurationSets": {Verb: "List", Resource: "ConfigurationSet", OutputListKey: "ConfigurationSets", OutputItemKey: "", Method: "GET", URI: "/v2/email/configuration-sets"}, + "ListContactLists": {Verb: "List", Resource: "ContactList", OutputListKey: "ContactLists", OutputItemKey: "", Method: "GET", URI: "/v2/email/contact-lists"}, + "ListContacts": {Verb: "List", Resource: "Contact", OutputListKey: "Contacts", OutputItemKey: "", Method: "POST", URI: "/v2/email/contact-lists/{ContactListName}/contacts/list"}, + "ListCustomVerificationEmailTemplates": {Verb: "List", Resource: "CustomVerificationEmailTemplate", OutputListKey: "CustomVerificationEmailTemplates", OutputItemKey: "", Method: "GET", URI: "/v2/email/custom-verification-email-templates"}, + "ListDedicatedIpPools": {Verb: "List", Resource: "DedicatedIpPool", OutputListKey: "DedicatedIpPools", OutputItemKey: "", Method: "GET", URI: "/v2/email/dedicated-ip-pools"}, + "ListDeliverabilityTestReports": {Verb: "List", Resource: "DeliverabilityTestReport", OutputListKey: "DeliverabilityTestReports", OutputItemKey: "", Method: "GET", URI: "/v2/email/deliverability-dashboard/test-reports"}, + "ListDomainDeliverabilityCampaigns": {Verb: "List", Resource: "DomainDeliverabilityCampaign", OutputListKey: "DomainDeliverabilityCampaigns", OutputItemKey: "", Method: "GET", URI: "/v2/email/deliverability-dashboard/domains/{SubscribedDomain}/campaigns"}, + "ListEmailIdentities": {Verb: "List", Resource: "EmailIdentity", OutputListKey: "EmailIdentities", OutputItemKey: "", Method: "GET", URI: "/v2/email/identities"}, + "ListEmailTemplates": {Verb: "List", Resource: "EmailTemplate", OutputListKey: "TemplatesMetadata", OutputItemKey: "", Method: "GET", URI: "/v2/email/templates"}, + "ListExportJobs": {Verb: "List", Resource: "ExportJob", OutputListKey: "ExportJobs", OutputItemKey: "", Method: "POST", URI: "/v2/email/list-export-jobs"}, + "ListImportJobs": {Verb: "List", Resource: "ImportJob", OutputListKey: "ImportJobs", OutputItemKey: "", Method: "POST", URI: "/v2/email/import-jobs/list"}, + "ListMultiRegionEndpoints": {Verb: "List", Resource: "MultiRegionEndpoint", OutputListKey: "MultiRegionEndpoints", OutputItemKey: "", Method: "GET", URI: "/v2/email/multi-region-endpoints"}, + "ListRecommendations": {Verb: "List", Resource: "Recommendation", OutputListKey: "Recommendations", OutputItemKey: "", Method: "POST", URI: "/v2/email/vdm/recommendations"}, + "ListReputationEntities": {Verb: "List", Resource: "ReputationEntity", OutputListKey: "ReputationEntities", OutputItemKey: "", Method: "POST", URI: "/v2/email/reputation/entities"}, + "ListResourceTenants": {Verb: "List", Resource: "ResourceTenant", OutputListKey: "ResourceTenants", OutputItemKey: "", Method: "POST", URI: "/v2/email/resources/tenants/list"}, + "ListSuppressedDestinations": {Verb: "List", Resource: "SuppressedDestination", OutputListKey: "SuppressedDestinationSummaries", OutputItemKey: "", Method: "GET", URI: "/v2/email/suppression/addresses"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "Tags", OutputItemKey: "", Method: "GET", URI: "/v2/email/tags"}, + "ListTenantResources": {Verb: "List", Resource: "TenantResource", OutputListKey: "TenantResources", OutputItemKey: "", Method: "POST", URI: "/v2/email/tenants/resources/list"}, + "ListTenants": {Verb: "List", Resource: "Tenant", OutputListKey: "Tenants", OutputItemKey: "", Method: "POST", URI: "/v2/email/tenants/list"}, + "PutAccountDedicatedIpWarmupAttributes": {Verb: "Update", Resource: "AccountDedicatedIpWarmupAttribute", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/account/dedicated-ips/warmup"}, + "PutAccountDetails": {Verb: "Update", Resource: "AccountDetail", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v2/email/account/details"}, + "PutAccountSendingAttributes": {Verb: "Update", Resource: "AccountSendingAttribute", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/account/sending"}, + "PutAccountSuppressionAttributes": {Verb: "Update", Resource: "AccountSuppressionAttribute", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/account/suppression"}, + "PutAccountVdmAttributes": {Verb: "Update", Resource: "AccountVdmAttribute", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/account/vdm"}, + "PutConfigurationSetArchivingOptions": {Verb: "Update", Resource: "ConfigurationSetArchivingOption", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/configuration-sets/{ConfigurationSetName}/archiving-options"}, + "PutConfigurationSetDeliveryOptions": {Verb: "Update", Resource: "ConfigurationSetDeliveryOption", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/configuration-sets/{ConfigurationSetName}/delivery-options"}, + "PutConfigurationSetReputationOptions": {Verb: "Update", Resource: "ConfigurationSetReputationOption", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/configuration-sets/{ConfigurationSetName}/reputation-options"}, + "PutConfigurationSetSendingOptions": {Verb: "Update", Resource: "ConfigurationSetSendingOption", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/configuration-sets/{ConfigurationSetName}/sending"}, + "PutConfigurationSetSuppressionOptions": {Verb: "Update", Resource: "ConfigurationSetSuppressionOption", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/configuration-sets/{ConfigurationSetName}/suppression-options"}, + "PutConfigurationSetTrackingOptions": {Verb: "Update", Resource: "ConfigurationSetTrackingOption", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/configuration-sets/{ConfigurationSetName}/tracking-options"}, + "PutConfigurationSetVdmOptions": {Verb: "Update", Resource: "ConfigurationSetVdmOption", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/configuration-sets/{ConfigurationSetName}/vdm-options"}, + "PutDedicatedIpInPool": {Verb: "Update", Resource: "DedicatedIpInPool", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/dedicated-ips/{Ip}/pool"}, + "PutDedicatedIpPoolScalingAttributes": {Verb: "Update", Resource: "DedicatedIpPoolScalingAttribute", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/dedicated-ip-pools/{PoolName}/scaling"}, + "PutDedicatedIpWarmupAttributes": {Verb: "Update", Resource: "DedicatedIpWarmupAttribute", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/dedicated-ips/{Ip}/warmup"}, + "PutDeliverabilityDashboardOption": {Verb: "Update", Resource: "DeliverabilityDashboardOption", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/deliverability-dashboard"}, + "PutEmailIdentityConfigurationSetAttributes": {Verb: "Update", Resource: "EmailIdentityConfigurationSetAttribute", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/identities/{EmailIdentity}/configuration-set"}, + "PutEmailIdentityDkimAttributes": {Verb: "Update", Resource: "EmailIdentityDkimAttribute", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/identities/{EmailIdentity}/dkim"}, + "PutEmailIdentityDkimSigningAttributes": {Verb: "Update", Resource: "EmailIdentityDkimSigningAttribute", OutputListKey: "DkimTokens", OutputItemKey: "", Method: "PUT", URI: "/v2/email/identities/{EmailIdentity}/dkim/signing"}, + "PutEmailIdentityFeedbackAttributes": {Verb: "Update", Resource: "EmailIdentityFeedbackAttribute", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/identities/{EmailIdentity}/feedback"}, + "PutEmailIdentityMailFromAttributes": {Verb: "Update", Resource: "EmailIdentityMailFromAttribute", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/identities/{EmailIdentity}/mail-from"}, + "PutSuppressedDestination": {Verb: "Update", Resource: "SuppressedDestination", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/suppression/addresses"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v2/email/tags"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v2/email/tags"}, + "UpdateConfigurationSetEventDestination": {Verb: "Update", Resource: "ConfigurationSetEventDestination", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/configuration-sets/{ConfigurationSetName}/event-destinations/{EventDestinationName}"}, + "UpdateContact": {Verb: "Update", Resource: "Contact", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/contact-lists/{ContactListName}/contacts/{EmailAddress}"}, + "UpdateContactList": {Verb: "Update", Resource: "ContactList", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/contact-lists/{ContactListName}"}, + "UpdateCustomVerificationEmailTemplate": {Verb: "Update", Resource: "CustomVerificationEmailTemplate", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/custom-verification-email-templates/{TemplateName}"}, + "UpdateEmailIdentityPolicy": {Verb: "Update", Resource: "EmailIdentityPolicy", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/identities/{EmailIdentity}/policies/{PolicyName}"}, + "UpdateEmailTemplate": {Verb: "Update", Resource: "EmailTemplate", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/templates/{TemplateName}"}, + "UpdateReputationEntityCustomerManagedStatus": {Verb: "Update", Resource: "ReputationEntityCustomerManagedStatu", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/reputation/entities/{ReputationEntityType}/{ReputationEntityReference}/customer-managed-status"}, + "UpdateReputationEntityPolicy": {Verb: "Update", Resource: "ReputationEntityPolicy", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v2/email/reputation/entities/{ReputationEntityType}/{ReputationEntityReference}/policy"}, + }) crud.Register("sfn", map[string]crud.OpMeta{ "CreateActivity": {Verb: "Create", Resource: "Activity", OutputListKey: "", OutputItemKey: ""}, "CreateStateMachine": {Verb: "Create", Resource: "StateMachine", OutputListKey: "", OutputItemKey: ""}, @@ -2649,45 +5101,48 @@ func init() { "UpdateTable": {Verb: "Update", Resource: "Table", OutputListKey: "", OutputItemKey: "Table"}, }) crud.Register("transcribe", map[string]crud.OpMeta{ - "CreateCallAnalyticsCategory": {Verb: "Create", Resource: "CallAnalyticsCategory", OutputListKey: "", OutputItemKey: "CategoryProperties"}, - "CreateLanguageModel": {Verb: "Create", Resource: "LanguageModel", OutputListKey: "", OutputItemKey: "InputDataConfig"}, - "CreateMedicalVocabulary": {Verb: "Create", Resource: "MedicalVocabulary", OutputListKey: "", OutputItemKey: ""}, - "CreateVocabulary": {Verb: "Create", Resource: "Vocabulary", OutputListKey: "", OutputItemKey: ""}, - "CreateVocabularyFilter": {Verb: "Create", Resource: "VocabularyFilter", OutputListKey: "", OutputItemKey: ""}, - "DeleteCallAnalyticsCategory": {Verb: "Delete", Resource: "CallAnalyticsCategory", OutputListKey: "", OutputItemKey: ""}, - "DeleteCallAnalyticsJob": {Verb: "Delete", Resource: "CallAnalyticsJob", OutputListKey: "", OutputItemKey: ""}, - "DeleteLanguageModel": {Verb: "Delete", Resource: "LanguageModel", OutputListKey: "", OutputItemKey: ""}, - "DeleteMedicalScribeJob": {Verb: "Delete", Resource: "MedicalScribeJob", OutputListKey: "", OutputItemKey: ""}, - "DeleteMedicalTranscriptionJob": {Verb: "Delete", Resource: "MedicalTranscriptionJob", OutputListKey: "", OutputItemKey: ""}, - "DeleteMedicalVocabulary": {Verb: "Delete", Resource: "MedicalVocabulary", OutputListKey: "", OutputItemKey: ""}, - "DeleteTranscriptionJob": {Verb: "Delete", Resource: "TranscriptionJob", OutputListKey: "", OutputItemKey: ""}, - "DeleteVocabulary": {Verb: "Delete", Resource: "Vocabulary", OutputListKey: "", OutputItemKey: ""}, - "DeleteVocabularyFilter": {Verb: "Delete", Resource: "VocabularyFilter", OutputListKey: "", OutputItemKey: ""}, - "DescribeLanguageModel": {Verb: "Get", Resource: "LanguageModel", OutputListKey: "", OutputItemKey: "LanguageModel"}, - "GetCallAnalyticsCategory": {Verb: "Get", Resource: "CallAnalyticsCategory", OutputListKey: "", OutputItemKey: "CategoryProperties"}, - "GetCallAnalyticsJob": {Verb: "Get", Resource: "CallAnalyticsJob", OutputListKey: "", OutputItemKey: "CallAnalyticsJob"}, - "GetMedicalScribeJob": {Verb: "Get", Resource: "MedicalScribeJob", OutputListKey: "", OutputItemKey: "MedicalScribeJob"}, - "GetMedicalTranscriptionJob": {Verb: "Get", Resource: "MedicalTranscriptionJob", OutputListKey: "", OutputItemKey: "MedicalTranscriptionJob"}, - "GetMedicalVocabulary": {Verb: "Get", Resource: "MedicalVocabulary", OutputListKey: "", OutputItemKey: ""}, - "GetTranscriptionJob": {Verb: "Get", Resource: "TranscriptionJob", OutputListKey: "", OutputItemKey: "TranscriptionJob"}, - "GetVocabulary": {Verb: "Get", Resource: "Vocabulary", OutputListKey: "", OutputItemKey: ""}, - "GetVocabularyFilter": {Verb: "Get", Resource: "VocabularyFilter", OutputListKey: "", OutputItemKey: ""}, - "ListCallAnalyticsCategories": {Verb: "List", Resource: "CallAnalyticsCategory", OutputListKey: "Categories", OutputItemKey: ""}, - "ListCallAnalyticsJobs": {Verb: "List", Resource: "CallAnalyticsJob", OutputListKey: "CallAnalyticsJobSummaries", OutputItemKey: ""}, - "ListLanguageModels": {Verb: "List", Resource: "LanguageModel", OutputListKey: "Models", OutputItemKey: ""}, - "ListMedicalScribeJobs": {Verb: "List", Resource: "MedicalScribeJob", OutputListKey: "MedicalScribeJobSummaries", OutputItemKey: ""}, - "ListMedicalTranscriptionJobs": {Verb: "List", Resource: "MedicalTranscriptionJob", OutputListKey: "MedicalTranscriptionJobSummaries", OutputItemKey: ""}, - "ListMedicalVocabularies": {Verb: "List", Resource: "MedicalVocabulary", OutputListKey: "Vocabularies", OutputItemKey: ""}, - "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "Tags", OutputItemKey: ""}, - "ListTranscriptionJobs": {Verb: "List", Resource: "TranscriptionJob", OutputListKey: "TranscriptionJobSummaries", OutputItemKey: ""}, - "ListVocabularies": {Verb: "List", Resource: "Vocabulary", OutputListKey: "Vocabularies", OutputItemKey: ""}, - "ListVocabularyFilters": {Verb: "List", Resource: "VocabularyFilter", OutputListKey: "VocabularyFilters", OutputItemKey: ""}, - "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: ""}, - "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: ""}, - "UpdateCallAnalyticsCategory": {Verb: "Update", Resource: "CallAnalyticsCategory", OutputListKey: "", OutputItemKey: "CategoryProperties"}, - "UpdateMedicalVocabulary": {Verb: "Update", Resource: "MedicalVocabulary", OutputListKey: "", OutputItemKey: ""}, - "UpdateVocabulary": {Verb: "Update", Resource: "Vocabulary", OutputListKey: "", OutputItemKey: ""}, - "UpdateVocabularyFilter": {Verb: "Update", Resource: "VocabularyFilter", OutputListKey: "", OutputItemKey: ""}, + "CreateCallAnalyticsCategory": {Verb: "Create", Resource: "CallAnalyticsCategory", OutputListKey: "", OutputItemKey: "CategoryProperties", Method: "PUT", URI: "/callanalyticscategories/{CategoryName}"}, + "CreateLanguageModel": {Verb: "Create", Resource: "LanguageModel", OutputListKey: "", OutputItemKey: "InputDataConfig", Method: "PUT", URI: "/languagemodels/{ModelName}"}, + "CreateMedicalVocabulary": {Verb: "Create", Resource: "MedicalVocabulary", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/medicalvocabularies/{VocabularyName}"}, + "CreateVocabulary": {Verb: "Create", Resource: "Vocabulary", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/vocabularies/{VocabularyName}"}, + "CreateVocabularyFilter": {Verb: "Create", Resource: "VocabularyFilter", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/vocabularyFilters/{VocabularyFilterName}"}, + "DeleteCallAnalyticsCategory": {Verb: "Delete", Resource: "CallAnalyticsCategory", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/callanalyticscategories/{CategoryName}"}, + "DeleteCallAnalyticsJob": {Verb: "Delete", Resource: "CallAnalyticsJob", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/callanalyticsjobs/{CallAnalyticsJobName}"}, + "DeleteLanguageModel": {Verb: "Delete", Resource: "LanguageModel", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/languagemodels/{ModelName}"}, + "DeleteMedicalScribeJob": {Verb: "Delete", Resource: "MedicalScribeJob", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/medicalscribejobs/{MedicalScribeJobName}"}, + "DeleteMedicalTranscriptionJob": {Verb: "Delete", Resource: "MedicalTranscriptionJob", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/medicaltranscriptionjobs/{MedicalTranscriptionJobName}"}, + "DeleteMedicalVocabulary": {Verb: "Delete", Resource: "MedicalVocabulary", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/medicalvocabularies/{VocabularyName}"}, + "DeleteTranscriptionJob": {Verb: "Delete", Resource: "TranscriptionJob", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/transcriptionjobs/{TranscriptionJobName}"}, + "DeleteVocabulary": {Verb: "Delete", Resource: "Vocabulary", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/vocabularies/{VocabularyName}"}, + "DeleteVocabularyFilter": {Verb: "Delete", Resource: "VocabularyFilter", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/vocabularyFilters/{VocabularyFilterName}"}, + "DescribeLanguageModel": {Verb: "Get", Resource: "LanguageModel", OutputListKey: "", OutputItemKey: "LanguageModel", Method: "GET", URI: "/languagemodels/{ModelName}"}, + "GetCallAnalyticsCategory": {Verb: "Get", Resource: "CallAnalyticsCategory", OutputListKey: "", OutputItemKey: "CategoryProperties", Method: "GET", URI: "/callanalyticscategories/{CategoryName}"}, + "GetCallAnalyticsJob": {Verb: "Get", Resource: "CallAnalyticsJob", OutputListKey: "", OutputItemKey: "CallAnalyticsJob", Method: "GET", URI: "/callanalyticsjobs/{CallAnalyticsJobName}"}, + "GetMedicalScribeJob": {Verb: "Get", Resource: "MedicalScribeJob", OutputListKey: "", OutputItemKey: "MedicalScribeJob", Method: "GET", URI: "/medicalscribejobs/{MedicalScribeJobName}"}, + "GetMedicalTranscriptionJob": {Verb: "Get", Resource: "MedicalTranscriptionJob", OutputListKey: "", OutputItemKey: "MedicalTranscriptionJob", Method: "GET", URI: "/medicaltranscriptionjobs/{MedicalTranscriptionJobName}"}, + "GetMedicalVocabulary": {Verb: "Get", Resource: "MedicalVocabulary", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/medicalvocabularies/{VocabularyName}"}, + "GetTranscriptionJob": {Verb: "Get", Resource: "TranscriptionJob", OutputListKey: "", OutputItemKey: "TranscriptionJob", Method: "GET", URI: "/transcriptionjobs/{TranscriptionJobName}"}, + "GetVocabulary": {Verb: "Get", Resource: "Vocabulary", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/vocabularies/{VocabularyName}"}, + "GetVocabularyFilter": {Verb: "Get", Resource: "VocabularyFilter", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/vocabularyFilters/{VocabularyFilterName}"}, + "ListCallAnalyticsCategories": {Verb: "List", Resource: "CallAnalyticsCategory", OutputListKey: "Categories", OutputItemKey: "", Method: "GET", URI: "/callanalyticscategories"}, + "ListCallAnalyticsJobs": {Verb: "List", Resource: "CallAnalyticsJob", OutputListKey: "CallAnalyticsJobSummaries", OutputItemKey: "", Method: "GET", URI: "/callanalyticsjobs"}, + "ListLanguageModels": {Verb: "List", Resource: "LanguageModel", OutputListKey: "Models", OutputItemKey: "", Method: "GET", URI: "/languagemodels"}, + "ListMedicalScribeJobs": {Verb: "List", Resource: "MedicalScribeJob", OutputListKey: "MedicalScribeJobSummaries", OutputItemKey: "", Method: "GET", URI: "/medicalscribejobs"}, + "ListMedicalTranscriptionJobs": {Verb: "List", Resource: "MedicalTranscriptionJob", OutputListKey: "MedicalTranscriptionJobSummaries", OutputItemKey: "", Method: "GET", URI: "/medicaltranscriptionjobs"}, + "ListMedicalVocabularies": {Verb: "List", Resource: "MedicalVocabulary", OutputListKey: "Vocabularies", OutputItemKey: "", Method: "GET", URI: "/medicalvocabularies"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "Tags", OutputItemKey: "", Method: "GET", URI: "/tags/{ResourceArn}"}, + "ListTranscriptionJobs": {Verb: "List", Resource: "TranscriptionJob", OutputListKey: "TranscriptionJobSummaries", OutputItemKey: "", Method: "GET", URI: "/transcriptionjobs"}, + "ListVocabularies": {Verb: "List", Resource: "Vocabulary", OutputListKey: "Vocabularies", OutputItemKey: "", Method: "GET", URI: "/vocabularies"}, + "ListVocabularyFilters": {Verb: "List", Resource: "VocabularyFilter", OutputListKey: "VocabularyFilters", OutputItemKey: "", Method: "GET", URI: "/vocabularyFilters"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/tags/{ResourceArn}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/tags/{ResourceArn}"}, + "UpdateCallAnalyticsCategory": {Verb: "Update", Resource: "CallAnalyticsCategory", OutputListKey: "", OutputItemKey: "CategoryProperties", Method: "PATCH", URI: "/callanalyticscategories/{CategoryName}"}, + "UpdateMedicalVocabulary": {Verb: "Update", Resource: "MedicalVocabulary", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/medicalvocabularies/{VocabularyName}"}, + "UpdateVocabulary": {Verb: "Update", Resource: "Vocabulary", OutputListKey: "", OutputItemKey: "", Method: "PATCH", URI: "/vocabularies/{VocabularyName}"}, + "UpdateVocabularyFilter": {Verb: "Update", Resource: "VocabularyFilter", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/vocabularyFilters/{VocabularyFilterName}"}, + }) + crud.Register("transcribestreaming", map[string]crud.OpMeta{ + "GetMedicalScribeStream": {Verb: "Get", Resource: "MedicalScribeStream", OutputListKey: "", OutputItemKey: "MedicalScribeStreamDetails", Method: "GET", URI: "/medical-scribe-stream/{SessionId}"}, }) crud.Register("transfer", map[string]crud.OpMeta{ "CreateAccess": {Verb: "Create", Resource: "Access", OutputListKey: "", OutputItemKey: ""}, @@ -2696,7 +5151,7 @@ func init() { "CreateProfile": {Verb: "Create", Resource: "Profile", OutputListKey: "", OutputItemKey: ""}, "CreateServer": {Verb: "Create", Resource: "Server", OutputListKey: "", OutputItemKey: ""}, "CreateUser": {Verb: "Create", Resource: "User", OutputListKey: "", OutputItemKey: ""}, - "CreateWebApp": {Verb: "Create", Resource: "WebApp", OutputListKey: "", OutputItemKey: ""}, + "CreateWebApp": {Verb: "Create", Resource: "WebApp", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/createWebApp"}, "CreateWorkflow": {Verb: "Create", Resource: "Workflow", OutputListKey: "", OutputItemKey: ""}, "DeleteAccess": {Verb: "Delete", Resource: "Access", OutputListKey: "", OutputItemKey: ""}, "DeleteAgreement": {Verb: "Delete", Resource: "Agreement", OutputListKey: "", OutputItemKey: ""}, @@ -2707,8 +5162,8 @@ func init() { "DeleteServer": {Verb: "Delete", Resource: "Server", OutputListKey: "", OutputItemKey: ""}, "DeleteSshPublicKey": {Verb: "Delete", Resource: "SshPublicKey", OutputListKey: "", OutputItemKey: ""}, "DeleteUser": {Verb: "Delete", Resource: "User", OutputListKey: "", OutputItemKey: ""}, - "DeleteWebApp": {Verb: "Delete", Resource: "WebApp", OutputListKey: "", OutputItemKey: ""}, - "DeleteWebAppCustomization": {Verb: "Delete", Resource: "WebAppCustomization", OutputListKey: "", OutputItemKey: ""}, + "DeleteWebApp": {Verb: "Delete", Resource: "WebApp", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/deleteWebApp"}, + "DeleteWebAppCustomization": {Verb: "Delete", Resource: "WebAppCustomization", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/deleteWebAppCustomization"}, "DeleteWorkflow": {Verb: "Delete", Resource: "Workflow", OutputListKey: "", OutputItemKey: ""}, "DescribeAccess": {Verb: "Get", Resource: "Access", OutputListKey: "", OutputItemKey: "Access"}, "DescribeAgreement": {Verb: "Get", Resource: "Agreement", OutputListKey: "", OutputItemKey: "Agreement"}, @@ -2720,22 +5175,22 @@ func init() { "DescribeSecurityPolicy": {Verb: "Get", Resource: "SecurityPolicy", OutputListKey: "", OutputItemKey: "SecurityPolicy"}, "DescribeServer": {Verb: "Get", Resource: "Server", OutputListKey: "", OutputItemKey: "Server"}, "DescribeUser": {Verb: "Get", Resource: "User", OutputListKey: "", OutputItemKey: "User"}, - "DescribeWebApp": {Verb: "Get", Resource: "WebApp", OutputListKey: "", OutputItemKey: "WebApp"}, - "DescribeWebAppCustomization": {Verb: "Get", Resource: "WebAppCustomization", OutputListKey: "", OutputItemKey: "WebAppCustomization"}, + "DescribeWebApp": {Verb: "Get", Resource: "WebApp", OutputListKey: "", OutputItemKey: "WebApp", Method: "POST", URI: "/describeWebApp"}, + "DescribeWebAppCustomization": {Verb: "Get", Resource: "WebAppCustomization", OutputListKey: "", OutputItemKey: "WebAppCustomization", Method: "POST", URI: "/describeWebAppCustomization"}, "DescribeWorkflow": {Verb: "Get", Resource: "Workflow", OutputListKey: "", OutputItemKey: "Workflow"}, "ListAccesses": {Verb: "List", Resource: "Access", OutputListKey: "Accesses", OutputItemKey: ""}, "ListAgreements": {Verb: "List", Resource: "Agreement", OutputListKey: "Agreements", OutputItemKey: ""}, "ListCertificates": {Verb: "List", Resource: "Certificate", OutputListKey: "Certificates", OutputItemKey: ""}, "ListConnectors": {Verb: "List", Resource: "Connector", OutputListKey: "Connectors", OutputItemKey: ""}, "ListExecutions": {Verb: "List", Resource: "Execution", OutputListKey: "Executions", OutputItemKey: ""}, - "ListFileTransferResults": {Verb: "List", Resource: "FileTransferResult", OutputListKey: "FileTransferResults", OutputItemKey: ""}, + "ListFileTransferResults": {Verb: "List", Resource: "FileTransferResult", OutputListKey: "FileTransferResults", OutputItemKey: "", Method: "POST", URI: "/listFileTransferResults"}, "ListHostKeys": {Verb: "List", Resource: "HostKey", OutputListKey: "HostKeys", OutputItemKey: ""}, "ListProfiles": {Verb: "List", Resource: "Profile", OutputListKey: "Profiles", OutputItemKey: ""}, "ListSecurityPolicies": {Verb: "List", Resource: "SecurityPolicy", OutputListKey: "SecurityPolicyNames", OutputItemKey: ""}, "ListServers": {Verb: "List", Resource: "Server", OutputListKey: "Servers", OutputItemKey: ""}, "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "Tags", OutputItemKey: ""}, "ListUsers": {Verb: "List", Resource: "User", OutputListKey: "Users", OutputItemKey: ""}, - "ListWebApps": {Verb: "List", Resource: "WebApp", OutputListKey: "WebApps", OutputItemKey: ""}, + "ListWebApps": {Verb: "List", Resource: "WebApp", OutputListKey: "WebApps", OutputItemKey: "", Method: "POST", URI: "/listWebApps"}, "ListWorkflows": {Verb: "List", Resource: "Workflow", OutputListKey: "Workflows", OutputItemKey: ""}, "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: ""}, "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: ""}, @@ -2747,8 +5202,8 @@ func init() { "UpdateProfile": {Verb: "Update", Resource: "Profile", OutputListKey: "", OutputItemKey: ""}, "UpdateServer": {Verb: "Update", Resource: "Server", OutputListKey: "", OutputItemKey: ""}, "UpdateUser": {Verb: "Update", Resource: "User", OutputListKey: "", OutputItemKey: ""}, - "UpdateWebApp": {Verb: "Update", Resource: "WebApp", OutputListKey: "", OutputItemKey: ""}, - "UpdateWebAppCustomization": {Verb: "Update", Resource: "WebAppCustomization", OutputListKey: "", OutputItemKey: ""}, + "UpdateWebApp": {Verb: "Update", Resource: "WebApp", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/updateWebApp"}, + "UpdateWebAppCustomization": {Verb: "Update", Resource: "WebAppCustomization", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/updateWebAppCustomization"}, }) crud.Register("translate", map[string]crud.OpMeta{ "CreateParallelData": {Verb: "Create", Resource: "ParallelData", OutputListKey: "", OutputItemKey: ""}, @@ -2923,4 +5378,42 @@ func init() { "UpdateRuleGroup": {Verb: "Update", Resource: "RuleGroup", OutputListKey: "", OutputItemKey: ""}, "UpdateWebACL": {Verb: "Update", Resource: "WebACL", OutputListKey: "", OutputItemKey: ""}, }) + crud.Register("xray", map[string]crud.OpMeta{ + "BatchGetTraces": {Verb: "List", Resource: "Trace", OutputListKey: "Traces", OutputItemKey: "", Method: "POST", URI: "/Traces"}, + "CreateGroup": {Verb: "Create", Resource: "Group", OutputListKey: "", OutputItemKey: "Group", Method: "POST", URI: "/CreateGroup"}, + "CreateSamplingRule": {Verb: "Create", Resource: "SamplingRule", OutputListKey: "", OutputItemKey: "SamplingRuleRecord", Method: "POST", URI: "/CreateSamplingRule"}, + "DeleteGroup": {Verb: "Delete", Resource: "Group", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/DeleteGroup"}, + "DeleteResourcePolicy": {Verb: "Delete", Resource: "ResourcePolicy", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/DeleteResourcePolicy"}, + "DeleteSamplingRule": {Verb: "Delete", Resource: "SamplingRule", OutputListKey: "", OutputItemKey: "SamplingRuleRecord", Method: "POST", URI: "/DeleteSamplingRule"}, + "GetEncryptionConfig": {Verb: "Get", Resource: "EncryptionConfig", OutputListKey: "", OutputItemKey: "EncryptionConfig", Method: "POST", URI: "/EncryptionConfig"}, + "GetGroup": {Verb: "Get", Resource: "Group", OutputListKey: "", OutputItemKey: "Group", Method: "POST", URI: "/GetGroup"}, + "GetGroups": {Verb: "Get", Resource: "Group", OutputListKey: "Groups", OutputItemKey: "", Method: "POST", URI: "/Groups"}, + "GetIndexingRules": {Verb: "Get", Resource: "IndexingRule", OutputListKey: "IndexingRules", OutputItemKey: "", Method: "POST", URI: "/GetIndexingRules"}, + "GetInsight": {Verb: "Get", Resource: "Insight", OutputListKey: "", OutputItemKey: "Insight", Method: "POST", URI: "/Insight"}, + "GetInsightEvents": {Verb: "Get", Resource: "InsightEvent", OutputListKey: "InsightEvents", OutputItemKey: "", Method: "POST", URI: "/InsightEvents"}, + "GetInsightImpactGraph": {Verb: "Get", Resource: "InsightImpactGraph", OutputListKey: "Services", OutputItemKey: "", Method: "POST", URI: "/InsightImpactGraph"}, + "GetInsightSummaries": {Verb: "Get", Resource: "InsightSummary", OutputListKey: "InsightSummaries", OutputItemKey: "", Method: "POST", URI: "/InsightSummaries"}, + "GetRetrievedTracesGraph": {Verb: "Get", Resource: "RetrievedTracesGraph", OutputListKey: "Services", OutputItemKey: "", Method: "POST", URI: "/GetRetrievedTracesGraph"}, + "GetSamplingRules": {Verb: "Get", Resource: "SamplingRule", OutputListKey: "SamplingRuleRecords", OutputItemKey: "", Method: "POST", URI: "/GetSamplingRules"}, + "GetSamplingStatisticSummaries": {Verb: "Get", Resource: "SamplingStatisticSummary", OutputListKey: "SamplingStatisticSummaries", OutputItemKey: "", Method: "POST", URI: "/SamplingStatisticSummaries"}, + "GetSamplingTargets": {Verb: "Get", Resource: "SamplingTarget", OutputListKey: "SamplingTargetDocuments", OutputItemKey: "", Method: "POST", URI: "/SamplingTargets"}, + "GetServiceGraph": {Verb: "Get", Resource: "ServiceGraph", OutputListKey: "Services", OutputItemKey: "", Method: "POST", URI: "/ServiceGraph"}, + "GetTimeSeriesServiceStatistics": {Verb: "Get", Resource: "TimeSeriesServiceStatistic", OutputListKey: "TimeSeriesServiceStatistics", OutputItemKey: "", Method: "POST", URI: "/TimeSeriesServiceStatistics"}, + "GetTraceGraph": {Verb: "Get", Resource: "TraceGraph", OutputListKey: "Services", OutputItemKey: "", Method: "POST", URI: "/TraceGraph"}, + "GetTraceSegmentDestination": {Verb: "Get", Resource: "TraceSegmentDestination", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/GetTraceSegmentDestination"}, + "GetTraceSummaries": {Verb: "Get", Resource: "TraceSummary", OutputListKey: "TraceSummaries", OutputItemKey: "", Method: "POST", URI: "/TraceSummaries"}, + "ListResourcePolicies": {Verb: "List", Resource: "ResourcePolicy", OutputListKey: "ResourcePolicies", OutputItemKey: "", Method: "POST", URI: "/ListResourcePolicies"}, + "ListRetrievedTraces": {Verb: "List", Resource: "RetrievedTrace", OutputListKey: "Traces", OutputItemKey: "", Method: "POST", URI: "/ListRetrievedTraces"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "Tags", OutputItemKey: "", Method: "POST", URI: "/ListTagsForResource"}, + "PutEncryptionConfig": {Verb: "Update", Resource: "EncryptionConfig", OutputListKey: "", OutputItemKey: "EncryptionConfig", Method: "POST", URI: "/PutEncryptionConfig"}, + "PutResourcePolicy": {Verb: "Update", Resource: "ResourcePolicy", OutputListKey: "", OutputItemKey: "ResourcePolicy", Method: "POST", URI: "/PutResourcePolicy"}, + "PutTelemetryRecords": {Verb: "Update", Resource: "TelemetryRecord", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/TelemetryRecords"}, + "PutTraceSegments": {Verb: "Update", Resource: "TraceSegment", OutputListKey: "UnprocessedTraceSegments", OutputItemKey: "", Method: "POST", URI: "/TraceSegments"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/TagResource"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/UntagResource"}, + "UpdateGroup": {Verb: "Update", Resource: "Group", OutputListKey: "", OutputItemKey: "Group", Method: "POST", URI: "/UpdateGroup"}, + "UpdateIndexingRule": {Verb: "Update", Resource: "IndexingRule", OutputListKey: "", OutputItemKey: "IndexingRule", Method: "POST", URI: "/UpdateIndexingRule"}, + "UpdateSamplingRule": {Verb: "Update", Resource: "SamplingRule", OutputListKey: "", OutputItemKey: "SamplingRuleRecord", Method: "POST", URI: "/UpdateSamplingRule"}, + "UpdateTraceSegmentDestination": {Verb: "Update", Resource: "TraceSegmentDestination", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/UpdateTraceSegmentDestination"}, + }) } diff --git a/internal/generated/devopsguru/router.go b/internal/generated/devopsguru/router.go index 9aca8ff0..6f0245a7 100644 --- a/internal/generated/devopsguru/router.go +++ b/internal/generated/devopsguru/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package devopsguru -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -59,126 +52,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/docdb/router.go b/internal/generated/docdb/router.go index 2a2b5362..bff61827 100644 --- a/internal/generated/docdb/router.go +++ b/internal/generated/docdb/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package docdb -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -83,126 +76,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/dynamodb/router.go b/internal/generated/dynamodb/router.go index 231c1c19..a81ed4b2 100644 --- a/internal/generated/dynamodb/router.go +++ b/internal/generated/dynamodb/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package dynamodb -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -85,126 +78,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/dynamodbstreams/router.go b/internal/generated/dynamodbstreams/router.go index ddd0c136..94eed756 100644 --- a/internal/generated/dynamodbstreams/router.go +++ b/internal/generated/dynamodbstreams/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package dynamodbstreams -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -32,126 +25,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/ebs/router.go b/internal/generated/ebs/router.go index 57f1dc0e..0c692e38 100644 --- a/internal/generated/ebs/router.go +++ b/internal/generated/ebs/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package ebs -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -34,126 +27,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/ec2/router.go b/internal/generated/ec2/router.go index d1f63176..fe7769b7 100644 --- a/internal/generated/ec2/router.go +++ b/internal/generated/ec2/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package ec2 -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -784,126 +777,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/ecr/router.go b/internal/generated/ecr/router.go index 13730ce4..54df2dc5 100644 --- a/internal/generated/ecr/router.go +++ b/internal/generated/ecr/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package ecr -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -86,126 +79,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/ecs/router.go b/internal/generated/ecs/router.go index eeb46c95..40564d13 100644 --- a/internal/generated/ecs/router.go +++ b/internal/generated/ecs/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package ecs -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -104,126 +97,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/efs/router.go b/internal/generated/efs/router.go index 6c3a442e..9df13a97 100644 --- a/internal/generated/efs/router.go +++ b/internal/generated/efs/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package efs -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -59,126 +52,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/eks/router.go b/internal/generated/eks/router.go index 4d4003f3..8392791b 100644 --- a/internal/generated/eks/router.go +++ b/internal/generated/eks/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package eks -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -92,126 +85,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/elasticache/router.go b/internal/generated/elasticache/router.go index a227634a..42df9352 100644 --- a/internal/generated/elasticache/router.go +++ b/internal/generated/elasticache/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package elasticache -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -103,126 +96,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/elasticbeanstalk/router.go b/internal/generated/elasticbeanstalk/router.go index 1cad3867..77e8bd71 100644 --- a/internal/generated/elasticbeanstalk/router.go +++ b/internal/generated/elasticbeanstalk/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package elasticbeanstalk -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -75,126 +68,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/elasticloadbalancingv2/router.go b/internal/generated/elasticloadbalancingv2/router.go index 80322861..f28f7548 100644 --- a/internal/generated/elasticloadbalancingv2/router.go +++ b/internal/generated/elasticloadbalancingv2/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package elasticloadbalancingv2 -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -79,126 +72,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/elasticsearchservice/router.go b/internal/generated/elasticsearchservice/router.go index 1aea7447..55f9d2dd 100644 --- a/internal/generated/elasticsearchservice/router.go +++ b/internal/generated/elasticsearchservice/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package elasticsearchservice -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -79,126 +72,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/emr/router.go b/internal/generated/emr/router.go index 6d01d72a..773673cf 100644 --- a/internal/generated/emr/router.go +++ b/internal/generated/emr/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package emr -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -88,126 +81,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/entityresolution/router.go b/internal/generated/entityresolution/router.go index 13699d32..002838da 100644 --- a/internal/generated/entityresolution/router.go +++ b/internal/generated/entityresolution/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package entityresolution -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -66,126 +59,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/eventbridge/router.go b/internal/generated/eventbridge/router.go index 3616563c..0aef66c4 100644 --- a/internal/generated/eventbridge/router.go +++ b/internal/generated/eventbridge/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package eventbridge -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -85,126 +78,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/fidelity/manifest_gen.go b/internal/generated/fidelity/manifest_gen.go index 7cfa18cf..c853a686 100644 --- a/internal/generated/fidelity/manifest_gen.go +++ b/internal/generated/fidelity/manifest_gen.go @@ -46,12 +46,22 @@ type Service struct { // service's API. When false the unimplemented tail is not knowable, so the // manifest lists only what DevCloud serves. ModelBacked bool + // EngineWired reports whether the provider hands the operations it does not + // implement to the generic CRUD engine, by returning plugin.ErrUnhandledOp. + // + // It is the difference between an operation being *classifiable* and being + // *reachable*. The CRUD registry is built from the model, so it holds + // entries for services whose hand-written provider refuses unknown + // operations itself and never routes to the engine — for those, a + // registered operation is genuinely unimplemented, and only this field says + // so without guessing. + EngineWired bool Operations map[string]Tier } // Services maps a registered service ID to its operations. var Services = map[string]Service{ - "account": {Protocol: "", ModelBacked: false, Operations: map[string]Tier{ + "account": {Protocol: "", ModelBacked: false, EngineWired: false, Operations: map[string]Tier{ "AcceptPrimaryEmailUpdate": TierHandVerified, "DeleteAlternateContact": TierHandVerified, "DeleteContactInformation": TierHandVerified, @@ -68,7 +78,7 @@ var Services = map[string]Service{ "PutContactInformation": TierHandVerified, "StartPrimaryEmailUpdate": TierHandVerified, }}, - "acm": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "acm": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AddTagsToCertificate": TierHandVerified, "CancelCertificateIssuance": TierHandVerified, "CreatePermission": TierHandVerified, @@ -108,7 +118,7 @@ var Services = map[string]Service{ "UpdateCertificateOptions": TierHandVerified, "WaitForValidation": TierHandVerified, }}, - "acmpca": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "acmpca": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "CreateCertificateAuthority": TierHandVerified, "CreateCertificateAuthorityAuditReport": TierHandVerified, "CreatePermission": TierHandVerified, @@ -133,7 +143,7 @@ var Services = map[string]Service{ "UntagCertificateAuthority": TierHandVerified, "UpdateCertificateAuthority": TierHandVerified, }}, - "amplify": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "amplify": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "CreateApp": TierHandVerified, "CreateBackendEnvironment": TierHandVerified, "CreateBranch": TierHandVerified, @@ -172,7 +182,7 @@ var Services = map[string]Service{ "UpdateDomainAssociation": TierHandVerified, "UpdateWebhook": TierHandVerified, }}, - "apigatewayv2": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "apigatewayv2": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "CreateApi": TierHandVerified, "CreateApiMapping": TierHandVerified, "CreateAuthorizer": TierHandVerified, @@ -277,7 +287,7 @@ var Services = map[string]Service{ "UpdateStage": TierHandVerified, "UpdateVpcLink": TierHandVerified, }}, - "appconfig": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "appconfig": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "CreateApplication": TierHandVerified, "CreateConfigurationProfile": TierHandVerified, "CreateDeploymentStrategy": TierHandVerified, @@ -324,7 +334,7 @@ var Services = map[string]Service{ "UpdateExtensionAssociation": TierHandVerified, "ValidateConfiguration": TierHandVerified, }}, - "applicationautoscaling": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "applicationautoscaling": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "BatchDeleteScalingPolicy": TierHandVerified, "BatchDeleteScheduledAction": TierHandVerified, "BatchDeregisterScalableTarget": TierHandVerified, @@ -366,7 +376,7 @@ var Services = map[string]Service{ "UpdateScalingPolicy": TierHandVerified, "UpdateScheduledAction": TierHandVerified, }}, - "appsync": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "appsync": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "AssociateApi": TierHandVerified, "AssociateMergedGraphqlApi": TierHandVerified, "AssociateSourceGraphqlApi": TierHandVerified, @@ -446,7 +456,7 @@ var Services = map[string]Service{ "UpdateSourceApiAssociation": TierHandVerified, "UpdateType": TierHandVerified, }}, - "athena": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "athena": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "BatchGetNamedQuery": TierHandVerified, "BatchGetPreparedStatement": TierHandVerified, "BatchGetQueryExecution": TierHandVerified, @@ -518,7 +528,7 @@ var Services = map[string]Service{ "UpdatePreparedStatement": TierHandVerified, "UpdateWorkGroup": TierHandVerified, }}, - "autoscaling": {Protocol: "query", ModelBacked: true, Operations: map[string]Tier{ + "autoscaling": {Protocol: "query", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "AttachInstances": TierHandVerified, "AttachLoadBalancerTargetGroups": TierHandVerified, "AttachLoadBalancers": TierHandVerified, @@ -586,7 +596,7 @@ var Services = map[string]Service{ "TerminateInstanceInAutoScalingGroup": TierHandVerified, "UpdateAutoScalingGroup": TierHandVerified, }}, - "backup": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "backup": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "AssociateBackupVaultMpaApprovalTeam": TierUnimplemented, "CancelLegalHold": TierUnimplemented, "CreateBackupPlan": TierHandVerified, @@ -696,7 +706,7 @@ var Services = map[string]Service{ "UpdateRestoreTestingSelection": TierHandVerified, "UpdateTieringConfiguration": TierUnimplemented, }}, - "batch": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "batch": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "CancelJob": TierHandVerified, "CreateComputeEnvironment": TierHandVerified, "CreateConsumableResource": TierHandVerified, @@ -743,7 +753,7 @@ var Services = map[string]Service{ "UpdateServiceEnvironment": TierHandVerified, "UpdateServiceJob": TierHandVerified, }}, - "bedrock": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "bedrock": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "BatchDeleteEvaluationJob": TierUnimplemented, "CancelAutomatedReasoningPolicyBuildWorkflow": TierUnimplemented, "CreateAutomatedReasoningPolicy": TierUnimplemented, @@ -848,136 +858,136 @@ var Services = map[string]Service{ "UpdateMarketplaceModelEndpoint": TierUnimplemented, "UpdateProvisionedModelThroughput": TierUnimplemented, }}, - "bedrockagent": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "bedrockagent": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AssociateAgentCollaborator": TierUnimplemented, "AssociateAgentKnowledgeBase": TierUnimplemented, - "CreateAgent": TierUnimplemented, - "CreateAgentActionGroup": TierUnimplemented, - "CreateAgentAlias": TierUnimplemented, - "CreateDataSource": TierUnimplemented, - "CreateFlow": TierUnimplemented, - "CreateFlowAlias": TierUnimplemented, - "CreateFlowVersion": TierUnimplemented, - "CreateKnowledgeBase": TierUnimplemented, - "CreatePrompt": TierUnimplemented, - "CreatePromptVersion": TierUnimplemented, - "DeleteAgent": TierUnimplemented, - "DeleteAgentActionGroup": TierUnimplemented, - "DeleteAgentAlias": TierUnimplemented, - "DeleteAgentVersion": TierUnimplemented, - "DeleteDataSource": TierUnimplemented, - "DeleteFlow": TierUnimplemented, - "DeleteFlowAlias": TierUnimplemented, - "DeleteFlowVersion": TierUnimplemented, - "DeleteKnowledgeBase": TierUnimplemented, - "DeleteKnowledgeBaseDocuments": TierUnimplemented, - "DeletePrompt": TierUnimplemented, - "DeleteResourcePolicy": TierUnimplemented, + "CreateAgent": TierAutoCRUD, + "CreateAgentActionGroup": TierAutoCRUD, + "CreateAgentAlias": TierAutoCRUD, + "CreateDataSource": TierAutoCRUD, + "CreateFlow": TierAutoCRUD, + "CreateFlowAlias": TierAutoCRUD, + "CreateFlowVersion": TierAutoCRUD, + "CreateKnowledgeBase": TierAutoCRUD, + "CreatePrompt": TierAutoCRUD, + "CreatePromptVersion": TierAutoCRUD, + "DeleteAgent": TierAutoCRUD, + "DeleteAgentActionGroup": TierAutoCRUD, + "DeleteAgentAlias": TierAutoCRUD, + "DeleteAgentVersion": TierAutoCRUD, + "DeleteDataSource": TierAutoCRUD, + "DeleteFlow": TierAutoCRUD, + "DeleteFlowAlias": TierAutoCRUD, + "DeleteFlowVersion": TierAutoCRUD, + "DeleteKnowledgeBase": TierAutoCRUD, + "DeleteKnowledgeBaseDocuments": TierAutoCRUD, + "DeletePrompt": TierAutoCRUD, + "DeleteResourcePolicy": TierAutoCRUD, "DisassociateAgentCollaborator": TierUnimplemented, "DisassociateAgentKnowledgeBase": TierUnimplemented, - "GetAgent": TierUnimplemented, - "GetAgentActionGroup": TierUnimplemented, - "GetAgentAlias": TierUnimplemented, - "GetAgentCollaborator": TierUnimplemented, - "GetAgentKnowledgeBase": TierUnimplemented, - "GetAgentVersion": TierUnimplemented, - "GetDataSource": TierUnimplemented, - "GetFlow": TierUnimplemented, - "GetFlowAlias": TierUnimplemented, - "GetFlowVersion": TierUnimplemented, - "GetIngestionJob": TierUnimplemented, - "GetKnowledgeBase": TierUnimplemented, - "GetKnowledgeBaseDocuments": TierUnimplemented, - "GetPrompt": TierUnimplemented, - "GetResourcePolicy": TierUnimplemented, + "GetAgent": TierAutoCRUD, + "GetAgentActionGroup": TierAutoCRUD, + "GetAgentAlias": TierAutoCRUD, + "GetAgentCollaborator": TierAutoCRUD, + "GetAgentKnowledgeBase": TierAutoCRUD, + "GetAgentVersion": TierAutoCRUD, + "GetDataSource": TierAutoCRUD, + "GetFlow": TierAutoCRUD, + "GetFlowAlias": TierAutoCRUD, + "GetFlowVersion": TierAutoCRUD, + "GetIngestionJob": TierAutoCRUD, + "GetKnowledgeBase": TierAutoCRUD, + "GetKnowledgeBaseDocuments": TierAutoCRUD, + "GetPrompt": TierAutoCRUD, + "GetResourcePolicy": TierAutoCRUD, "IngestKnowledgeBaseDocuments": TierUnimplemented, - "ListAgentActionGroups": TierUnimplemented, - "ListAgentAliases": TierUnimplemented, - "ListAgentCollaborators": TierUnimplemented, - "ListAgentKnowledgeBases": TierUnimplemented, - "ListAgentVersions": TierUnimplemented, - "ListAgents": TierUnimplemented, - "ListDataSources": TierUnimplemented, - "ListFlowAliases": TierUnimplemented, - "ListFlowVersions": TierUnimplemented, - "ListFlows": TierUnimplemented, - "ListIngestionJobs": TierUnimplemented, - "ListKnowledgeBaseDocuments": TierUnimplemented, - "ListKnowledgeBases": TierUnimplemented, - "ListPrompts": TierUnimplemented, - "ListTagsForResource": TierUnimplemented, + "ListAgentActionGroups": TierAutoCRUD, + "ListAgentAliases": TierAutoCRUD, + "ListAgentCollaborators": TierAutoCRUD, + "ListAgentKnowledgeBases": TierAutoCRUD, + "ListAgentVersions": TierAutoCRUD, + "ListAgents": TierAutoCRUD, + "ListDataSources": TierAutoCRUD, + "ListFlowAliases": TierAutoCRUD, + "ListFlowVersions": TierAutoCRUD, + "ListFlows": TierAutoCRUD, + "ListIngestionJobs": TierAutoCRUD, + "ListKnowledgeBaseDocuments": TierAutoCRUD, + "ListKnowledgeBases": TierAutoCRUD, + "ListPrompts": TierAutoCRUD, + "ListTagsForResource": TierAutoCRUD, "PrepareAgent": TierUnimplemented, "PrepareFlow": TierUnimplemented, - "PutResourcePolicy": TierUnimplemented, + "PutResourcePolicy": TierAutoCRUD, "StartIngestionJob": TierUnimplemented, "StopIngestionJob": TierUnimplemented, - "TagResource": TierUnimplemented, - "UntagResource": TierUnimplemented, - "UpdateAgent": TierUnimplemented, - "UpdateAgentActionGroup": TierUnimplemented, - "UpdateAgentAlias": TierUnimplemented, - "UpdateAgentCollaborator": TierUnimplemented, - "UpdateAgentKnowledgeBase": TierUnimplemented, - "UpdateDataSource": TierUnimplemented, - "UpdateFlow": TierUnimplemented, - "UpdateFlowAlias": TierUnimplemented, - "UpdateKnowledgeBase": TierUnimplemented, - "UpdatePrompt": TierUnimplemented, + "TagResource": TierAutoCRUD, + "UntagResource": TierAutoCRUD, + "UpdateAgent": TierAutoCRUD, + "UpdateAgentActionGroup": TierAutoCRUD, + "UpdateAgentAlias": TierAutoCRUD, + "UpdateAgentCollaborator": TierAutoCRUD, + "UpdateAgentKnowledgeBase": TierAutoCRUD, + "UpdateDataSource": TierAutoCRUD, + "UpdateFlow": TierAutoCRUD, + "UpdateFlowAlias": TierAutoCRUD, + "UpdateKnowledgeBase": TierAutoCRUD, + "UpdatePrompt": TierAutoCRUD, "ValidateFlowDefinition": TierUnimplemented, }}, - "bedrockagentcore": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "bedrockagentcore": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "BatchCreateMemoryRecords": TierUnimplemented, "BatchDeleteMemoryRecords": TierUnimplemented, "BatchUpdateMemoryRecords": TierUnimplemented, "CompleteResourceTokenAuth": TierUnimplemented, - "CreateABTest": TierUnimplemented, - "CreateEvent": TierUnimplemented, - "CreatePaymentInstrument": TierUnimplemented, - "CreatePaymentSession": TierUnimplemented, - "DeleteABTest": TierUnimplemented, - "DeleteBatchEvaluation": TierUnimplemented, - "DeleteCapacityProviderSession": TierUnimplemented, - "DeleteEvent": TierUnimplemented, - "DeleteMemoryRecord": TierUnimplemented, - "DeletePaymentInstrument": TierUnimplemented, - "DeletePaymentSession": TierUnimplemented, - "DeleteRecommendation": TierUnimplemented, + "CreateABTest": TierAutoCRUD, + "CreateEvent": TierAutoCRUD, + "CreatePaymentInstrument": TierAutoCRUD, + "CreatePaymentSession": TierAutoCRUD, + "DeleteABTest": TierAutoCRUD, + "DeleteBatchEvaluation": TierAutoCRUD, + "DeleteCapacityProviderSession": TierAutoCRUD, + "DeleteEvent": TierAutoCRUD, + "DeleteMemoryRecord": TierAutoCRUD, + "DeletePaymentInstrument": TierAutoCRUD, + "DeletePaymentSession": TierAutoCRUD, + "DeleteRecommendation": TierAutoCRUD, "Evaluate": TierUnimplemented, - "GetABTest": TierUnimplemented, - "GetAgentCard": TierUnimplemented, - "GetBatchEvaluation": TierUnimplemented, - "GetBrowserSession": TierUnimplemented, - "GetCodeInterpreterSession": TierUnimplemented, - "GetEvent": TierUnimplemented, - "GetMemoryRecord": TierUnimplemented, - "GetPaymentInstrument": TierUnimplemented, - "GetPaymentInstrumentBalance": TierUnimplemented, - "GetPaymentSession": TierUnimplemented, - "GetRecommendation": TierUnimplemented, - "GetResourceApiKey": TierUnimplemented, - "GetResourceOauth2Token": TierUnimplemented, - "GetResourcePaymentToken": TierUnimplemented, - "GetWorkloadAccessToken": TierUnimplemented, - "GetWorkloadAccessTokenForJWT": TierUnimplemented, - "GetWorkloadAccessTokenForUserId": TierUnimplemented, + "GetABTest": TierAutoCRUD, + "GetAgentCard": TierAutoCRUD, + "GetBatchEvaluation": TierAutoCRUD, + "GetBrowserSession": TierAutoCRUD, + "GetCodeInterpreterSession": TierAutoCRUD, + "GetEvent": TierAutoCRUD, + "GetMemoryRecord": TierAutoCRUD, + "GetPaymentInstrument": TierAutoCRUD, + "GetPaymentInstrumentBalance": TierAutoCRUD, + "GetPaymentSession": TierAutoCRUD, + "GetRecommendation": TierAutoCRUD, + "GetResourceApiKey": TierAutoCRUD, + "GetResourceOauth2Token": TierAutoCRUD, + "GetResourcePaymentToken": TierAutoCRUD, + "GetWorkloadAccessToken": TierAutoCRUD, + "GetWorkloadAccessTokenForJWT": TierAutoCRUD, + "GetWorkloadAccessTokenForUserId": TierAutoCRUD, "IngestData": TierUnimplemented, "InvokeAgentRuntime": TierUnimplemented, "InvokeAgentRuntimeCommand": TierUnimplemented, "InvokeBrowser": TierUnimplemented, "InvokeCodeInterpreter": TierUnimplemented, "InvokeHarness": TierUnimplemented, - "ListABTests": TierUnimplemented, - "ListActors": TierUnimplemented, - "ListBatchEvaluations": TierUnimplemented, - "ListBrowserSessions": TierUnimplemented, - "ListCodeInterpreterSessions": TierUnimplemented, - "ListEvents": TierUnimplemented, - "ListMemoryExtractionJobs": TierUnimplemented, - "ListMemoryRecords": TierUnimplemented, - "ListPaymentInstruments": TierUnimplemented, - "ListPaymentSessions": TierUnimplemented, - "ListRecommendations": TierUnimplemented, - "ListSessions": TierUnimplemented, + "ListABTests": TierAutoCRUD, + "ListActors": TierAutoCRUD, + "ListBatchEvaluations": TierAutoCRUD, + "ListBrowserSessions": TierAutoCRUD, + "ListCodeInterpreterSessions": TierAutoCRUD, + "ListEvents": TierAutoCRUD, + "ListMemoryExtractionJobs": TierAutoCRUD, + "ListMemoryRecords": TierAutoCRUD, + "ListPaymentInstruments": TierAutoCRUD, + "ListPaymentSessions": TierAutoCRUD, + "ListRecommendations": TierAutoCRUD, + "ListSessions": TierAutoCRUD, "ProcessPayment": TierUnimplemented, "RetrieveMemoryRecords": TierUnimplemented, "SaveBrowserSessionProfile": TierUnimplemented, @@ -991,248 +1001,248 @@ var Services = map[string]Service{ "StopBrowserSession": TierUnimplemented, "StopCodeInterpreterSession": TierUnimplemented, "StopRuntimeSession": TierUnimplemented, - "UpdateABTest": TierUnimplemented, - "UpdateBrowserStream": TierUnimplemented, + "UpdateABTest": TierAutoCRUD, + "UpdateBrowserStream": TierAutoCRUD, }}, - "bedrockagentcorecontrol": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "bedrockagentcorecontrol": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AddDatasetExamples": TierUnimplemented, "BatchPutGatewayRateLimits": TierUnimplemented, - "CreateAgentRuntime": TierUnimplemented, - "CreateAgentRuntimeEndpoint": TierUnimplemented, - "CreateApiKeyCredentialProvider": TierUnimplemented, - "CreateBrowser": TierUnimplemented, - "CreateBrowserProfile": TierUnimplemented, - "CreateCapacityProvider": TierUnimplemented, - "CreateCodeInterpreter": TierUnimplemented, - "CreateConfigurationBundle": TierUnimplemented, - "CreateConsentPortal": TierUnimplemented, - "CreateDataset": TierUnimplemented, - "CreateDatasetVersion": TierUnimplemented, - "CreateEvaluator": TierUnimplemented, - "CreateGateway": TierUnimplemented, - "CreateGatewayRateLimit": TierUnimplemented, - "CreateGatewayRule": TierUnimplemented, - "CreateGatewayTarget": TierUnimplemented, - "CreateHarness": TierUnimplemented, - "CreateHarnessEndpoint": TierUnimplemented, - "CreateMemory": TierUnimplemented, - "CreateOauth2CredentialProvider": TierUnimplemented, - "CreateOnlineEvaluationConfig": TierUnimplemented, - "CreatePaymentConnector": TierUnimplemented, - "CreatePaymentCredentialProvider": TierUnimplemented, - "CreatePaymentManager": TierUnimplemented, - "CreatePolicy": TierUnimplemented, - "CreatePolicyEngine": TierUnimplemented, - "CreateRegistry": TierUnimplemented, - "CreateRegistryRecord": TierUnimplemented, - "CreateWorkloadIdentity": TierUnimplemented, - "DeleteAgentRuntime": TierUnimplemented, - "DeleteAgentRuntimeEndpoint": TierUnimplemented, - "DeleteApiKeyCredentialProvider": TierUnimplemented, - "DeleteBrowser": TierUnimplemented, - "DeleteBrowserProfile": TierUnimplemented, - "DeleteCapacityProvider": TierUnimplemented, - "DeleteCodeInterpreter": TierUnimplemented, - "DeleteConfigurationBundle": TierUnimplemented, - "DeleteConsentPortal": TierUnimplemented, - "DeleteDataset": TierUnimplemented, - "DeleteDatasetExamples": TierUnimplemented, - "DeleteEvaluator": TierUnimplemented, - "DeleteGateway": TierUnimplemented, - "DeleteGatewayRateLimit": TierUnimplemented, - "DeleteGatewayRule": TierUnimplemented, - "DeleteGatewayTarget": TierUnimplemented, - "DeleteHarness": TierUnimplemented, - "DeleteHarnessEndpoint": TierUnimplemented, - "DeleteMemory": TierUnimplemented, - "DeleteOauth2CredentialProvider": TierUnimplemented, - "DeleteOnlineEvaluationConfig": TierUnimplemented, - "DeletePaymentConnector": TierUnimplemented, - "DeletePaymentCredentialProvider": TierUnimplemented, - "DeletePaymentManager": TierUnimplemented, - "DeletePolicy": TierUnimplemented, - "DeletePolicyEngine": TierUnimplemented, - "DeleteRegistry": TierUnimplemented, - "DeleteRegistryRecord": TierUnimplemented, - "DeleteResourcePolicy": TierUnimplemented, - "DeleteWorkloadIdentity": TierUnimplemented, - "GetAgentRuntime": TierUnimplemented, - "GetAgentRuntimeEndpoint": TierUnimplemented, - "GetApiKeyCredentialProvider": TierUnimplemented, - "GetBrowser": TierUnimplemented, - "GetBrowserProfile": TierUnimplemented, - "GetCapacityProvider": TierUnimplemented, - "GetCodeInterpreter": TierUnimplemented, - "GetConfigurationBundle": TierUnimplemented, - "GetConfigurationBundleVersion": TierUnimplemented, - "GetConsentPortal": TierUnimplemented, - "GetDataset": TierUnimplemented, - "GetEvaluator": TierUnimplemented, - "GetGateway": TierUnimplemented, - "GetGatewayRateLimit": TierUnimplemented, - "GetGatewayRule": TierUnimplemented, - "GetGatewayTarget": TierUnimplemented, - "GetHarness": TierUnimplemented, - "GetHarnessEndpoint": TierUnimplemented, - "GetMemory": TierUnimplemented, - "GetOauth2CredentialProvider": TierUnimplemented, - "GetOnlineEvaluationConfig": TierUnimplemented, - "GetPaymentConnector": TierUnimplemented, - "GetPaymentCredentialProvider": TierUnimplemented, - "GetPaymentManager": TierUnimplemented, - "GetPolicy": TierUnimplemented, - "GetPolicyEngine": TierUnimplemented, - "GetPolicyEngineSummary": TierUnimplemented, - "GetPolicyGeneration": TierUnimplemented, - "GetPolicyGenerationSummary": TierUnimplemented, - "GetPolicySummary": TierUnimplemented, - "GetRegistry": TierUnimplemented, - "GetRegistryRecord": TierUnimplemented, - "GetResourcePolicy": TierUnimplemented, - "GetTokenVault": TierUnimplemented, - "GetWorkloadIdentity": TierUnimplemented, - "ListAgentRuntimeEndpoints": TierUnimplemented, - "ListAgentRuntimeVersions": TierUnimplemented, - "ListAgentRuntimeVersionsByCapacityProvider": TierUnimplemented, - "ListAgentRuntimes": TierUnimplemented, - "ListApiKeyCredentialProviders": TierUnimplemented, - "ListBrowserProfiles": TierUnimplemented, - "ListBrowsers": TierUnimplemented, - "ListCapacityProviders": TierUnimplemented, - "ListCodeInterpreters": TierUnimplemented, - "ListConfigurationBundleVersions": TierUnimplemented, - "ListConfigurationBundles": TierUnimplemented, - "ListConsentPortals": TierUnimplemented, - "ListDatasetExamples": TierUnimplemented, - "ListDatasetVersions": TierUnimplemented, - "ListDatasets": TierUnimplemented, - "ListEvaluators": TierUnimplemented, - "ListGatewayRateLimits": TierUnimplemented, - "ListGatewayRules": TierUnimplemented, - "ListGatewayTargets": TierUnimplemented, - "ListGateways": TierUnimplemented, - "ListHarnessEndpoints": TierUnimplemented, - "ListHarnessVersions": TierUnimplemented, - "ListHarnesses": TierUnimplemented, - "ListMemories": TierUnimplemented, - "ListOauth2CredentialProviders": TierUnimplemented, - "ListOnlineEvaluationConfigs": TierUnimplemented, - "ListPaymentConnectors": TierUnimplemented, - "ListPaymentCredentialProviders": TierUnimplemented, - "ListPaymentManagers": TierUnimplemented, - "ListPolicies": TierUnimplemented, - "ListPolicyEngineSummaries": TierUnimplemented, - "ListPolicyEngines": TierUnimplemented, - "ListPolicyGenerationAssets": TierUnimplemented, - "ListPolicyGenerationSummaries": TierUnimplemented, - "ListPolicyGenerations": TierUnimplemented, - "ListPolicySummaries": TierUnimplemented, - "ListRegistries": TierUnimplemented, - "ListRegistryRecords": TierUnimplemented, - "ListTagsForResource": TierUnimplemented, - "ListWorkloadIdentities": TierUnimplemented, - "PutResourcePolicy": TierUnimplemented, + "CreateAgentRuntime": TierAutoCRUD, + "CreateAgentRuntimeEndpoint": TierAutoCRUD, + "CreateApiKeyCredentialProvider": TierAutoCRUD, + "CreateBrowser": TierAutoCRUD, + "CreateBrowserProfile": TierAutoCRUD, + "CreateCapacityProvider": TierAutoCRUD, + "CreateCodeInterpreter": TierAutoCRUD, + "CreateConfigurationBundle": TierAutoCRUD, + "CreateConsentPortal": TierAutoCRUD, + "CreateDataset": TierAutoCRUD, + "CreateDatasetVersion": TierAutoCRUD, + "CreateEvaluator": TierAutoCRUD, + "CreateGateway": TierAutoCRUD, + "CreateGatewayRateLimit": TierAutoCRUD, + "CreateGatewayRule": TierAutoCRUD, + "CreateGatewayTarget": TierAutoCRUD, + "CreateHarness": TierAutoCRUD, + "CreateHarnessEndpoint": TierAutoCRUD, + "CreateMemory": TierAutoCRUD, + "CreateOauth2CredentialProvider": TierAutoCRUD, + "CreateOnlineEvaluationConfig": TierAutoCRUD, + "CreatePaymentConnector": TierAutoCRUD, + "CreatePaymentCredentialProvider": TierAutoCRUD, + "CreatePaymentManager": TierAutoCRUD, + "CreatePolicy": TierAutoCRUD, + "CreatePolicyEngine": TierAutoCRUD, + "CreateRegistry": TierAutoCRUD, + "CreateRegistryRecord": TierAutoCRUD, + "CreateWorkloadIdentity": TierAutoCRUD, + "DeleteAgentRuntime": TierAutoCRUD, + "DeleteAgentRuntimeEndpoint": TierAutoCRUD, + "DeleteApiKeyCredentialProvider": TierAutoCRUD, + "DeleteBrowser": TierAutoCRUD, + "DeleteBrowserProfile": TierAutoCRUD, + "DeleteCapacityProvider": TierAutoCRUD, + "DeleteCodeInterpreter": TierAutoCRUD, + "DeleteConfigurationBundle": TierAutoCRUD, + "DeleteConsentPortal": TierAutoCRUD, + "DeleteDataset": TierAutoCRUD, + "DeleteDatasetExamples": TierAutoCRUD, + "DeleteEvaluator": TierAutoCRUD, + "DeleteGateway": TierAutoCRUD, + "DeleteGatewayRateLimit": TierAutoCRUD, + "DeleteGatewayRule": TierAutoCRUD, + "DeleteGatewayTarget": TierAutoCRUD, + "DeleteHarness": TierAutoCRUD, + "DeleteHarnessEndpoint": TierAutoCRUD, + "DeleteMemory": TierAutoCRUD, + "DeleteOauth2CredentialProvider": TierAutoCRUD, + "DeleteOnlineEvaluationConfig": TierAutoCRUD, + "DeletePaymentConnector": TierAutoCRUD, + "DeletePaymentCredentialProvider": TierAutoCRUD, + "DeletePaymentManager": TierAutoCRUD, + "DeletePolicy": TierAutoCRUD, + "DeletePolicyEngine": TierAutoCRUD, + "DeleteRegistry": TierAutoCRUD, + "DeleteRegistryRecord": TierAutoCRUD, + "DeleteResourcePolicy": TierAutoCRUD, + "DeleteWorkloadIdentity": TierAutoCRUD, + "GetAgentRuntime": TierAutoCRUD, + "GetAgentRuntimeEndpoint": TierAutoCRUD, + "GetApiKeyCredentialProvider": TierAutoCRUD, + "GetBrowser": TierAutoCRUD, + "GetBrowserProfile": TierAutoCRUD, + "GetCapacityProvider": TierAutoCRUD, + "GetCodeInterpreter": TierAutoCRUD, + "GetConfigurationBundle": TierAutoCRUD, + "GetConfigurationBundleVersion": TierAutoCRUD, + "GetConsentPortal": TierAutoCRUD, + "GetDataset": TierAutoCRUD, + "GetEvaluator": TierAutoCRUD, + "GetGateway": TierAutoCRUD, + "GetGatewayRateLimit": TierAutoCRUD, + "GetGatewayRule": TierAutoCRUD, + "GetGatewayTarget": TierAutoCRUD, + "GetHarness": TierAutoCRUD, + "GetHarnessEndpoint": TierAutoCRUD, + "GetMemory": TierAutoCRUD, + "GetOauth2CredentialProvider": TierAutoCRUD, + "GetOnlineEvaluationConfig": TierAutoCRUD, + "GetPaymentConnector": TierAutoCRUD, + "GetPaymentCredentialProvider": TierAutoCRUD, + "GetPaymentManager": TierAutoCRUD, + "GetPolicy": TierAutoCRUD, + "GetPolicyEngine": TierAutoCRUD, + "GetPolicyEngineSummary": TierAutoCRUD, + "GetPolicyGeneration": TierAutoCRUD, + "GetPolicyGenerationSummary": TierAutoCRUD, + "GetPolicySummary": TierAutoCRUD, + "GetRegistry": TierAutoCRUD, + "GetRegistryRecord": TierAutoCRUD, + "GetResourcePolicy": TierAutoCRUD, + "GetTokenVault": TierAutoCRUD, + "GetWorkloadIdentity": TierAutoCRUD, + "ListAgentRuntimeEndpoints": TierAutoCRUD, + "ListAgentRuntimeVersions": TierAutoCRUD, + "ListAgentRuntimeVersionsByCapacityProvider": TierAutoCRUD, + "ListAgentRuntimes": TierAutoCRUD, + "ListApiKeyCredentialProviders": TierAutoCRUD, + "ListBrowserProfiles": TierAutoCRUD, + "ListBrowsers": TierAutoCRUD, + "ListCapacityProviders": TierAutoCRUD, + "ListCodeInterpreters": TierAutoCRUD, + "ListConfigurationBundleVersions": TierAutoCRUD, + "ListConfigurationBundles": TierAutoCRUD, + "ListConsentPortals": TierAutoCRUD, + "ListDatasetExamples": TierAutoCRUD, + "ListDatasetVersions": TierAutoCRUD, + "ListDatasets": TierAutoCRUD, + "ListEvaluators": TierAutoCRUD, + "ListGatewayRateLimits": TierAutoCRUD, + "ListGatewayRules": TierAutoCRUD, + "ListGatewayTargets": TierAutoCRUD, + "ListGateways": TierAutoCRUD, + "ListHarnessEndpoints": TierAutoCRUD, + "ListHarnessVersions": TierAutoCRUD, + "ListHarnesses": TierAutoCRUD, + "ListMemories": TierAutoCRUD, + "ListOauth2CredentialProviders": TierAutoCRUD, + "ListOnlineEvaluationConfigs": TierAutoCRUD, + "ListPaymentConnectors": TierAutoCRUD, + "ListPaymentCredentialProviders": TierAutoCRUD, + "ListPaymentManagers": TierAutoCRUD, + "ListPolicies": TierAutoCRUD, + "ListPolicyEngineSummaries": TierAutoCRUD, + "ListPolicyEngines": TierAutoCRUD, + "ListPolicyGenerationAssets": TierAutoCRUD, + "ListPolicyGenerationSummaries": TierAutoCRUD, + "ListPolicyGenerations": TierAutoCRUD, + "ListPolicySummaries": TierAutoCRUD, + "ListRegistries": TierAutoCRUD, + "ListRegistryRecords": TierAutoCRUD, + "ListTagsForResource": TierAutoCRUD, + "ListWorkloadIdentities": TierAutoCRUD, + "PutResourcePolicy": TierAutoCRUD, "SetTokenVaultCMK": TierUnimplemented, "StartPolicyGeneration": TierUnimplemented, "SubmitRegistryRecordForApproval": TierUnimplemented, "SynchronizeGatewayTargets": TierUnimplemented, - "TagResource": TierUnimplemented, - "UntagResource": TierUnimplemented, - "UpdateAgentRuntime": TierUnimplemented, - "UpdateAgentRuntimeEndpoint": TierUnimplemented, - "UpdateApiKeyCredentialProvider": TierUnimplemented, - "UpdateCapacityProvider": TierUnimplemented, - "UpdateConfigurationBundle": TierUnimplemented, - "UpdateConsentPortal": TierUnimplemented, - "UpdateDataset": TierUnimplemented, - "UpdateDatasetExamples": TierUnimplemented, - "UpdateEvaluator": TierUnimplemented, - "UpdateGateway": TierUnimplemented, - "UpdateGatewayRateLimit": TierUnimplemented, - "UpdateGatewayRule": TierUnimplemented, - "UpdateGatewayTarget": TierUnimplemented, - "UpdateHarness": TierUnimplemented, - "UpdateHarnessEndpoint": TierUnimplemented, - "UpdateMemory": TierUnimplemented, - "UpdateOauth2CredentialProvider": TierUnimplemented, - "UpdateOnlineEvaluationConfig": TierUnimplemented, - "UpdatePaymentConnector": TierUnimplemented, - "UpdatePaymentCredentialProvider": TierUnimplemented, - "UpdatePaymentManager": TierUnimplemented, - "UpdatePolicy": TierUnimplemented, - "UpdatePolicyEngine": TierUnimplemented, - "UpdateRegistry": TierUnimplemented, - "UpdateRegistryRecord": TierUnimplemented, - "UpdateRegistryRecordStatus": TierUnimplemented, - "UpdateWorkloadIdentity": TierUnimplemented, - }}, - "bedrockagentruntime": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "TagResource": TierAutoCRUD, + "UntagResource": TierAutoCRUD, + "UpdateAgentRuntime": TierAutoCRUD, + "UpdateAgentRuntimeEndpoint": TierAutoCRUD, + "UpdateApiKeyCredentialProvider": TierAutoCRUD, + "UpdateCapacityProvider": TierAutoCRUD, + "UpdateConfigurationBundle": TierAutoCRUD, + "UpdateConsentPortal": TierAutoCRUD, + "UpdateDataset": TierAutoCRUD, + "UpdateDatasetExamples": TierAutoCRUD, + "UpdateEvaluator": TierAutoCRUD, + "UpdateGateway": TierAutoCRUD, + "UpdateGatewayRateLimit": TierAutoCRUD, + "UpdateGatewayRule": TierAutoCRUD, + "UpdateGatewayTarget": TierAutoCRUD, + "UpdateHarness": TierAutoCRUD, + "UpdateHarnessEndpoint": TierAutoCRUD, + "UpdateMemory": TierAutoCRUD, + "UpdateOauth2CredentialProvider": TierAutoCRUD, + "UpdateOnlineEvaluationConfig": TierAutoCRUD, + "UpdatePaymentConnector": TierAutoCRUD, + "UpdatePaymentCredentialProvider": TierAutoCRUD, + "UpdatePaymentManager": TierAutoCRUD, + "UpdatePolicy": TierAutoCRUD, + "UpdatePolicyEngine": TierAutoCRUD, + "UpdateRegistry": TierAutoCRUD, + "UpdateRegistryRecord": TierAutoCRUD, + "UpdateRegistryRecordStatus": TierAutoCRUD, + "UpdateWorkloadIdentity": TierAutoCRUD, + }}, + "bedrockagentruntime": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AgenticRetrieveStream": TierUnimplemented, "CheckIngestedDocumentAcl": TierUnimplemented, - "CreateInvocation": TierUnimplemented, - "CreateSession": TierUnimplemented, - "DeleteAgentMemory": TierUnimplemented, - "DeleteSession": TierUnimplemented, + "CreateInvocation": TierAutoCRUD, + "CreateSession": TierAutoCRUD, + "DeleteAgentMemory": TierAutoCRUD, + "DeleteSession": TierAutoCRUD, "EndSession": TierUnimplemented, "GenerateQuery": TierUnimplemented, - "GetAgentMemory": TierUnimplemented, - "GetDocumentContent": TierUnimplemented, - "GetExecutionFlowSnapshot": TierUnimplemented, - "GetFlowExecution": TierUnimplemented, - "GetIngestedDocumentAcl": TierUnimplemented, - "GetInvocationStep": TierUnimplemented, - "GetSession": TierUnimplemented, + "GetAgentMemory": TierAutoCRUD, + "GetDocumentContent": TierAutoCRUD, + "GetExecutionFlowSnapshot": TierAutoCRUD, + "GetFlowExecution": TierAutoCRUD, + "GetIngestedDocumentAcl": TierAutoCRUD, + "GetInvocationStep": TierAutoCRUD, + "GetSession": TierAutoCRUD, "InvokeAgent": TierUnimplemented, "InvokeFlow": TierUnimplemented, "InvokeInlineAgent": TierUnimplemented, - "ListFlowExecutionEvents": TierUnimplemented, - "ListFlowExecutions": TierUnimplemented, - "ListInvocationSteps": TierUnimplemented, - "ListInvocations": TierUnimplemented, - "ListSessions": TierUnimplemented, - "ListTagsForResource": TierUnimplemented, + "ListFlowExecutionEvents": TierAutoCRUD, + "ListFlowExecutions": TierAutoCRUD, + "ListInvocationSteps": TierAutoCRUD, + "ListInvocations": TierAutoCRUD, + "ListSessions": TierAutoCRUD, + "ListTagsForResource": TierAutoCRUD, "OptimizePrompt": TierUnimplemented, - "PutInvocationStep": TierUnimplemented, + "PutInvocationStep": TierAutoCRUD, "Rerank": TierUnimplemented, "Retrieve": TierUnimplemented, "RetrieveAndGenerate": TierUnimplemented, "RetrieveAndGenerateStream": TierUnimplemented, "StartFlowExecution": TierUnimplemented, "StopFlowExecution": TierUnimplemented, - "TagResource": TierUnimplemented, - "UntagResource": TierUnimplemented, - "UpdateSession": TierUnimplemented, + "TagResource": TierAutoCRUD, + "UntagResource": TierAutoCRUD, + "UpdateSession": TierAutoCRUD, }}, - "bedrockdataautomation": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "bedrockdataautomation": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "CopyBlueprintStage": TierUnimplemented, - "CreateBlueprint": TierUnimplemented, - "CreateBlueprintVersion": TierUnimplemented, - "CreateDataAutomationLibrary": TierUnimplemented, - "CreateDataAutomationProject": TierUnimplemented, - "DeleteBlueprint": TierUnimplemented, - "DeleteDataAutomationLibrary": TierUnimplemented, - "DeleteDataAutomationProject": TierUnimplemented, - "GetBlueprint": TierUnimplemented, - "GetBlueprintOptimizationStatus": TierUnimplemented, - "GetDataAutomationLibrary": TierUnimplemented, - "GetDataAutomationLibraryEntity": TierUnimplemented, - "GetDataAutomationLibraryIngestionJob": TierUnimplemented, - "GetDataAutomationProject": TierUnimplemented, + "CreateBlueprint": TierAutoCRUD, + "CreateBlueprintVersion": TierAutoCRUD, + "CreateDataAutomationLibrary": TierAutoCRUD, + "CreateDataAutomationProject": TierAutoCRUD, + "DeleteBlueprint": TierAutoCRUD, + "DeleteDataAutomationLibrary": TierAutoCRUD, + "DeleteDataAutomationProject": TierAutoCRUD, + "GetBlueprint": TierAutoCRUD, + "GetBlueprintOptimizationStatus": TierAutoCRUD, + "GetDataAutomationLibrary": TierAutoCRUD, + "GetDataAutomationLibraryEntity": TierAutoCRUD, + "GetDataAutomationLibraryIngestionJob": TierAutoCRUD, + "GetDataAutomationProject": TierAutoCRUD, "InvokeBlueprintOptimizationAsync": TierUnimplemented, "InvokeDataAutomationLibraryIngestionJob": TierUnimplemented, - "ListBlueprints": TierUnimplemented, - "ListDataAutomationLibraries": TierUnimplemented, - "ListDataAutomationLibraryEntities": TierUnimplemented, - "ListDataAutomationLibraryIngestionJobs": TierUnimplemented, - "ListDataAutomationProjects": TierUnimplemented, - "ListTagsForResource": TierUnimplemented, - "TagResource": TierUnimplemented, - "UntagResource": TierUnimplemented, - "UpdateBlueprint": TierUnimplemented, - "UpdateDataAutomationLibrary": TierUnimplemented, - "UpdateDataAutomationProject": TierUnimplemented, - }}, - "bedrockdataautomationruntime": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "ListBlueprints": TierAutoCRUD, + "ListDataAutomationLibraries": TierAutoCRUD, + "ListDataAutomationLibraryEntities": TierAutoCRUD, + "ListDataAutomationLibraryIngestionJobs": TierAutoCRUD, + "ListDataAutomationProjects": TierAutoCRUD, + "ListTagsForResource": TierAutoCRUD, + "TagResource": TierAutoCRUD, + "UntagResource": TierAutoCRUD, + "UpdateBlueprint": TierAutoCRUD, + "UpdateDataAutomationLibrary": TierAutoCRUD, + "UpdateDataAutomationProject": TierAutoCRUD, + }}, + "bedrockdataautomationruntime": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "GetDataAutomationStatus": TierAutoCRUD, "InvokeDataAutomation": TierUnimplemented, "InvokeDataAutomationAsync": TierUnimplemented, @@ -1240,20 +1250,20 @@ var Services = map[string]Service{ "TagResource": TierAutoCRUD, "UntagResource": TierAutoCRUD, }}, - "bedrockruntime": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "bedrockruntime": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "ApplyGuardrail": TierUnimplemented, "Converse": TierUnimplemented, "ConverseStream": TierUnimplemented, "CountTokens": TierUnimplemented, - "GetAsyncInvoke": TierUnimplemented, + "GetAsyncInvoke": TierAutoCRUD, "InvokeGuardrailChecks": TierUnimplemented, "InvokeModel": TierUnimplemented, "InvokeModelWithBidirectionalStream": TierUnimplemented, "InvokeModelWithResponseStream": TierUnimplemented, - "ListAsyncInvokes": TierUnimplemented, + "ListAsyncInvokes": TierAutoCRUD, "StartAsyncInvoke": TierUnimplemented, }}, - "cloudcontrol": {Protocol: "", ModelBacked: false, Operations: map[string]Tier{ + "cloudcontrol": {Protocol: "", ModelBacked: false, EngineWired: false, Operations: map[string]Tier{ "BatchGetResources": TierHandVerified, "CancelResourceRequest": TierHandVerified, "CloneResource": TierHandVerified, @@ -1281,7 +1291,7 @@ var Services = map[string]Service{ "ValidateResource": TierHandVerified, "WaitForResource": TierHandVerified, }}, - "cloudformation": {Protocol: "query", ModelBacked: true, Operations: map[string]Tier{ + "cloudformation": {Protocol: "query", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "ActivateOrganizationsAccess": TierUnimplemented, "ActivateType": TierHandVerified, "BatchDescribeTypeConfigurations": TierHandVerified, @@ -1373,7 +1383,7 @@ var Services = map[string]Service{ "UpdateTerminationProtection": TierHandVerified, "ValidateTemplate": TierHandVerified, }}, - "cloudfront": {Protocol: "rest-xml", ModelBacked: true, Operations: map[string]Tier{ + "cloudfront": {Protocol: "rest-xml", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "AssociateAlias": TierUnimplemented, "AssociateDistributionTenantWebACL": TierUnimplemented, "AssociateDistributionWebACL": TierUnimplemented, @@ -1542,7 +1552,7 @@ var Services = map[string]Service{ "UpdateVpcOrigin": TierUnimplemented, "VerifyDnsConfiguration": TierUnimplemented, }}, - "cloudsearch": {Protocol: "query", ModelBacked: true, Operations: map[string]Tier{ + "cloudsearch": {Protocol: "query", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "BuildSuggesters": TierHandVerified, "CreateDomain": TierHandVerified, "DefineAnalysisScheme": TierHandVerified, @@ -1570,7 +1580,7 @@ var Services = map[string]Service{ "UpdateScalingParameters": TierHandVerified, "UpdateServiceAccessPolicies": TierHandVerified, }}, - "cloudtrail": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "cloudtrail": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AddTags": TierHandVerified, "CancelQuery": TierHandVerified, "CreateChannel": TierHandVerified, @@ -1632,7 +1642,7 @@ var Services = map[string]Service{ "UpdateEventDataStore": TierHandVerified, "UpdateTrail": TierHandVerified, }}, - "cloudwatch": {Protocol: "json-1.0", ModelBacked: true, Operations: map[string]Tier{ + "cloudwatch": {Protocol: "json-1.0", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "DeleteAlarmMuteRule": TierAutoCRUD, "DeleteAlarms": TierHandVerified, "DeleteAnomalyDetector": TierHandVerified, @@ -1680,7 +1690,7 @@ var Services = map[string]Service{ "TagResource": TierHandVerified, "UntagResource": TierHandVerified, }}, - "cloudwatchlogs": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "cloudwatchlogs": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AssociateKmsKey": TierUnimplemented, "AssociateSourceToS3TableIntegration": TierUnimplemented, "CancelExportTask": TierUnimplemented, @@ -1795,7 +1805,7 @@ var Services = map[string]Service{ "UpdateLookupTable": TierAutoCRUD, "UpdateScheduledQuery": TierAutoCRUD, }}, - "codeartifact": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "codeartifact": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "AssociateExternalConnection": TierHandVerified, "CopyPackageVersions": TierHandVerified, "CreateDomain": TierHandVerified, @@ -1845,7 +1855,7 @@ var Services = map[string]Service{ "UpdatePackageVersionsStatus": TierHandVerified, "UpdateRepository": TierHandVerified, }}, - "codebuild": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "codebuild": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "BatchDeleteBuilds": TierHandVerified, "BatchGetBuildBatches": TierAutoCRUD, "BatchGetBuilds": TierHandVerified, @@ -1909,7 +1919,7 @@ var Services = map[string]Service{ "UpdateReportGroup": TierHandVerified, "UpdateWebhook": TierAutoCRUD, }}, - "codecommit": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "codecommit": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AssociateApprovalRuleTemplateWithRepository": TierHandVerified, "BatchAssociateApprovalRuleTemplateWithRepositories": TierHandVerified, "BatchDescribeMergeConflicts": TierHandVerified, @@ -1990,7 +2000,7 @@ var Services = map[string]Service{ "UpdateRepositoryEncryptionKey": TierHandVerified, "UpdateRepositoryName": TierHandVerified, }}, - "codeconnections": {Protocol: "", ModelBacked: false, Operations: map[string]Tier{ + "codeconnections": {Protocol: "", ModelBacked: false, EngineWired: false, Operations: map[string]Tier{ "CreateConnection": TierHandVerified, "CreateHost": TierHandVerified, "CreateRepositoryLink": TierHandVerified, @@ -2027,7 +2037,7 @@ var Services = map[string]Service{ "UpdateSyncBlocker": TierHandVerified, "UpdateSyncConfiguration": TierHandVerified, }}, - "codedeploy": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "codedeploy": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AddTagsToOnPremisesInstances": TierUnimplemented, "BatchGetApplicationRevisions": TierAutoCRUD, "BatchGetApplications": TierHandVerified, @@ -2076,63 +2086,63 @@ var Services = map[string]Service{ "UpdateApplication": TierHandVerified, "UpdateDeploymentGroup": TierHandVerified, }}, - "codeguruprofiler": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "codeguruprofiler": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AddNotificationChannels": TierUnimplemented, - "BatchGetFrameMetricData": TierUnimplemented, + "BatchGetFrameMetricData": TierAutoCRUD, "ConfigureAgent": TierUnimplemented, - "CreateProfilingGroup": TierUnimplemented, - "DeleteProfilingGroup": TierUnimplemented, - "DescribeProfilingGroup": TierUnimplemented, - "GetFindingsReportAccountSummary": TierUnimplemented, - "GetNotificationConfiguration": TierUnimplemented, - "GetPolicy": TierUnimplemented, - "GetProfile": TierUnimplemented, - "GetRecommendations": TierUnimplemented, - "ListFindingsReports": TierUnimplemented, - "ListProfileTimes": TierUnimplemented, - "ListProfilingGroups": TierUnimplemented, - "ListTagsForResource": TierUnimplemented, + "CreateProfilingGroup": TierAutoCRUD, + "DeleteProfilingGroup": TierAutoCRUD, + "DescribeProfilingGroup": TierAutoCRUD, + "GetFindingsReportAccountSummary": TierAutoCRUD, + "GetNotificationConfiguration": TierAutoCRUD, + "GetPolicy": TierAutoCRUD, + "GetProfile": TierAutoCRUD, + "GetRecommendations": TierAutoCRUD, + "ListFindingsReports": TierAutoCRUD, + "ListProfileTimes": TierAutoCRUD, + "ListProfilingGroups": TierAutoCRUD, + "ListTagsForResource": TierAutoCRUD, "PostAgentProfile": TierUnimplemented, - "PutPermission": TierUnimplemented, + "PutPermission": TierAutoCRUD, "RemoveNotificationChannel": TierUnimplemented, "RemovePermission": TierUnimplemented, "SubmitFeedback": TierUnimplemented, - "TagResource": TierUnimplemented, - "UntagResource": TierUnimplemented, - "UpdateProfilingGroup": TierUnimplemented, + "TagResource": TierAutoCRUD, + "UntagResource": TierAutoCRUD, + "UpdateProfilingGroup": TierAutoCRUD, }}, - "codegurureviewer": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "codegurureviewer": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AssociateRepository": TierUnimplemented, - "CreateCodeReview": TierUnimplemented, - "DescribeCodeReview": TierUnimplemented, - "DescribeRecommendationFeedback": TierUnimplemented, - "DescribeRepositoryAssociation": TierUnimplemented, + "CreateCodeReview": TierAutoCRUD, + "DescribeCodeReview": TierAutoCRUD, + "DescribeRecommendationFeedback": TierAutoCRUD, + "DescribeRepositoryAssociation": TierAutoCRUD, "DisassociateRepository": TierUnimplemented, - "ListCodeReviews": TierUnimplemented, - "ListRecommendationFeedback": TierUnimplemented, - "ListRecommendations": TierUnimplemented, - "ListRepositoryAssociations": TierUnimplemented, - "ListTagsForResource": TierUnimplemented, - "PutRecommendationFeedback": TierUnimplemented, - "TagResource": TierUnimplemented, - "UntagResource": TierUnimplemented, - }}, - "codegurusecurity": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ - "BatchGetFindings": TierUnimplemented, - "CreateScan": TierUnimplemented, - "CreateUploadUrl": TierUnimplemented, - "GetAccountConfiguration": TierUnimplemented, - "GetFindings": TierUnimplemented, - "GetMetricsSummary": TierUnimplemented, - "GetScan": TierUnimplemented, - "ListFindingsMetrics": TierUnimplemented, - "ListScans": TierUnimplemented, - "ListTagsForResource": TierUnimplemented, - "TagResource": TierUnimplemented, - "UntagResource": TierUnimplemented, - "UpdateAccountConfiguration": TierUnimplemented, - }}, - "codepipeline": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "ListCodeReviews": TierAutoCRUD, + "ListRecommendationFeedback": TierAutoCRUD, + "ListRecommendations": TierAutoCRUD, + "ListRepositoryAssociations": TierAutoCRUD, + "ListTagsForResource": TierAutoCRUD, + "PutRecommendationFeedback": TierAutoCRUD, + "TagResource": TierAutoCRUD, + "UntagResource": TierAutoCRUD, + }}, + "codegurusecurity": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ + "BatchGetFindings": TierAutoCRUD, + "CreateScan": TierAutoCRUD, + "CreateUploadUrl": TierAutoCRUD, + "GetAccountConfiguration": TierAutoCRUD, + "GetFindings": TierAutoCRUD, + "GetMetricsSummary": TierAutoCRUD, + "GetScan": TierAutoCRUD, + "ListFindingsMetrics": TierAutoCRUD, + "ListScans": TierAutoCRUD, + "ListTagsForResource": TierAutoCRUD, + "TagResource": TierAutoCRUD, + "UntagResource": TierAutoCRUD, + "UpdateAccountConfiguration": TierAutoCRUD, + }}, + "codepipeline": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AcknowledgeJob": TierHandVerified, "AcknowledgeThirdPartyJob": TierHandVerified, "CreateCustomActionType": TierHandVerified, @@ -2181,7 +2191,7 @@ var Services = map[string]Service{ "UpdatePipeline": TierHandVerified, "UpdatePipelineSettings": TierHandVerified, }}, - "cognitoidentity": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "cognitoidentity": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "CreateIdentityPool": TierHandVerified, "DeleteIdentities": TierHandVerified, "DeleteIdentityPool": TierHandVerified, @@ -2206,7 +2216,7 @@ var Services = map[string]Service{ "UntagResource": TierHandVerified, "UpdateIdentityPool": TierHandVerified, }}, - "cognitoidentityprovider": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "cognitoidentityprovider": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AddCustomAttributes": TierUnimplemented, "AddUserPoolClientSecret": TierUnimplemented, "AdminAddUserToGroup": TierHandVerified, @@ -2330,7 +2340,7 @@ var Services = map[string]Service{ "VerifySoftwareToken": TierUnimplemented, "VerifyUserAttribute": TierUnimplemented, }}, - "comprehend": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "comprehend": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "BatchDetectDominantLanguage": TierUnimplemented, "BatchDetectEntities": TierUnimplemented, "BatchDetectKeyPhrases": TierUnimplemented, @@ -2417,7 +2427,7 @@ var Services = map[string]Service{ "UpdateEndpoint": TierAutoCRUD, "UpdateFlywheel": TierAutoCRUD, }}, - "comprehendmedical": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "comprehendmedical": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "DescribeEntitiesDetectionV2Job": TierAutoCRUD, "DescribeICD10CMInferenceJob": TierAutoCRUD, "DescribePHIDetectionJob": TierAutoCRUD, @@ -2445,7 +2455,7 @@ var Services = map[string]Service{ "StopRxNormInferenceJob": TierUnimplemented, "StopSNOMEDCTInferenceJob": TierUnimplemented, }}, - "configservice": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "configservice": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AssociateResourceTypes": TierUnimplemented, "BatchGetAggregateResourceConfig": TierAutoCRUD, "BatchGetResourceConfig": TierAutoCRUD, @@ -2544,7 +2554,7 @@ var Services = map[string]Service{ "TagResource": TierHandVerified, "UntagResource": TierHandVerified, }}, - "costexplorer": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "costexplorer": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "CreateAnomalyMonitor": TierHandVerified, "CreateAnomalySubscription": TierHandVerified, "CreateCostCategoryDefinition": TierHandVerified, @@ -2593,40 +2603,40 @@ var Services = map[string]Service{ "UpdateCostAllocationTagsStatus": TierHandVerified, "UpdateCostCategoryDefinition": TierHandVerified, }}, - "devopsguru": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "devopsguru": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AddNotificationChannel": TierUnimplemented, - "DeleteInsight": TierUnimplemented, - "DescribeAccountHealth": TierUnimplemented, - "DescribeAccountOverview": TierUnimplemented, - "DescribeAnomaly": TierUnimplemented, - "DescribeEventSourcesConfig": TierUnimplemented, - "DescribeFeedback": TierUnimplemented, - "DescribeInsight": TierUnimplemented, - "DescribeOrganizationHealth": TierUnimplemented, - "DescribeOrganizationOverview": TierUnimplemented, - "DescribeOrganizationResourceCollectionHealth": TierUnimplemented, - "DescribeResourceCollectionHealth": TierUnimplemented, - "DescribeServiceIntegration": TierUnimplemented, - "GetCostEstimation": TierUnimplemented, - "GetResourceCollection": TierUnimplemented, - "ListAnomaliesForInsight": TierUnimplemented, - "ListAnomalousLogGroups": TierUnimplemented, - "ListEvents": TierUnimplemented, - "ListInsights": TierUnimplemented, - "ListMonitoredResources": TierUnimplemented, - "ListNotificationChannels": TierUnimplemented, - "ListOrganizationInsights": TierUnimplemented, - "ListRecommendations": TierUnimplemented, - "PutFeedback": TierUnimplemented, + "DeleteInsight": TierAutoCRUD, + "DescribeAccountHealth": TierAutoCRUD, + "DescribeAccountOverview": TierAutoCRUD, + "DescribeAnomaly": TierAutoCRUD, + "DescribeEventSourcesConfig": TierAutoCRUD, + "DescribeFeedback": TierAutoCRUD, + "DescribeInsight": TierAutoCRUD, + "DescribeOrganizationHealth": TierAutoCRUD, + "DescribeOrganizationOverview": TierAutoCRUD, + "DescribeOrganizationResourceCollectionHealth": TierAutoCRUD, + "DescribeResourceCollectionHealth": TierAutoCRUD, + "DescribeServiceIntegration": TierAutoCRUD, + "GetCostEstimation": TierAutoCRUD, + "GetResourceCollection": TierAutoCRUD, + "ListAnomaliesForInsight": TierAutoCRUD, + "ListAnomalousLogGroups": TierAutoCRUD, + "ListEvents": TierAutoCRUD, + "ListInsights": TierAutoCRUD, + "ListMonitoredResources": TierAutoCRUD, + "ListNotificationChannels": TierAutoCRUD, + "ListOrganizationInsights": TierAutoCRUD, + "ListRecommendations": TierAutoCRUD, + "PutFeedback": TierAutoCRUD, "RemoveNotificationChannel": TierUnimplemented, "SearchInsights": TierUnimplemented, "SearchOrganizationInsights": TierUnimplemented, "StartCostEstimation": TierUnimplemented, - "UpdateEventSourcesConfig": TierUnimplemented, - "UpdateResourceCollection": TierUnimplemented, - "UpdateServiceIntegration": TierUnimplemented, + "UpdateEventSourcesConfig": TierAutoCRUD, + "UpdateResourceCollection": TierAutoCRUD, + "UpdateServiceIntegration": TierAutoCRUD, }}, - "dms": {Protocol: "", ModelBacked: false, Operations: map[string]Tier{ + "dms": {Protocol: "", ModelBacked: false, EngineWired: false, Operations: map[string]Tier{ "AddTagsToResource": TierHandVerified, "CreateEndpoint": TierHandVerified, "CreateEventSubscription": TierHandVerified, @@ -2661,7 +2671,7 @@ var Services = map[string]Service{ "StopReplicationTask": TierHandVerified, "TestConnection": TierHandVerified, }}, - "docdb": {Protocol: "query", ModelBacked: true, Operations: map[string]Tier{ + "docdb": {Protocol: "query", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "AddSourceIdentifierToSubscription": TierHandVerified, "AddTagsToResource": TierHandVerified, "ApplyPendingMaintenanceAction": TierHandVerified, @@ -2718,7 +2728,7 @@ var Services = map[string]Service{ "StopDBCluster": TierHandVerified, "SwitchoverGlobalCluster": TierHandVerified, }}, - "dynamodb": {Protocol: "json-1.0", ModelBacked: true, Operations: map[string]Tier{ + "dynamodb": {Protocol: "json-1.0", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "BatchExecuteStatement": TierUnimplemented, "BatchGetItem": TierHandVerified, "BatchWriteItem": TierHandVerified, @@ -2777,7 +2787,7 @@ var Services = map[string]Service{ "UpdateTableReplicaAutoScaling": TierAutoCRUD, "UpdateTimeToLive": TierHandVerified, }}, - "dynamodbstreams": {Protocol: "json-1.0", ModelBacked: true, Operations: map[string]Tier{ + "dynamodbstreams": {Protocol: "json-1.0", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AddTagsToStream": TierHandVerified, "DescribeContinuousBackups": TierHandVerified, "DescribeLimits": TierHandVerified, @@ -2801,7 +2811,7 @@ var Services = map[string]Service{ "SplitShard": TierHandVerified, "UpdateStream": TierHandVerified, }}, - "ebs": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "ebs": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "CompleteSnapshot": TierHandVerified, "CopySnapshot": TierHandVerified, "DescribeVolumesModifications": TierHandVerified, @@ -2815,7 +2825,7 @@ var Services = map[string]Service{ "RestoreSnapshotTier": TierHandVerified, "StartSnapshot": TierHandVerified, }}, - "ec2": {Protocol: "", ModelBacked: true, Operations: map[string]Tier{ + "ec2": {Protocol: "", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "AcceptAddressTransfer": TierUnimplemented, "AcceptCapacityReservationBillingOwnership": TierUnimplemented, "AcceptReservedInstancesExchangeQuote": TierUnimplemented, @@ -3573,7 +3583,7 @@ var Services = map[string]Service{ "UpdateSecurityGroupRuleDescriptionsIngress": TierUnimplemented, "WithdrawByoipCidr": TierUnimplemented, }}, - "ecr": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "ecr": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "BatchCheckLayerAvailability": TierHandVerified, "BatchDeleteImage": TierHandVerified, "BatchGetImage": TierHandVerified, @@ -3633,7 +3643,7 @@ var Services = map[string]Service{ "UploadLayerPart": TierHandVerified, "ValidatePullThroughCacheRule": TierUnimplemented, }}, - "ecs": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "ecs": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "CreateCapacityProvider": TierHandVerified, "CreateCluster": TierHandVerified, "CreateDaemon": TierAutoCRUD, @@ -3717,7 +3727,7 @@ var Services = map[string]Service{ "UpdateTaskProtection": TierHandVerified, "UpdateTaskSet": TierHandVerified, }}, - "efs": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "efs": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "CreateAccessPoint": TierHandVerified, "CreateFileSystem": TierHandVerified, "CreateMountTarget": TierHandVerified, @@ -3750,7 +3760,7 @@ var Services = map[string]Service{ "UpdateFileSystem": TierHandVerified, "UpdateFileSystemProtection": TierUnimplemented, }}, - "eks": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "eks": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "AssociateAccessPolicy": TierHandVerified, "AssociateEncryptionConfig": TierHandVerified, "AssociateIdentityProviderConfig": TierHandVerified, @@ -3816,7 +3826,7 @@ var Services = map[string]Service{ "UpdateNodegroupVersion": TierHandVerified, "UpdatePodIdentityAssociation": TierHandVerified, }}, - "elasticache": {Protocol: "query", ModelBacked: true, Operations: map[string]Tier{ + "elasticache": {Protocol: "query", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "AddTagsToResource": TierHandVerified, "AuthorizeCacheSecurityGroupIngress": TierHandVerified, "BatchApplyUpdateAction": TierUnimplemented, @@ -3893,7 +3903,7 @@ var Services = map[string]Service{ "TestFailover": TierHandVerified, "TestMigration": TierUnimplemented, }}, - "elasticbeanstalk": {Protocol: "query", ModelBacked: true, Operations: map[string]Tier{ + "elasticbeanstalk": {Protocol: "query", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "AbortEnvironmentUpdate": TierHandVerified, "ApplyEnvironmentManagedAction": TierHandVerified, "AssociateEnvironmentOperationsRole": TierHandVerified, @@ -3942,7 +3952,7 @@ var Services = map[string]Service{ "UpdateTagsForResource": TierHandVerified, "ValidateConfigurationSettings": TierHandVerified, }}, - "elasticloadbalancingv2": {Protocol: "query", ModelBacked: true, Operations: map[string]Tier{ + "elasticloadbalancingv2": {Protocol: "query", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "AddListenerCertificates": TierHandVerified, "AddTags": TierHandVerified, "AddTrustStoreRevocations": TierUnimplemented, @@ -3995,7 +4005,7 @@ var Services = map[string]Service{ "SetSecurityGroups": TierHandVerified, "SetSubnets": TierHandVerified, }}, - "elasticsearchservice": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "elasticsearchservice": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "AcceptInboundCrossClusterSearchConnection": TierHandVerified, "AddTags": TierHandVerified, "AssociatePackage": TierHandVerified, @@ -4048,7 +4058,7 @@ var Services = map[string]Service{ "UpdateVpcEndpoint": TierHandVerified, "UpgradeElasticsearchDomain": TierHandVerified, }}, - "emr": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "emr": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AddInstanceFleet": TierHandVerified, "AddInstanceGroups": TierHandVerified, "AddJobFlowSteps": TierHandVerified, @@ -4110,47 +4120,47 @@ var Services = map[string]Service{ "UpdateStudio": TierHandVerified, "UpdateStudioSessionMapping": TierHandVerified, }}, - "entityresolution": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "entityresolution": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AddPolicyStatement": TierUnimplemented, "BatchDeleteUniqueId": TierUnimplemented, - "CreateIdMappingWorkflow": TierUnimplemented, - "CreateIdNamespace": TierUnimplemented, - "CreateMatchingWorkflow": TierUnimplemented, - "CreateSchemaMapping": TierUnimplemented, - "DeleteIdMappingWorkflow": TierUnimplemented, - "DeleteIdNamespace": TierUnimplemented, - "DeleteMatchingWorkflow": TierUnimplemented, - "DeletePolicyStatement": TierUnimplemented, - "DeleteSchemaMapping": TierUnimplemented, + "CreateIdMappingWorkflow": TierAutoCRUD, + "CreateIdNamespace": TierAutoCRUD, + "CreateMatchingWorkflow": TierAutoCRUD, + "CreateSchemaMapping": TierAutoCRUD, + "DeleteIdMappingWorkflow": TierAutoCRUD, + "DeleteIdNamespace": TierAutoCRUD, + "DeleteMatchingWorkflow": TierAutoCRUD, + "DeletePolicyStatement": TierAutoCRUD, + "DeleteSchemaMapping": TierAutoCRUD, "GenerateMatchId": TierUnimplemented, - "GetIdMappingJob": TierUnimplemented, - "GetIdMappingWorkflow": TierUnimplemented, - "GetIdNamespace": TierUnimplemented, - "GetMatchId": TierUnimplemented, - "GetMatchingJob": TierUnimplemented, - "GetMatchingWorkflow": TierUnimplemented, - "GetPolicy": TierUnimplemented, - "GetProviderService": TierUnimplemented, - "GetSchemaMapping": TierUnimplemented, - "ListIdMappingJobs": TierUnimplemented, - "ListIdMappingWorkflows": TierUnimplemented, - "ListIdNamespaces": TierUnimplemented, - "ListMatchingJobs": TierUnimplemented, - "ListMatchingWorkflows": TierUnimplemented, - "ListProviderServices": TierUnimplemented, - "ListSchemaMappings": TierUnimplemented, - "ListTagsForResource": TierUnimplemented, - "PutPolicy": TierUnimplemented, + "GetIdMappingJob": TierAutoCRUD, + "GetIdMappingWorkflow": TierAutoCRUD, + "GetIdNamespace": TierAutoCRUD, + "GetMatchId": TierAutoCRUD, + "GetMatchingJob": TierAutoCRUD, + "GetMatchingWorkflow": TierAutoCRUD, + "GetPolicy": TierAutoCRUD, + "GetProviderService": TierAutoCRUD, + "GetSchemaMapping": TierAutoCRUD, + "ListIdMappingJobs": TierAutoCRUD, + "ListIdMappingWorkflows": TierAutoCRUD, + "ListIdNamespaces": TierAutoCRUD, + "ListMatchingJobs": TierAutoCRUD, + "ListMatchingWorkflows": TierAutoCRUD, + "ListProviderServices": TierAutoCRUD, + "ListSchemaMappings": TierAutoCRUD, + "ListTagsForResource": TierAutoCRUD, + "PutPolicy": TierAutoCRUD, "StartIdMappingJob": TierUnimplemented, "StartMatchingJob": TierUnimplemented, - "TagResource": TierUnimplemented, - "UntagResource": TierUnimplemented, - "UpdateIdMappingWorkflow": TierUnimplemented, - "UpdateIdNamespace": TierUnimplemented, - "UpdateMatchingWorkflow": TierUnimplemented, - "UpdateSchemaMapping": TierUnimplemented, - }}, - "eventbridge": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "TagResource": TierAutoCRUD, + "UntagResource": TierAutoCRUD, + "UpdateIdMappingWorkflow": TierAutoCRUD, + "UpdateIdNamespace": TierAutoCRUD, + "UpdateMatchingWorkflow": TierAutoCRUD, + "UpdateSchemaMapping": TierAutoCRUD, + }}, + "eventbridge": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "ActivateEventSource": TierUnimplemented, "CancelReplay": TierHandVerified, "CreateApiDestination": TierAutoCRUD, @@ -4209,7 +4219,7 @@ var Services = map[string]Service{ "UpdateEndpoint": TierAutoCRUD, "UpdateEventBus": TierAutoCRUD, }}, - "firehose": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "firehose": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AddKinesisSource": TierHandVerified, "CreateDeliveryStream": TierHandVerified, "DeleteDeliveryStream": TierHandVerified, @@ -4251,7 +4261,7 @@ var Services = map[string]Service{ "UpdateS3Destination": TierHandVerified, "UpdateSplunkDestination": TierHandVerified, }}, - "fis": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "fis": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "CancelExperiment": TierHandVerified, "CloneExperimentTemplate": TierHandVerified, "CreateExperimentTemplate": TierHandVerified, @@ -4286,7 +4296,7 @@ var Services = map[string]Service{ "UpdateTargetAccountConfiguration": TierHandVerified, "ValidateExperimentTemplate": TierHandVerified, }}, - "forecast": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "forecast": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "CreateAutoPredictor": TierAutoCRUD, "CreateDataset": TierAutoCRUD, "CreateDatasetGroup": TierAutoCRUD, @@ -4351,11 +4361,11 @@ var Services = map[string]Service{ "UntagResource": TierAutoCRUD, "UpdateDatasetGroup": TierAutoCRUD, }}, - "forecastquery": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "forecastquery": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "QueryForecast": TierUnimplemented, "QueryWhatIfForecast": TierUnimplemented, }}, - "frauddetector": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "frauddetector": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "BatchCreateVariable": TierUnimplemented, "BatchGetVariable": TierAutoCRUD, "CancelBatchImportJob": TierUnimplemented, @@ -4430,7 +4440,7 @@ var Services = map[string]Service{ "UpdateRuleVersion": TierAutoCRUD, "UpdateVariable": TierAutoCRUD, }}, - "glacier": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "glacier": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "AbortMultipartUpload": TierHandVerified, "AbortVaultLock": TierHandVerified, "AddTagsToVault": TierHandVerified, @@ -4465,7 +4475,7 @@ var Services = map[string]Service{ "UploadArchive": TierHandVerified, "UploadMultipartPart": TierHandVerified, }}, - "glue": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "glue": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "BatchCreatePartition": TierHandVerified, "BatchDeleteConnection": TierHandVerified, "BatchDeletePartition": TierHandVerified, @@ -4732,7 +4742,7 @@ var Services = map[string]Service{ "UpdateUserDefinedFunction": TierAutoCRUD, "UpdateWorkflow": TierAutoCRUD, }}, - "healthlake": {Protocol: "json-1.0", ModelBacked: true, Operations: map[string]Tier{ + "healthlake": {Protocol: "json-1.0", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "CreateDataTransformationProfile": TierAutoCRUD, "CreateFHIRDatastore": TierAutoCRUD, "DeleteDataTransformationProfile": TierAutoCRUD, @@ -4760,7 +4770,7 @@ var Services = map[string]Service{ "UpdateFHIRDatastore": TierAutoCRUD, "UpdateProfileWithAgent": TierAutoCRUD, }}, - "iam": {Protocol: "query", ModelBacked: true, Operations: map[string]Tier{ + "iam": {Protocol: "query", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "AcceptDelegationRequest": TierUnimplemented, "AddClientIDToOpenIDConnectProvider": TierUnimplemented, "AddRoleToInstanceProfile": TierHandVerified, @@ -4938,7 +4948,7 @@ var Services = map[string]Service{ "UploadServerCertificate": TierUnimplemented, "UploadSigningCertificate": TierUnimplemented, }}, - "identitystore": {Protocol: "", ModelBacked: false, Operations: map[string]Tier{ + "identitystore": {Protocol: "", ModelBacked: false, EngineWired: false, Operations: map[string]Tier{ "ActivateUser": TierHandVerified, "BatchCreateGroups": TierHandVerified, "BatchCreateUsers": TierHandVerified, @@ -4977,7 +4987,7 @@ var Services = map[string]Service{ "UpdateGroup": TierHandVerified, "UpdateUser": TierHandVerified, }}, - "iot": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "iot": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "AcceptCertificateTransfer": TierUnimplemented, "AddThingToBillingGroup": TierUnimplemented, "AddThingToThingGroup": TierHandVerified, @@ -5251,7 +5261,7 @@ var Services = map[string]Service{ "UpdateTopicRuleDestination": TierUnimplemented, "ValidateSecurityProfileBehaviors": TierUnimplemented, }}, - "iotdataplane": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "iotdataplane": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "DeleteConnection": TierHandVerified, "DeleteThingShadow": TierHandVerified, "GetRetainedMessage": TierHandVerified, @@ -5261,7 +5271,7 @@ var Services = map[string]Service{ "Publish": TierHandVerified, "UpdateThingShadow": TierHandVerified, }}, - "iotwireless": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "iotwireless": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "AssociateAwsAccountWithPartnerAccount": TierUnimplemented, "AssociateMulticastGroupWithFuotaTask": TierUnimplemented, "AssociateWirelessDeviceWithFuotaTask": TierUnimplemented, @@ -5375,7 +5385,7 @@ var Services = map[string]Service{ "UpdateWirelessDeviceImportTask": TierUnimplemented, "UpdateWirelessGateway": TierHandVerified, }}, - "kafka": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "kafka": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "BatchAssociateScramSecret": TierHandVerified, "BatchDisassociateScramSecret": TierHandVerified, "CreateCluster": TierHandVerified, @@ -5436,7 +5446,7 @@ var Services = map[string]Service{ "UpdateStorage": TierHandVerified, "UpdateTopic": TierHandVerified, }}, - "kendra": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "kendra": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AssociateEntitiesToExperience": TierUnimplemented, "AssociatePersonasToEntities": TierUnimplemented, "BatchDeleteDocument": TierUnimplemented, @@ -5504,7 +5514,7 @@ var Services = map[string]Service{ "UpdateQuerySuggestionsConfig": TierAutoCRUD, "UpdateThesaurus": TierAutoCRUD, }}, - "kendraranking": {Protocol: "json-1.0", ModelBacked: true, Operations: map[string]Tier{ + "kendraranking": {Protocol: "json-1.0", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "CreateRescoreExecutionPlan": TierAutoCRUD, "DeleteRescoreExecutionPlan": TierAutoCRUD, "DescribeRescoreExecutionPlan": TierAutoCRUD, @@ -5515,7 +5525,7 @@ var Services = map[string]Service{ "UntagResource": TierAutoCRUD, "UpdateRescoreExecutionPlan": TierAutoCRUD, }}, - "kinesis": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "kinesis": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AddTagsToStream": TierHandVerified, "CreateStream": TierHandVerified, "DecreaseStreamRetentionPeriod": TierHandVerified, @@ -5556,7 +5566,7 @@ var Services = map[string]Service{ "UpdateStreamMode": TierHandVerified, "UpdateStreamWarmThroughput": TierHandVerified, }}, - "kinesisanalyticsv2": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "kinesisanalyticsv2": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AddApplicationCloudWatchLoggingOption": TierHandVerified, "AddApplicationInput": TierHandVerified, "AddApplicationInputProcessingConfiguration": TierHandVerified, @@ -5591,7 +5601,7 @@ var Services = map[string]Service{ "UpdateApplication": TierHandVerified, "UpdateApplicationMaintenanceConfiguration": TierHandVerified, }}, - "kms": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "kms": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "CancelKeyDeletion": TierHandVerified, "ConnectCustomKeyStore": TierUnimplemented, "CreateAlias": TierHandVerified, @@ -5646,7 +5656,7 @@ var Services = map[string]Service{ "Verify": TierHandVerified, "VerifyMac": TierUnimplemented, }}, - "lakeformation": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "lakeformation": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "AddLFTagsToResource": TierHandVerified, "AssumeDecoratedRoleWithSAML": TierHandVerified, "BatchGrantPermissions": TierHandVerified, @@ -5709,7 +5719,7 @@ var Services = map[string]Service{ "UpdateTableObjects": TierHandVerified, "UpdateTableStorageOptimizer": TierHandVerified, }}, - "lambda": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "lambda": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "AddLayerVersionPermission": TierUnimplemented, "AddPermission": TierHandVerified, "CheckpointDurableExecution": TierUnimplemented, @@ -5796,137 +5806,137 @@ var Services = map[string]Service{ "UpdateFunctionEventInvokeConfig": TierUnimplemented, "UpdateFunctionUrlConfig": TierUnimplemented, }}, - "lexmodelbuildingservice": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ - "CreateBotVersion": TierUnimplemented, - "CreateIntentVersion": TierUnimplemented, - "CreateSlotTypeVersion": TierUnimplemented, - "DeleteBot": TierUnimplemented, - "DeleteBotAlias": TierUnimplemented, - "DeleteBotChannelAssociation": TierUnimplemented, - "DeleteBotVersion": TierUnimplemented, - "DeleteIntent": TierUnimplemented, - "DeleteIntentVersion": TierUnimplemented, - "DeleteSlotType": TierUnimplemented, - "DeleteSlotTypeVersion": TierUnimplemented, - "DeleteUtterances": TierUnimplemented, - "GetBot": TierUnimplemented, - "GetBotAlias": TierUnimplemented, - "GetBotAliases": TierUnimplemented, - "GetBotChannelAssociation": TierUnimplemented, - "GetBotChannelAssociations": TierUnimplemented, - "GetBotVersions": TierUnimplemented, - "GetBots": TierUnimplemented, - "GetBuiltinIntent": TierUnimplemented, - "GetBuiltinIntents": TierUnimplemented, - "GetBuiltinSlotTypes": TierUnimplemented, - "GetExport": TierUnimplemented, - "GetImport": TierUnimplemented, - "GetIntent": TierUnimplemented, - "GetIntentVersions": TierUnimplemented, - "GetIntents": TierUnimplemented, - "GetMigration": TierUnimplemented, - "GetMigrations": TierUnimplemented, - "GetSlotType": TierUnimplemented, - "GetSlotTypeVersions": TierUnimplemented, - "GetSlotTypes": TierUnimplemented, - "GetUtterancesView": TierUnimplemented, - "ListTagsForResource": TierUnimplemented, - "PutBot": TierUnimplemented, - "PutBotAlias": TierUnimplemented, - "PutIntent": TierUnimplemented, - "PutSlotType": TierUnimplemented, + "lexmodelbuildingservice": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ + "CreateBotVersion": TierAutoCRUD, + "CreateIntentVersion": TierAutoCRUD, + "CreateSlotTypeVersion": TierAutoCRUD, + "DeleteBot": TierAutoCRUD, + "DeleteBotAlias": TierAutoCRUD, + "DeleteBotChannelAssociation": TierAutoCRUD, + "DeleteBotVersion": TierAutoCRUD, + "DeleteIntent": TierAutoCRUD, + "DeleteIntentVersion": TierAutoCRUD, + "DeleteSlotType": TierAutoCRUD, + "DeleteSlotTypeVersion": TierAutoCRUD, + "DeleteUtterances": TierAutoCRUD, + "GetBot": TierAutoCRUD, + "GetBotAlias": TierAutoCRUD, + "GetBotAliases": TierAutoCRUD, + "GetBotChannelAssociation": TierAutoCRUD, + "GetBotChannelAssociations": TierAutoCRUD, + "GetBotVersions": TierAutoCRUD, + "GetBots": TierAutoCRUD, + "GetBuiltinIntent": TierAutoCRUD, + "GetBuiltinIntents": TierAutoCRUD, + "GetBuiltinSlotTypes": TierAutoCRUD, + "GetExport": TierAutoCRUD, + "GetImport": TierAutoCRUD, + "GetIntent": TierAutoCRUD, + "GetIntentVersions": TierAutoCRUD, + "GetIntents": TierAutoCRUD, + "GetMigration": TierAutoCRUD, + "GetMigrations": TierAutoCRUD, + "GetSlotType": TierAutoCRUD, + "GetSlotTypeVersions": TierAutoCRUD, + "GetSlotTypes": TierAutoCRUD, + "GetUtterancesView": TierAutoCRUD, + "ListTagsForResource": TierAutoCRUD, + "PutBot": TierAutoCRUD, + "PutBotAlias": TierAutoCRUD, + "PutIntent": TierAutoCRUD, + "PutSlotType": TierAutoCRUD, "StartImport": TierUnimplemented, "StartMigration": TierUnimplemented, - "TagResource": TierUnimplemented, - "UntagResource": TierUnimplemented, + "TagResource": TierAutoCRUD, + "UntagResource": TierAutoCRUD, }}, - "lexmodelsv2": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "lexmodelsv2": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "BatchCreateCustomVocabularyItem": TierUnimplemented, "BatchDeleteCustomVocabularyItem": TierUnimplemented, "BatchUpdateCustomVocabularyItem": TierUnimplemented, "BuildBotLocale": TierUnimplemented, - "CreateBot": TierUnimplemented, - "CreateBotAlias": TierUnimplemented, - "CreateBotLocale": TierUnimplemented, - "CreateBotReplica": TierUnimplemented, - "CreateBotVersion": TierUnimplemented, - "CreateExport": TierUnimplemented, - "CreateIntent": TierUnimplemented, - "CreateResourcePolicy": TierUnimplemented, - "CreateResourcePolicyStatement": TierUnimplemented, - "CreateSlot": TierUnimplemented, - "CreateSlotType": TierUnimplemented, - "CreateTestSetDiscrepancyReport": TierUnimplemented, - "CreateUploadUrl": TierUnimplemented, - "DeleteBot": TierUnimplemented, - "DeleteBotAlias": TierUnimplemented, - "DeleteBotAnalyzerRecommendation": TierUnimplemented, - "DeleteBotLocale": TierUnimplemented, - "DeleteBotReplica": TierUnimplemented, - "DeleteBotVersion": TierUnimplemented, - "DeleteCustomVocabulary": TierUnimplemented, - "DeleteExport": TierUnimplemented, - "DeleteImport": TierUnimplemented, - "DeleteIntent": TierUnimplemented, - "DeleteResourcePolicy": TierUnimplemented, - "DeleteResourcePolicyStatement": TierUnimplemented, - "DeleteSlot": TierUnimplemented, - "DeleteSlotType": TierUnimplemented, - "DeleteTestSet": TierUnimplemented, - "DeleteUtterances": TierUnimplemented, - "DescribeBot": TierUnimplemented, - "DescribeBotAlias": TierUnimplemented, - "DescribeBotAnalyzerRecommendation": TierUnimplemented, - "DescribeBotLocale": TierUnimplemented, - "DescribeBotRecommendation": TierUnimplemented, - "DescribeBotReplica": TierUnimplemented, - "DescribeBotResourceGeneration": TierUnimplemented, - "DescribeBotVersion": TierUnimplemented, - "DescribeCustomVocabularyMetadata": TierUnimplemented, - "DescribeExport": TierUnimplemented, - "DescribeImport": TierUnimplemented, - "DescribeIntent": TierUnimplemented, - "DescribeResourcePolicy": TierUnimplemented, - "DescribeSlot": TierUnimplemented, - "DescribeSlotType": TierUnimplemented, - "DescribeTestExecution": TierUnimplemented, - "DescribeTestSet": TierUnimplemented, - "DescribeTestSetDiscrepancyReport": TierUnimplemented, - "DescribeTestSetGeneration": TierUnimplemented, + "CreateBot": TierAutoCRUD, + "CreateBotAlias": TierAutoCRUD, + "CreateBotLocale": TierAutoCRUD, + "CreateBotReplica": TierAutoCRUD, + "CreateBotVersion": TierAutoCRUD, + "CreateExport": TierAutoCRUD, + "CreateIntent": TierAutoCRUD, + "CreateResourcePolicy": TierAutoCRUD, + "CreateResourcePolicyStatement": TierAutoCRUD, + "CreateSlot": TierAutoCRUD, + "CreateSlotType": TierAutoCRUD, + "CreateTestSetDiscrepancyReport": TierAutoCRUD, + "CreateUploadUrl": TierAutoCRUD, + "DeleteBot": TierAutoCRUD, + "DeleteBotAlias": TierAutoCRUD, + "DeleteBotAnalyzerRecommendation": TierAutoCRUD, + "DeleteBotLocale": TierAutoCRUD, + "DeleteBotReplica": TierAutoCRUD, + "DeleteBotVersion": TierAutoCRUD, + "DeleteCustomVocabulary": TierAutoCRUD, + "DeleteExport": TierAutoCRUD, + "DeleteImport": TierAutoCRUD, + "DeleteIntent": TierAutoCRUD, + "DeleteResourcePolicy": TierAutoCRUD, + "DeleteResourcePolicyStatement": TierAutoCRUD, + "DeleteSlot": TierAutoCRUD, + "DeleteSlotType": TierAutoCRUD, + "DeleteTestSet": TierAutoCRUD, + "DeleteUtterances": TierAutoCRUD, + "DescribeBot": TierAutoCRUD, + "DescribeBotAlias": TierAutoCRUD, + "DescribeBotAnalyzerRecommendation": TierAutoCRUD, + "DescribeBotLocale": TierAutoCRUD, + "DescribeBotRecommendation": TierAutoCRUD, + "DescribeBotReplica": TierAutoCRUD, + "DescribeBotResourceGeneration": TierAutoCRUD, + "DescribeBotVersion": TierAutoCRUD, + "DescribeCustomVocabularyMetadata": TierAutoCRUD, + "DescribeExport": TierAutoCRUD, + "DescribeImport": TierAutoCRUD, + "DescribeIntent": TierAutoCRUD, + "DescribeResourcePolicy": TierAutoCRUD, + "DescribeSlot": TierAutoCRUD, + "DescribeSlotType": TierAutoCRUD, + "DescribeTestExecution": TierAutoCRUD, + "DescribeTestSet": TierAutoCRUD, + "DescribeTestSetDiscrepancyReport": TierAutoCRUD, + "DescribeTestSetGeneration": TierAutoCRUD, "GenerateBotElement": TierUnimplemented, - "GetTestExecutionArtifactsUrl": TierUnimplemented, - "ListAggregatedUtterances": TierUnimplemented, - "ListBotAliasReplicas": TierUnimplemented, - "ListBotAliases": TierUnimplemented, - "ListBotAnalyzerHistory": TierUnimplemented, - "ListBotLocales": TierUnimplemented, - "ListBotRecommendations": TierUnimplemented, - "ListBotReplicas": TierUnimplemented, - "ListBotResourceGenerations": TierUnimplemented, - "ListBotVersionReplicas": TierUnimplemented, - "ListBotVersions": TierUnimplemented, - "ListBots": TierUnimplemented, - "ListBuiltInIntents": TierUnimplemented, - "ListBuiltInSlotTypes": TierUnimplemented, - "ListCustomVocabularyItems": TierUnimplemented, - "ListExports": TierUnimplemented, - "ListImports": TierUnimplemented, - "ListIntentMetrics": TierUnimplemented, - "ListIntentPaths": TierUnimplemented, - "ListIntentStageMetrics": TierUnimplemented, - "ListIntents": TierUnimplemented, - "ListRecommendedIntents": TierUnimplemented, - "ListSessionAnalyticsData": TierUnimplemented, - "ListSessionMetrics": TierUnimplemented, - "ListSlotTypes": TierUnimplemented, - "ListSlots": TierUnimplemented, - "ListTagsForResource": TierUnimplemented, - "ListTestExecutionResultItems": TierUnimplemented, - "ListTestExecutions": TierUnimplemented, - "ListTestSetRecords": TierUnimplemented, - "ListTestSets": TierUnimplemented, - "ListUtteranceAnalyticsData": TierUnimplemented, - "ListUtteranceMetrics": TierUnimplemented, + "GetTestExecutionArtifactsUrl": TierAutoCRUD, + "ListAggregatedUtterances": TierAutoCRUD, + "ListBotAliasReplicas": TierAutoCRUD, + "ListBotAliases": TierAutoCRUD, + "ListBotAnalyzerHistory": TierAutoCRUD, + "ListBotLocales": TierAutoCRUD, + "ListBotRecommendations": TierAutoCRUD, + "ListBotReplicas": TierAutoCRUD, + "ListBotResourceGenerations": TierAutoCRUD, + "ListBotVersionReplicas": TierAutoCRUD, + "ListBotVersions": TierAutoCRUD, + "ListBots": TierAutoCRUD, + "ListBuiltInIntents": TierAutoCRUD, + "ListBuiltInSlotTypes": TierAutoCRUD, + "ListCustomVocabularyItems": TierAutoCRUD, + "ListExports": TierAutoCRUD, + "ListImports": TierAutoCRUD, + "ListIntentMetrics": TierAutoCRUD, + "ListIntentPaths": TierAutoCRUD, + "ListIntentStageMetrics": TierAutoCRUD, + "ListIntents": TierAutoCRUD, + "ListRecommendedIntents": TierAutoCRUD, + "ListSessionAnalyticsData": TierAutoCRUD, + "ListSessionMetrics": TierAutoCRUD, + "ListSlotTypes": TierAutoCRUD, + "ListSlots": TierAutoCRUD, + "ListTagsForResource": TierAutoCRUD, + "ListTestExecutionResultItems": TierAutoCRUD, + "ListTestExecutions": TierAutoCRUD, + "ListTestSetRecords": TierAutoCRUD, + "ListTestSets": TierAutoCRUD, + "ListUtteranceAnalyticsData": TierAutoCRUD, + "ListUtteranceMetrics": TierAutoCRUD, "SearchAssociatedTranscripts": TierUnimplemented, "StartBotAnalyzer": TierUnimplemented, "StartBotRecommendation": TierUnimplemented, @@ -5936,35 +5946,35 @@ var Services = map[string]Service{ "StartTestSetGeneration": TierUnimplemented, "StopBotAnalyzer": TierUnimplemented, "StopBotRecommendation": TierUnimplemented, - "TagResource": TierUnimplemented, - "UntagResource": TierUnimplemented, - "UpdateBot": TierUnimplemented, - "UpdateBotAlias": TierUnimplemented, - "UpdateBotLocale": TierUnimplemented, - "UpdateBotRecommendation": TierUnimplemented, - "UpdateExport": TierUnimplemented, - "UpdateIntent": TierUnimplemented, - "UpdateResourcePolicy": TierUnimplemented, - "UpdateSlot": TierUnimplemented, - "UpdateSlotType": TierUnimplemented, - "UpdateTestSet": TierUnimplemented, - }}, - "lexruntimeservice": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ - "DeleteSession": TierUnimplemented, - "GetSession": TierUnimplemented, + "TagResource": TierAutoCRUD, + "UntagResource": TierAutoCRUD, + "UpdateBot": TierAutoCRUD, + "UpdateBotAlias": TierAutoCRUD, + "UpdateBotLocale": TierAutoCRUD, + "UpdateBotRecommendation": TierAutoCRUD, + "UpdateExport": TierAutoCRUD, + "UpdateIntent": TierAutoCRUD, + "UpdateResourcePolicy": TierAutoCRUD, + "UpdateSlot": TierAutoCRUD, + "UpdateSlotType": TierAutoCRUD, + "UpdateTestSet": TierAutoCRUD, + }}, + "lexruntimeservice": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ + "DeleteSession": TierAutoCRUD, + "GetSession": TierAutoCRUD, "PostContent": TierUnimplemented, "PostText": TierUnimplemented, - "PutSession": TierUnimplemented, + "PutSession": TierAutoCRUD, }}, - "lexruntimev2": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ - "DeleteSession": TierUnimplemented, - "GetSession": TierUnimplemented, - "PutSession": TierUnimplemented, + "lexruntimev2": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ + "DeleteSession": TierAutoCRUD, + "GetSession": TierAutoCRUD, + "PutSession": TierAutoCRUD, "RecognizeText": TierUnimplemented, "RecognizeUtterance": TierUnimplemented, "StartConversation": TierUnimplemented, }}, - "lookoutequipment": {Protocol: "json-1.0", ModelBacked: true, Operations: map[string]Tier{ + "lookoutequipment": {Protocol: "json-1.0", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "CreateDataset": TierAutoCRUD, "CreateInferenceScheduler": TierAutoCRUD, "CreateLabel": TierAutoCRUD, @@ -6015,7 +6025,7 @@ var Services = map[string]Service{ "UpdateModel": TierAutoCRUD, "UpdateRetrainingScheduler": TierAutoCRUD, }}, - "managedblockchain": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "managedblockchain": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "CreateAccessor": TierHandVerified, "CreateMember": TierHandVerified, "CreateNetwork": TierHandVerified, @@ -6045,7 +6055,7 @@ var Services = map[string]Service{ "UpdateNode": TierHandVerified, "VoteOnProposal": TierHandVerified, }}, - "mediaconvert": {Protocol: "", ModelBacked: false, Operations: map[string]Tier{ + "mediaconvert": {Protocol: "", ModelBacked: false, EngineWired: false, Operations: map[string]Tier{ "AssociateCertificate": TierHandVerified, "CancelJob": TierHandVerified, "CreateJob": TierHandVerified, @@ -6082,7 +6092,7 @@ var Services = map[string]Service{ "UpdatePreset": TierHandVerified, "UpdateQueue": TierHandVerified, }}, - "memorydb": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "memorydb": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "BatchUpdateCluster": TierHandVerified, "CopySnapshot": TierHandVerified, "CreateACL": TierHandVerified, @@ -6129,7 +6139,7 @@ var Services = map[string]Service{ "UpdateSubnetGroup": TierHandVerified, "UpdateUser": TierHandVerified, }}, - "mq": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "mq": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "CreateBroker": TierHandVerified, "CreateConfiguration": TierHandVerified, "CreateTags": TierHandVerified, @@ -6155,7 +6165,7 @@ var Services = map[string]Service{ "UpdateConfiguration": TierHandVerified, "UpdateUser": TierHandVerified, }}, - "mwaa": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "mwaa": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "CreateCliToken": TierHandVerified, "CreateDag": TierHandVerified, "CreateDagRun": TierHandVerified, @@ -6190,7 +6200,7 @@ var Services = map[string]Service{ "UpdateEnvironment": TierHandVerified, "UpdateVariables": TierHandVerified, }}, - "neptune": {Protocol: "query", ModelBacked: true, Operations: map[string]Tier{ + "neptune": {Protocol: "query", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "AddRoleToDBCluster": TierHandVerified, "AddSourceIdentifierToSubscription": TierHandVerified, "AddTagsToResource": TierHandVerified, @@ -6263,7 +6273,7 @@ var Services = map[string]Service{ "StopDBCluster": TierHandVerified, "SwitchoverGlobalCluster": TierHandVerified, }}, - "omics": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "omics": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AbortMultipartReadSetUpload": TierUnimplemented, "AcceptShare": TierUnimplemented, "BatchDeleteReadSet": TierUnimplemented, @@ -6272,86 +6282,86 @@ var Services = map[string]Service{ "CancelRunBatch": TierUnimplemented, "CancelVariantImportJob": TierUnimplemented, "CompleteMultipartReadSetUpload": TierUnimplemented, - "CreateAnnotationStore": TierUnimplemented, - "CreateAnnotationStoreVersion": TierUnimplemented, - "CreateConfiguration": TierUnimplemented, - "CreateMultipartReadSetUpload": TierUnimplemented, - "CreateReferenceStore": TierUnimplemented, - "CreateRunCache": TierUnimplemented, - "CreateRunGroup": TierUnimplemented, - "CreateSequenceStore": TierUnimplemented, - "CreateShare": TierUnimplemented, - "CreateVariantStore": TierUnimplemented, - "CreateWorkflow": TierUnimplemented, - "CreateWorkflowVersion": TierUnimplemented, - "DeleteAnnotationStore": TierUnimplemented, - "DeleteAnnotationStoreVersions": TierUnimplemented, - "DeleteBatch": TierUnimplemented, - "DeleteConfiguration": TierUnimplemented, - "DeleteReference": TierUnimplemented, - "DeleteReferenceStore": TierUnimplemented, - "DeleteRun": TierUnimplemented, - "DeleteRunBatch": TierUnimplemented, - "DeleteRunCache": TierUnimplemented, - "DeleteRunGroup": TierUnimplemented, - "DeleteS3AccessPolicy": TierUnimplemented, - "DeleteSequenceStore": TierUnimplemented, - "DeleteShare": TierUnimplemented, - "DeleteVariantStore": TierUnimplemented, - "DeleteWorkflow": TierUnimplemented, - "DeleteWorkflowVersion": TierUnimplemented, - "GetAnnotationImportJob": TierUnimplemented, - "GetAnnotationStore": TierUnimplemented, - "GetAnnotationStoreVersion": TierUnimplemented, - "GetBatch": TierUnimplemented, - "GetConfiguration": TierUnimplemented, - "GetReadSet": TierUnimplemented, - "GetReadSetActivationJob": TierUnimplemented, - "GetReadSetExportJob": TierUnimplemented, - "GetReadSetImportJob": TierUnimplemented, - "GetReadSetMetadata": TierUnimplemented, - "GetReference": TierUnimplemented, - "GetReferenceImportJob": TierUnimplemented, - "GetReferenceMetadata": TierUnimplemented, - "GetReferenceStore": TierUnimplemented, - "GetRun": TierUnimplemented, - "GetRunCache": TierUnimplemented, - "GetRunGroup": TierUnimplemented, - "GetRunTask": TierUnimplemented, - "GetS3AccessPolicy": TierUnimplemented, - "GetSequenceStore": TierUnimplemented, - "GetShare": TierUnimplemented, - "GetVariantImportJob": TierUnimplemented, - "GetVariantStore": TierUnimplemented, - "GetWorkflow": TierUnimplemented, - "GetWorkflowVersion": TierUnimplemented, - "ListAnnotationImportJobs": TierUnimplemented, - "ListAnnotationStoreVersions": TierUnimplemented, - "ListAnnotationStores": TierUnimplemented, - "ListBatch": TierUnimplemented, - "ListConfigurations": TierUnimplemented, - "ListMultipartReadSetUploads": TierUnimplemented, - "ListReadSetActivationJobs": TierUnimplemented, - "ListReadSetExportJobs": TierUnimplemented, - "ListReadSetImportJobs": TierUnimplemented, - "ListReadSetUploadParts": TierUnimplemented, - "ListReadSets": TierUnimplemented, - "ListReferenceImportJobs": TierUnimplemented, - "ListReferenceStores": TierUnimplemented, - "ListReferences": TierUnimplemented, - "ListRunCaches": TierUnimplemented, - "ListRunGroups": TierUnimplemented, - "ListRunTasks": TierUnimplemented, - "ListRuns": TierUnimplemented, - "ListRunsInBatch": TierUnimplemented, - "ListSequenceStores": TierUnimplemented, - "ListShares": TierUnimplemented, - "ListTagsForResource": TierUnimplemented, - "ListVariantImportJobs": TierUnimplemented, - "ListVariantStores": TierUnimplemented, - "ListWorkflowVersions": TierUnimplemented, - "ListWorkflows": TierUnimplemented, - "PutS3AccessPolicy": TierUnimplemented, + "CreateAnnotationStore": TierAutoCRUD, + "CreateAnnotationStoreVersion": TierAutoCRUD, + "CreateConfiguration": TierAutoCRUD, + "CreateMultipartReadSetUpload": TierAutoCRUD, + "CreateReferenceStore": TierAutoCRUD, + "CreateRunCache": TierAutoCRUD, + "CreateRunGroup": TierAutoCRUD, + "CreateSequenceStore": TierAutoCRUD, + "CreateShare": TierAutoCRUD, + "CreateVariantStore": TierAutoCRUD, + "CreateWorkflow": TierAutoCRUD, + "CreateWorkflowVersion": TierAutoCRUD, + "DeleteAnnotationStore": TierAutoCRUD, + "DeleteAnnotationStoreVersions": TierAutoCRUD, + "DeleteBatch": TierAutoCRUD, + "DeleteConfiguration": TierAutoCRUD, + "DeleteReference": TierAutoCRUD, + "DeleteReferenceStore": TierAutoCRUD, + "DeleteRun": TierAutoCRUD, + "DeleteRunBatch": TierAutoCRUD, + "DeleteRunCache": TierAutoCRUD, + "DeleteRunGroup": TierAutoCRUD, + "DeleteS3AccessPolicy": TierAutoCRUD, + "DeleteSequenceStore": TierAutoCRUD, + "DeleteShare": TierAutoCRUD, + "DeleteVariantStore": TierAutoCRUD, + "DeleteWorkflow": TierAutoCRUD, + "DeleteWorkflowVersion": TierAutoCRUD, + "GetAnnotationImportJob": TierAutoCRUD, + "GetAnnotationStore": TierAutoCRUD, + "GetAnnotationStoreVersion": TierAutoCRUD, + "GetBatch": TierAutoCRUD, + "GetConfiguration": TierAutoCRUD, + "GetReadSet": TierAutoCRUD, + "GetReadSetActivationJob": TierAutoCRUD, + "GetReadSetExportJob": TierAutoCRUD, + "GetReadSetImportJob": TierAutoCRUD, + "GetReadSetMetadata": TierAutoCRUD, + "GetReference": TierAutoCRUD, + "GetReferenceImportJob": TierAutoCRUD, + "GetReferenceMetadata": TierAutoCRUD, + "GetReferenceStore": TierAutoCRUD, + "GetRun": TierAutoCRUD, + "GetRunCache": TierAutoCRUD, + "GetRunGroup": TierAutoCRUD, + "GetRunTask": TierAutoCRUD, + "GetS3AccessPolicy": TierAutoCRUD, + "GetSequenceStore": TierAutoCRUD, + "GetShare": TierAutoCRUD, + "GetVariantImportJob": TierAutoCRUD, + "GetVariantStore": TierAutoCRUD, + "GetWorkflow": TierAutoCRUD, + "GetWorkflowVersion": TierAutoCRUD, + "ListAnnotationImportJobs": TierAutoCRUD, + "ListAnnotationStoreVersions": TierAutoCRUD, + "ListAnnotationStores": TierAutoCRUD, + "ListBatch": TierAutoCRUD, + "ListConfigurations": TierAutoCRUD, + "ListMultipartReadSetUploads": TierAutoCRUD, + "ListReadSetActivationJobs": TierAutoCRUD, + "ListReadSetExportJobs": TierAutoCRUD, + "ListReadSetImportJobs": TierAutoCRUD, + "ListReadSetUploadParts": TierAutoCRUD, + "ListReadSets": TierAutoCRUD, + "ListReferenceImportJobs": TierAutoCRUD, + "ListReferenceStores": TierAutoCRUD, + "ListReferences": TierAutoCRUD, + "ListRunCaches": TierAutoCRUD, + "ListRunGroups": TierAutoCRUD, + "ListRunTasks": TierAutoCRUD, + "ListRuns": TierAutoCRUD, + "ListRunsInBatch": TierAutoCRUD, + "ListSequenceStores": TierAutoCRUD, + "ListShares": TierAutoCRUD, + "ListTagsForResource": TierAutoCRUD, + "ListVariantImportJobs": TierAutoCRUD, + "ListVariantStores": TierAutoCRUD, + "ListWorkflowVersions": TierAutoCRUD, + "ListWorkflows": TierAutoCRUD, + "PutS3AccessPolicy": TierAutoCRUD, "StartAnnotationImportJob": TierUnimplemented, "StartReadSetActivationJob": TierUnimplemented, "StartReadSetExportJob": TierUnimplemented, @@ -6360,19 +6370,19 @@ var Services = map[string]Service{ "StartRun": TierUnimplemented, "StartRunBatch": TierUnimplemented, "StartVariantImportJob": TierUnimplemented, - "TagResource": TierUnimplemented, - "UntagResource": TierUnimplemented, - "UpdateAnnotationStore": TierUnimplemented, - "UpdateAnnotationStoreVersion": TierUnimplemented, - "UpdateRunCache": TierUnimplemented, - "UpdateRunGroup": TierUnimplemented, - "UpdateSequenceStore": TierUnimplemented, - "UpdateVariantStore": TierUnimplemented, - "UpdateWorkflow": TierUnimplemented, - "UpdateWorkflowVersion": TierUnimplemented, + "TagResource": TierAutoCRUD, + "UntagResource": TierAutoCRUD, + "UpdateAnnotationStore": TierAutoCRUD, + "UpdateAnnotationStoreVersion": TierAutoCRUD, + "UpdateRunCache": TierAutoCRUD, + "UpdateRunGroup": TierAutoCRUD, + "UpdateSequenceStore": TierAutoCRUD, + "UpdateVariantStore": TierAutoCRUD, + "UpdateWorkflow": TierAutoCRUD, + "UpdateWorkflowVersion": TierAutoCRUD, "UploadReadSetPart": TierUnimplemented, }}, - "opensearch": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "opensearch": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "AcceptInboundConnection": TierHandVerified, "AddDataSource": TierHandVerified, "AddDirectQueryDataSource": TierHandVerified, @@ -6461,7 +6471,7 @@ var Services = map[string]Service{ "UpdateVpcEndpoint": TierHandVerified, "UpgradeDomain": TierHandVerified, }}, - "organizations": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "organizations": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AcceptHandshake": TierHandVerified, "AttachPolicy": TierHandVerified, "CancelHandshake": TierHandVerified, @@ -6526,7 +6536,7 @@ var Services = map[string]Service{ "UpdatePolicy": TierHandVerified, "UpdateResponsibilityTransfer": TierAutoCRUD, }}, - "personalize": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "personalize": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "CreateBatchInferenceJob": TierAutoCRUD, "CreateBatchSegmentJob": TierAutoCRUD, "CreateCampaign": TierAutoCRUD, @@ -6599,19 +6609,19 @@ var Services = map[string]Service{ "UpdateRecommender": TierAutoCRUD, "UpdateSolution": TierAutoCRUD, }}, - "personalizeevents": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ - "PutActionInteractions": TierUnimplemented, - "PutActions": TierUnimplemented, - "PutEvents": TierUnimplemented, - "PutItems": TierUnimplemented, - "PutUsers": TierUnimplemented, + "personalizeevents": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ + "PutActionInteractions": TierAutoCRUD, + "PutActions": TierAutoCRUD, + "PutEvents": TierAutoCRUD, + "PutItems": TierAutoCRUD, + "PutUsers": TierAutoCRUD, }}, - "personalizeruntime": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ - "GetActionRecommendations": TierUnimplemented, - "GetPersonalizedRanking": TierUnimplemented, - "GetRecommendations": TierUnimplemented, + "personalizeruntime": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ + "GetActionRecommendations": TierAutoCRUD, + "GetPersonalizedRanking": TierAutoCRUD, + "GetRecommendations": TierAutoCRUD, }}, - "pinpoint": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "pinpoint": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "CreateApp": TierHandVerified, "CreateCampaign": TierHandVerified, "CreateEmailTemplate": TierHandVerified, @@ -6735,7 +6745,7 @@ var Services = map[string]Service{ "UpdateVoiceTemplate": TierHandVerified, "VerifyOTPMessage": TierHandVerified, }}, - "pipes": {Protocol: "", ModelBacked: false, Operations: map[string]Tier{ + "pipes": {Protocol: "", ModelBacked: false, EngineWired: false, Operations: map[string]Tier{ "CreatePipe": TierHandVerified, "DeletePipe": TierHandVerified, "DescribePipe": TierHandVerified, @@ -6760,56 +6770,56 @@ var Services = map[string]Service{ "UpdatePipe": TierHandVerified, "ValidatePipeParameters": TierHandVerified, }}, - "polly": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ - "DeleteLexicon": TierUnimplemented, - "DescribeVoices": TierUnimplemented, - "GetLexicon": TierUnimplemented, - "GetSpeechSynthesisTask": TierUnimplemented, - "ListLexicons": TierUnimplemented, - "ListSpeechSynthesisTasks": TierUnimplemented, - "PutLexicon": TierUnimplemented, + "polly": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ + "DeleteLexicon": TierAutoCRUD, + "DescribeVoices": TierAutoCRUD, + "GetLexicon": TierAutoCRUD, + "GetSpeechSynthesisTask": TierAutoCRUD, + "ListLexicons": TierAutoCRUD, + "ListSpeechSynthesisTasks": TierAutoCRUD, + "PutLexicon": TierAutoCRUD, "StartSpeechSynthesisStream": TierUnimplemented, "StartSpeechSynthesisTask": TierUnimplemented, "SynthesizeSpeech": TierUnimplemented, }}, - "qapps": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "qapps": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AssociateLibraryItemReview": TierUnimplemented, "AssociateQAppWithUser": TierUnimplemented, "BatchCreateCategory": TierUnimplemented, "BatchDeleteCategory": TierUnimplemented, "BatchUpdateCategory": TierUnimplemented, - "CreateLibraryItem": TierUnimplemented, - "CreatePresignedUrl": TierUnimplemented, - "CreateQApp": TierUnimplemented, - "DeleteLibraryItem": TierUnimplemented, - "DeleteQApp": TierUnimplemented, - "DescribeQAppPermissions": TierUnimplemented, + "CreateLibraryItem": TierAutoCRUD, + "CreatePresignedUrl": TierAutoCRUD, + "CreateQApp": TierAutoCRUD, + "DeleteLibraryItem": TierAutoCRUD, + "DeleteQApp": TierAutoCRUD, + "DescribeQAppPermissions": TierAutoCRUD, "DisassociateLibraryItemReview": TierUnimplemented, "DisassociateQAppFromUser": TierUnimplemented, "ExportQAppSessionData": TierUnimplemented, - "GetLibraryItem": TierUnimplemented, - "GetQApp": TierUnimplemented, - "GetQAppSession": TierUnimplemented, - "GetQAppSessionMetadata": TierUnimplemented, + "GetLibraryItem": TierAutoCRUD, + "GetQApp": TierAutoCRUD, + "GetQAppSession": TierAutoCRUD, + "GetQAppSessionMetadata": TierAutoCRUD, "ImportDocument": TierUnimplemented, - "ListCategories": TierUnimplemented, - "ListLibraryItems": TierUnimplemented, - "ListQAppSessionData": TierUnimplemented, - "ListQApps": TierUnimplemented, - "ListTagsForResource": TierUnimplemented, + "ListCategories": TierAutoCRUD, + "ListLibraryItems": TierAutoCRUD, + "ListQAppSessionData": TierAutoCRUD, + "ListQApps": TierAutoCRUD, + "ListTagsForResource": TierAutoCRUD, "PredictQApp": TierUnimplemented, "StartQAppSession": TierUnimplemented, "StopQAppSession": TierUnimplemented, - "TagResource": TierUnimplemented, - "UntagResource": TierUnimplemented, - "UpdateLibraryItem": TierUnimplemented, - "UpdateLibraryItemMetadata": TierUnimplemented, - "UpdateQApp": TierUnimplemented, - "UpdateQAppPermissions": TierUnimplemented, - "UpdateQAppSession": TierUnimplemented, - "UpdateQAppSessionMetadata": TierUnimplemented, - }}, - "qbusiness": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "TagResource": TierAutoCRUD, + "UntagResource": TierAutoCRUD, + "UpdateLibraryItem": TierAutoCRUD, + "UpdateLibraryItemMetadata": TierAutoCRUD, + "UpdateQApp": TierAutoCRUD, + "UpdateQAppPermissions": TierAutoCRUD, + "UpdateQAppSession": TierAutoCRUD, + "UpdateQAppSessionMetadata": TierAutoCRUD, + }}, + "qbusiness": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AssociatePermission": TierUnimplemented, "BatchDeleteDocument": TierUnimplemented, "BatchPutDocument": TierUnimplemented, @@ -6817,84 +6827,84 @@ var Services = map[string]Service{ "Chat": TierUnimplemented, "ChatSync": TierUnimplemented, "CheckDocumentAccess": TierUnimplemented, - "CreateAnonymousWebExperienceUrl": TierUnimplemented, - "CreateApplication": TierUnimplemented, - "CreateChatResponseConfiguration": TierUnimplemented, - "CreateDataAccessor": TierUnimplemented, - "CreateDataSource": TierUnimplemented, - "CreateIndex": TierUnimplemented, - "CreatePlugin": TierUnimplemented, - "CreateRetriever": TierUnimplemented, - "CreateSubscription": TierUnimplemented, - "CreateUser": TierUnimplemented, - "CreateWebExperience": TierUnimplemented, - "DeleteApplication": TierUnimplemented, - "DeleteAttachment": TierUnimplemented, - "DeleteChatControlsConfiguration": TierUnimplemented, - "DeleteChatResponseConfiguration": TierUnimplemented, - "DeleteConversation": TierUnimplemented, - "DeleteDataAccessor": TierUnimplemented, - "DeleteDataSource": TierUnimplemented, - "DeleteGroup": TierUnimplemented, - "DeleteIndex": TierUnimplemented, - "DeletePlugin": TierUnimplemented, - "DeleteRetriever": TierUnimplemented, - "DeleteUser": TierUnimplemented, - "DeleteWebExperience": TierUnimplemented, + "CreateAnonymousWebExperienceUrl": TierAutoCRUD, + "CreateApplication": TierAutoCRUD, + "CreateChatResponseConfiguration": TierAutoCRUD, + "CreateDataAccessor": TierAutoCRUD, + "CreateDataSource": TierAutoCRUD, + "CreateIndex": TierAutoCRUD, + "CreatePlugin": TierAutoCRUD, + "CreateRetriever": TierAutoCRUD, + "CreateSubscription": TierAutoCRUD, + "CreateUser": TierAutoCRUD, + "CreateWebExperience": TierAutoCRUD, + "DeleteApplication": TierAutoCRUD, + "DeleteAttachment": TierAutoCRUD, + "DeleteChatControlsConfiguration": TierAutoCRUD, + "DeleteChatResponseConfiguration": TierAutoCRUD, + "DeleteConversation": TierAutoCRUD, + "DeleteDataAccessor": TierAutoCRUD, + "DeleteDataSource": TierAutoCRUD, + "DeleteGroup": TierAutoCRUD, + "DeleteIndex": TierAutoCRUD, + "DeletePlugin": TierAutoCRUD, + "DeleteRetriever": TierAutoCRUD, + "DeleteUser": TierAutoCRUD, + "DeleteWebExperience": TierAutoCRUD, "DisassociatePermission": TierUnimplemented, - "GetApplication": TierUnimplemented, - "GetChatControlsConfiguration": TierUnimplemented, - "GetChatResponseConfiguration": TierUnimplemented, - "GetDataAccessor": TierUnimplemented, - "GetDataSource": TierUnimplemented, - "GetDocumentContent": TierUnimplemented, - "GetGroup": TierUnimplemented, - "GetIndex": TierUnimplemented, - "GetMedia": TierUnimplemented, - "GetPlugin": TierUnimplemented, - "GetPolicy": TierUnimplemented, - "GetRetriever": TierUnimplemented, - "GetUser": TierUnimplemented, - "GetWebExperience": TierUnimplemented, - "ListApplications": TierUnimplemented, - "ListAttachments": TierUnimplemented, - "ListChatResponseConfigurations": TierUnimplemented, - "ListConversations": TierUnimplemented, - "ListDataAccessors": TierUnimplemented, - "ListDataSourceSyncJobs": TierUnimplemented, - "ListDataSources": TierUnimplemented, - "ListDocuments": TierUnimplemented, - "ListGroups": TierUnimplemented, - "ListIndices": TierUnimplemented, - "ListMessages": TierUnimplemented, - "ListPluginActions": TierUnimplemented, - "ListPluginTypeActions": TierUnimplemented, - "ListPluginTypeMetadata": TierUnimplemented, - "ListPlugins": TierUnimplemented, - "ListRetrievers": TierUnimplemented, - "ListSubscriptions": TierUnimplemented, - "ListTagsForResource": TierUnimplemented, - "ListWebExperiences": TierUnimplemented, - "PutFeedback": TierUnimplemented, - "PutGroup": TierUnimplemented, + "GetApplication": TierAutoCRUD, + "GetChatControlsConfiguration": TierAutoCRUD, + "GetChatResponseConfiguration": TierAutoCRUD, + "GetDataAccessor": TierAutoCRUD, + "GetDataSource": TierAutoCRUD, + "GetDocumentContent": TierAutoCRUD, + "GetGroup": TierAutoCRUD, + "GetIndex": TierAutoCRUD, + "GetMedia": TierAutoCRUD, + "GetPlugin": TierAutoCRUD, + "GetPolicy": TierAutoCRUD, + "GetRetriever": TierAutoCRUD, + "GetUser": TierAutoCRUD, + "GetWebExperience": TierAutoCRUD, + "ListApplications": TierAutoCRUD, + "ListAttachments": TierAutoCRUD, + "ListChatResponseConfigurations": TierAutoCRUD, + "ListConversations": TierAutoCRUD, + "ListDataAccessors": TierAutoCRUD, + "ListDataSourceSyncJobs": TierAutoCRUD, + "ListDataSources": TierAutoCRUD, + "ListDocuments": TierAutoCRUD, + "ListGroups": TierAutoCRUD, + "ListIndices": TierAutoCRUD, + "ListMessages": TierAutoCRUD, + "ListPluginActions": TierAutoCRUD, + "ListPluginTypeActions": TierAutoCRUD, + "ListPluginTypeMetadata": TierAutoCRUD, + "ListPlugins": TierAutoCRUD, + "ListRetrievers": TierAutoCRUD, + "ListSubscriptions": TierAutoCRUD, + "ListTagsForResource": TierAutoCRUD, + "ListWebExperiences": TierAutoCRUD, + "PutFeedback": TierAutoCRUD, + "PutGroup": TierAutoCRUD, "SearchRelevantContent": TierUnimplemented, "StartDataSourceSyncJob": TierUnimplemented, "StopDataSourceSyncJob": TierUnimplemented, - "TagResource": TierUnimplemented, - "UntagResource": TierUnimplemented, - "UpdateApplication": TierUnimplemented, - "UpdateChatControlsConfiguration": TierUnimplemented, - "UpdateChatResponseConfiguration": TierUnimplemented, - "UpdateDataAccessor": TierUnimplemented, - "UpdateDataSource": TierUnimplemented, - "UpdateIndex": TierUnimplemented, - "UpdatePlugin": TierUnimplemented, - "UpdateRetriever": TierUnimplemented, - "UpdateSubscription": TierUnimplemented, - "UpdateUser": TierUnimplemented, - "UpdateWebExperience": TierUnimplemented, - }}, - "ram": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "TagResource": TierAutoCRUD, + "UntagResource": TierAutoCRUD, + "UpdateApplication": TierAutoCRUD, + "UpdateChatControlsConfiguration": TierAutoCRUD, + "UpdateChatResponseConfiguration": TierAutoCRUD, + "UpdateDataAccessor": TierAutoCRUD, + "UpdateDataSource": TierAutoCRUD, + "UpdateIndex": TierAutoCRUD, + "UpdatePlugin": TierAutoCRUD, + "UpdateRetriever": TierAutoCRUD, + "UpdateSubscription": TierAutoCRUD, + "UpdateUser": TierAutoCRUD, + "UpdateWebExperience": TierAutoCRUD, + }}, + "ram": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "AcceptResourceShareInvitation": TierHandVerified, "AssociateResourceShare": TierHandVerified, "AssociateResourceSharePermission": TierHandVerified, @@ -6931,7 +6941,7 @@ var Services = map[string]Service{ "UntagResource": TierHandVerified, "UpdateResourceShare": TierHandVerified, }}, - "rds": {Protocol: "query", ModelBacked: true, Operations: map[string]Tier{ + "rds": {Protocol: "query", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "AddRoleToDBCluster": TierUnimplemented, "AddRoleToDBInstance": TierUnimplemented, "AddSourceIdentifierToSubscription": TierUnimplemented, @@ -7096,7 +7106,7 @@ var Services = map[string]Service{ "SwitchoverGlobalCluster": TierUnimplemented, "SwitchoverReadReplica": TierUnimplemented, }}, - "redshift": {Protocol: "query", ModelBacked: true, Operations: map[string]Tier{ + "redshift": {Protocol: "query", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "AcceptReservedNodeExchange": TierUnimplemented, "AddPartner": TierUnimplemented, "AssociateDataShareConsumer": TierUnimplemented, @@ -7239,7 +7249,7 @@ var Services = map[string]Service{ "RotateEncryptionKey": TierUnimplemented, "UpdatePartnerStatus": TierUnimplemented, }}, - "rekognition": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "rekognition": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AssociateFaces": TierUnimplemented, "CompareFaces": TierUnimplemented, "CopyProjectVersion": TierUnimplemented, @@ -7316,7 +7326,7 @@ var Services = map[string]Service{ "UpdateDatasetEntries": TierAutoCRUD, "UpdateStreamProcessor": TierAutoCRUD, }}, - "resourcegroups": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "resourcegroups": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "CancelTagSyncTask": TierHandVerified, "CreateGroup": TierHandVerified, "DeleteGroup": TierHandVerified, @@ -7341,7 +7351,7 @@ var Services = map[string]Service{ "UpdateGroup": TierHandVerified, "UpdateGroupQuery": TierHandVerified, }}, - "resourcegroupstaggingapi": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "resourcegroupstaggingapi": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AssociateTags": TierHandVerified, "CreateTagOption": TierHandVerified, "DeleteTagOption": TierHandVerified, @@ -7365,7 +7375,7 @@ var Services = map[string]Service{ "UntagResources": TierHandVerified, "UpdateTagOption": TierHandVerified, }}, - "route53": {Protocol: "rest-xml", ModelBacked: true, Operations: map[string]Tier{ + "route53": {Protocol: "rest-xml", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "ActivateKeySigningKey": TierHandVerified, "AssociateVPCWithHostedZone": TierHandVerified, "ChangeCidrCollection": TierHandVerified, @@ -7439,7 +7449,7 @@ var Services = map[string]Service{ "UpdateTrafficPolicyComment": TierUnimplemented, "UpdateTrafficPolicyInstance": TierHandVerified, }}, - "route53resolver": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "route53resolver": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AssociateFirewallRuleGroup": TierHandVerified, "AssociateResolverEndpointIpAddress": TierHandVerified, "AssociateResolverQueryLogConfig": TierHandVerified, @@ -7509,7 +7519,7 @@ var Services = map[string]Service{ "UpdateResolverEndpoint": TierHandVerified, "UpdateResolverRule": TierHandVerified, }}, - "s3": {Protocol: "rest-xml", ModelBacked: true, Operations: map[string]Tier{ + "s3": {Protocol: "rest-xml", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "AbortMultipartUpload": TierHandVerified, "CompleteMultipartUpload": TierHandVerified, "CopyObject": TierHandVerified, @@ -7618,7 +7628,7 @@ var Services = map[string]Service{ "UploadPartCopy": TierUnimplemented, "WriteGetObjectResponse": TierUnimplemented, }}, - "s3tables": {Protocol: "", ModelBacked: false, Operations: map[string]Tier{ + "s3tables": {Protocol: "", ModelBacked: false, EngineWired: false, Operations: map[string]Tier{ "CreateNamespace": TierHandVerified, "CreateTable": TierHandVerified, "CreateTableBucket": TierHandVerified, @@ -7653,7 +7663,7 @@ var Services = map[string]Service{ "RenameTable": TierHandVerified, "UpdateTableMetadataLocation": TierHandVerified, }}, - "sagemaker": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "sagemaker": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AddAssociation": TierUnimplemented, "AddTags": TierHandVerified, "AssociateTrialComponent": TierUnimplemented, @@ -8036,67 +8046,67 @@ var Services = map[string]Service{ "UpdateWorkforce": TierAutoCRUD, "UpdateWorkteam": TierAutoCRUD, }}, - "sagemakera2iruntime": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ - "DeleteHumanLoop": TierUnimplemented, - "DescribeHumanLoop": TierUnimplemented, - "ListHumanLoops": TierUnimplemented, + "sagemakera2iruntime": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ + "DeleteHumanLoop": TierAutoCRUD, + "DescribeHumanLoop": TierAutoCRUD, + "ListHumanLoops": TierAutoCRUD, "StartHumanLoop": TierUnimplemented, "StopHumanLoop": TierUnimplemented, }}, - "sagemakeredge": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ - "GetDeployments": TierUnimplemented, - "GetDeviceRegistration": TierUnimplemented, + "sagemakeredge": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ + "GetDeployments": TierAutoCRUD, + "GetDeviceRegistration": TierAutoCRUD, "SendHeartbeat": TierUnimplemented, }}, - "sagemakerfeaturestoreruntime": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ - "BatchGetRecord": TierUnimplemented, + "sagemakerfeaturestoreruntime": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ + "BatchGetRecord": TierAutoCRUD, "BatchWriteRecord": TierUnimplemented, - "DeleteRecord": TierUnimplemented, - "GetRecord": TierUnimplemented, - "ListRecords": TierUnimplemented, - "PutRecord": TierUnimplemented, - "UpdateRecord": TierUnimplemented, - }}, - "sagemakergeospatial": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ - "DeleteEarthObservationJob": TierUnimplemented, - "DeleteVectorEnrichmentJob": TierUnimplemented, + "DeleteRecord": TierAutoCRUD, + "GetRecord": TierAutoCRUD, + "ListRecords": TierAutoCRUD, + "PutRecord": TierAutoCRUD, + "UpdateRecord": TierAutoCRUD, + }}, + "sagemakergeospatial": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ + "DeleteEarthObservationJob": TierAutoCRUD, + "DeleteVectorEnrichmentJob": TierAutoCRUD, "ExportEarthObservationJob": TierUnimplemented, "ExportVectorEnrichmentJob": TierUnimplemented, - "GetEarthObservationJob": TierUnimplemented, - "GetRasterDataCollection": TierUnimplemented, - "GetTile": TierUnimplemented, - "GetVectorEnrichmentJob": TierUnimplemented, - "ListEarthObservationJobs": TierUnimplemented, - "ListRasterDataCollections": TierUnimplemented, - "ListTagsForResource": TierUnimplemented, - "ListVectorEnrichmentJobs": TierUnimplemented, + "GetEarthObservationJob": TierAutoCRUD, + "GetRasterDataCollection": TierAutoCRUD, + "GetTile": TierAutoCRUD, + "GetVectorEnrichmentJob": TierAutoCRUD, + "ListEarthObservationJobs": TierAutoCRUD, + "ListRasterDataCollections": TierAutoCRUD, + "ListTagsForResource": TierAutoCRUD, + "ListVectorEnrichmentJobs": TierAutoCRUD, "SearchRasterDataCollection": TierUnimplemented, "StartEarthObservationJob": TierUnimplemented, "StartVectorEnrichmentJob": TierUnimplemented, "StopEarthObservationJob": TierUnimplemented, "StopVectorEnrichmentJob": TierUnimplemented, - "TagResource": TierUnimplemented, - "UntagResource": TierUnimplemented, + "TagResource": TierAutoCRUD, + "UntagResource": TierAutoCRUD, }}, - "sagemakerjobruntime": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "sagemakerjobruntime": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "CompleteRollout": TierUnimplemented, "Sample": TierUnimplemented, "SampleWithResponseStream": TierUnimplemented, - "UpdateReward": TierUnimplemented, + "UpdateReward": TierAutoCRUD, }}, - "sagemakermetrics": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ - "BatchGetMetrics": TierUnimplemented, + "sagemakermetrics": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ + "BatchGetMetrics": TierAutoCRUD, "BatchPutMetrics": TierUnimplemented, }}, - "sagemakerruntime": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "sagemakerruntime": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "InvokeEndpoint": TierUnimplemented, "InvokeEndpointAsync": TierUnimplemented, "InvokeEndpointWithResponseStream": TierUnimplemented, }}, - "sagemakerruntimehttp2": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "sagemakerruntimehttp2": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "InvokeEndpointWithBidirectionalStream": TierUnimplemented, }}, - "scheduler": {Protocol: "", ModelBacked: false, Operations: map[string]Tier{ + "scheduler": {Protocol: "", ModelBacked: false, EngineWired: false, Operations: map[string]Tier{ "BatchCheckMaxRateLimits": TierHandVerified, "BatchCreateSchedules": TierHandVerified, "BatchDeleteSchedules": TierHandVerified, @@ -8135,7 +8145,7 @@ var Services = map[string]Service{ "UpdateScheduleGroup": TierHandVerified, "ValidateScheduleExpression": TierHandVerified, }}, - "secretsmanager": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "secretsmanager": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "BatchGetSecretValue": TierHandVerified, "CancelRotateSecret": TierHandVerified, "ClearSecretValue": TierHandVerified, @@ -8177,7 +8187,7 @@ var Services = map[string]Service{ "ValidateResourcePolicy": TierHandVerified, "ValidateSecret": TierHandVerified, }}, - "serverlessrepo": {Protocol: "", ModelBacked: false, Operations: map[string]Tier{ + "serverlessrepo": {Protocol: "", ModelBacked: false, EngineWired: false, Operations: map[string]Tier{ "AddApplicationDependency": TierHandVerified, "CancelCloudFormationChangeSet": TierHandVerified, "CreateApplication": TierHandVerified, @@ -8220,7 +8230,7 @@ var Services = map[string]Service{ "UpdateApplication": TierHandVerified, "UpdateApplicationVersion": TierHandVerified, }}, - "servicediscovery": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "servicediscovery": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "CreateHttpNamespace": TierHandVerified, "CreatePrivateDnsNamespace": TierHandVerified, "CreatePublicDnsNamespace": TierHandVerified, @@ -8252,7 +8262,7 @@ var Services = map[string]Service{ "UpdateService": TierHandVerified, "UpdateServiceAttributes": TierHandVerified, }}, - "ses": {Protocol: "query", ModelBacked: true, Operations: map[string]Tier{ + "ses": {Protocol: "query", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "CloneReceiptRuleSet": TierHandVerified, "CreateConfigurationSet": TierHandVerified, "CreateConfigurationSetEventDestination": TierHandVerified, @@ -8330,7 +8340,7 @@ var Services = map[string]Service{ "VerifyEmailAddress": TierHandVerified, "VerifyEmailIdentity": TierHandVerified, }}, - "sesv2": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "sesv2": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "BatchGetMetricData": TierHandVerified, "CancelExportJob": TierHandVerified, "CreateConfigurationSet": TierHandVerified, @@ -8442,7 +8452,7 @@ var Services = map[string]Service{ "UpdateReputationEntityCustomerManagedStatus": TierHandVerified, "UpdateReputationEntityPolicy": TierHandVerified, }}, - "sfn": {Protocol: "json-1.0", ModelBacked: true, Operations: map[string]Tier{ + "sfn": {Protocol: "json-1.0", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "CreateActivity": TierHandVerified, "CreateStateMachine": TierHandVerified, "CreateStateMachineAlias": TierHandVerified, @@ -8481,7 +8491,7 @@ var Services = map[string]Service{ "UpdateStateMachineAlias": TierHandVerified, "ValidateStateMachineDefinition": TierHandVerified, }}, - "shield": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "shield": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AssociateDRTLogBucket": TierHandVerified, "AssociateDRTRole": TierHandVerified, "AssociateHealthCheck": TierHandVerified, @@ -8519,7 +8529,7 @@ var Services = map[string]Service{ "UpdateProtectionGroup": TierHandVerified, "UpdateSubscription": TierHandVerified, }}, - "sns": {Protocol: "query", ModelBacked: true, Operations: map[string]Tier{ + "sns": {Protocol: "query", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "AddPermission": TierHandVerified, "CheckIfPhoneNumberIsOptedOut": TierHandVerified, "ConfirmSubscription": TierHandVerified, @@ -8563,7 +8573,7 @@ var Services = map[string]Service{ "UntagResource": TierHandVerified, "VerifySMSSandboxPhoneNumber": TierUnimplemented, }}, - "sqs": {Protocol: "json-1.0", ModelBacked: true, Operations: map[string]Tier{ + "sqs": {Protocol: "json-1.0", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AddPermission": TierHandVerified, "CancelMessageMoveTask": TierHandVerified, "ChangeMessageVisibility": TierHandVerified, @@ -8588,7 +8598,7 @@ var Services = map[string]Service{ "TagQueue": TierHandVerified, "UntagQueue": TierHandVerified, }}, - "ssm": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "ssm": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AddTagsToResource": TierHandVerified, "AssociateOpsItemRelatedItem": TierUnimplemented, "CancelCommand": TierUnimplemented, @@ -8736,7 +8746,7 @@ var Services = map[string]Service{ "UpdateResourceDataSync": TierAutoCRUD, "UpdateServiceSetting": TierAutoCRUD, }}, - "ssoadmin": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "ssoadmin": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AddRegion": TierHandVerified, "AttachCustomerManagedPolicyReferenceToPermissionSet": TierHandVerified, "AttachManagedPolicyToPermissionSet": TierHandVerified, @@ -8817,7 +8827,7 @@ var Services = map[string]Service{ "UpdatePermissionSet": TierHandVerified, "UpdateTrustedTokenIssuer": TierHandVerified, }}, - "sts": {Protocol: "query", ModelBacked: true, Operations: map[string]Tier{ + "sts": {Protocol: "query", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "AssumeRole": TierHandVerified, "AssumeRoleWithSAML": TierUnimplemented, "AssumeRoleWithWebIdentity": TierUnimplemented, @@ -8830,7 +8840,7 @@ var Services = map[string]Service{ "GetSessionToken": TierHandVerified, "GetWebIdentityToken": TierUnimplemented, }}, - "support": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "support": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AddAttachmentsToSet": TierHandVerified, "AddCommunicationToCase": TierHandVerified, "CreateCase": TierHandVerified, @@ -8875,7 +8885,7 @@ var Services = map[string]Service{ "UpdateCaseAttributes": TierHandVerified, "UpdateSupportPlan": TierHandVerified, }}, - "swf": {Protocol: "json-1.0", ModelBacked: true, Operations: map[string]Tier{ + "swf": {Protocol: "json-1.0", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "CountClosedWorkflowExecutions": TierHandVerified, "CountOpenWorkflowExecutions": TierHandVerified, "CountPendingActivityTasks": TierHandVerified, @@ -8916,7 +8926,7 @@ var Services = map[string]Service{ "UndeprecateWorkflowType": TierHandVerified, "UntagResource": TierHandVerified, }}, - "textract": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "textract": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AnalyzeDocument": TierHandVerified, "AnalyzeExpense": TierHandVerified, "AnalyzeID": TierHandVerified, @@ -8964,7 +8974,7 @@ var Services = map[string]Service{ "UntagResource": TierHandVerified, "UpdateAdapter": TierHandVerified, }}, - "timestreamwrite": {Protocol: "json-1.0", ModelBacked: true, Operations: map[string]Tier{ + "timestreamwrite": {Protocol: "json-1.0", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "CreateBatchLoadTask": TierHandVerified, "CreateDatabase": TierHandVerified, "CreateTable": TierHandVerified, @@ -8985,7 +8995,7 @@ var Services = map[string]Service{ "UpdateTable": TierHandVerified, "WriteRecords": TierHandVerified, }}, - "transcribe": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "transcribe": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "CreateCallAnalyticsCategory": TierHandVerified, "CreateLanguageModel": TierHandVerified, "CreateMedicalVocabulary": TierHandVerified, @@ -9030,14 +9040,14 @@ var Services = map[string]Service{ "UpdateVocabulary": TierHandVerified, "UpdateVocabularyFilter": TierHandVerified, }}, - "transcribestreaming": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ - "GetMedicalScribeStream": TierUnimplemented, + "transcribestreaming": {Protocol: "rest-json", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ + "GetMedicalScribeStream": TierAutoCRUD, "StartCallAnalyticsStreamTranscription": TierUnimplemented, "StartMedicalScribeStream": TierUnimplemented, "StartMedicalStreamTranscription": TierUnimplemented, "StartStreamTranscription": TierUnimplemented, }}, - "transfer": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "transfer": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "CreateAccess": TierHandVerified, "CreateAgreement": TierAutoCRUD, "CreateConnector": TierAutoCRUD, @@ -9110,7 +9120,7 @@ var Services = map[string]Service{ "UpdateWebApp": TierAutoCRUD, "UpdateWebAppCustomization": TierAutoCRUD, }}, - "translate": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "translate": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "CreateParallelData": TierAutoCRUD, "DeleteParallelData": TierAutoCRUD, "DeleteTerminology": TierAutoCRUD, @@ -9131,7 +9141,7 @@ var Services = map[string]Service{ "UntagResource": TierAutoCRUD, "UpdateParallelData": TierAutoCRUD, }}, - "verifiedpermissions": {Protocol: "", ModelBacked: false, Operations: map[string]Tier{ + "verifiedpermissions": {Protocol: "", ModelBacked: false, EngineWired: false, Operations: map[string]Tier{ "BatchEvaluatePermissions": TierHandVerified, "BatchGetEntityRelationship": TierHandVerified, "CreateEntityRelationship": TierHandVerified, @@ -9169,7 +9179,7 @@ var Services = map[string]Service{ "PutPolicyTemplate": TierHandVerified, "PutSchema": TierHandVerified, }}, - "voiceid": {Protocol: "json-1.0", ModelBacked: true, Operations: map[string]Tier{ + "voiceid": {Protocol: "json-1.0", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AssociateFraudster": TierUnimplemented, "CreateDomain": TierAutoCRUD, "CreateWatchlist": TierAutoCRUD, @@ -9200,7 +9210,7 @@ var Services = map[string]Service{ "UpdateDomain": TierAutoCRUD, "UpdateWatchlist": TierAutoCRUD, }}, - "waf": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "waf": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "CreateByteMatchSet": TierHandVerified, "CreateGeoMatchSet": TierHandVerified, "CreateIPSet": TierHandVerified, @@ -9279,7 +9289,7 @@ var Services = map[string]Service{ "UpdateWebACL": TierHandVerified, "UpdateXssMatchSet": TierHandVerified, }}, - "wafv2": {Protocol: "json-1.1", ModelBacked: true, Operations: map[string]Tier{ + "wafv2": {Protocol: "json-1.1", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AssociateWebACL": TierHandVerified, "CheckCapacity": TierHandVerified, "CreateAPIKey": TierHandVerified, @@ -9336,7 +9346,7 @@ var Services = map[string]Service{ "UpdateRuleGroup": TierHandVerified, "UpdateWebACL": TierHandVerified, }}, - "xray": {Protocol: "rest-json", ModelBacked: true, Operations: map[string]Tier{ + "xray": {Protocol: "rest-json", ModelBacked: true, EngineWired: false, Operations: map[string]Tier{ "BatchGetTraces": TierHandVerified, "CancelTraceRetrieval": TierUnimplemented, "CreateGroup": TierHandVerified, diff --git a/internal/generated/firehose/router.go b/internal/generated/firehose/router.go index 274e1252..9677b611 100644 --- a/internal/generated/firehose/router.go +++ b/internal/generated/firehose/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package firehose -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -40,126 +33,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/fis/router.go b/internal/generated/fis/router.go index d74d4cac..71a9d906 100644 --- a/internal/generated/fis/router.go +++ b/internal/generated/fis/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package fis -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -54,126 +47,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/forecast/router.go b/internal/generated/forecast/router.go index 0935d29a..93ba5977 100644 --- a/internal/generated/forecast/router.go +++ b/internal/generated/forecast/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package forecast -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -91,126 +84,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/forecastquery/router.go b/internal/generated/forecastquery/router.go index 34e85a5e..c21df4b7 100644 --- a/internal/generated/forecastquery/router.go +++ b/internal/generated/forecastquery/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package forecastquery -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -30,126 +23,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/frauddetector/router.go b/internal/generated/frauddetector/router.go index 4a34e070..524dc0d4 100644 --- a/internal/generated/frauddetector/router.go +++ b/internal/generated/frauddetector/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package frauddetector -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -101,126 +94,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/glacier/router.go b/internal/generated/glacier/router.go index 869c2187..572ffb06 100644 --- a/internal/generated/glacier/router.go +++ b/internal/generated/glacier/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package glacier -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -61,126 +54,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/glue/router.go b/internal/generated/glue/router.go index 34b279d5..0c97d13b 100644 --- a/internal/generated/glue/router.go +++ b/internal/generated/glue/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package glue -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -293,126 +286,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/healthlake/router.go b/internal/generated/healthlake/router.go index 203c31ab..22a92b77 100644 --- a/internal/generated/healthlake/router.go +++ b/internal/generated/healthlake/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package healthlake -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -54,126 +47,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/iam/router.go b/internal/generated/iam/router.go index 65b3549c..cce5b751 100644 --- a/internal/generated/iam/router.go +++ b/internal/generated/iam/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package iam -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -204,126 +197,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/iot/router.go b/internal/generated/iot/router.go index a148480a..08f40de2 100644 --- a/internal/generated/iot/router.go +++ b/internal/generated/iot/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package iot -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -300,126 +293,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/iotdataplane/router.go b/internal/generated/iotdataplane/router.go index 523df8bd..142014be 100644 --- a/internal/generated/iotdataplane/router.go +++ b/internal/generated/iotdataplane/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package iotdataplane -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -36,126 +29,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/iotwireless/router.go b/internal/generated/iotwireless/router.go index 6ee6168b..13835f1e 100644 --- a/internal/generated/iotwireless/router.go +++ b/internal/generated/iotwireless/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package iotwireless -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -140,126 +133,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/kafka/router.go b/internal/generated/kafka/router.go index a2904c33..bd39da93 100644 --- a/internal/generated/kafka/router.go +++ b/internal/generated/kafka/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package kafka -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -87,126 +80,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/kendra/router.go b/internal/generated/kendra/router.go index 553669de..8c9fdcfd 100644 --- a/internal/generated/kendra/router.go +++ b/internal/generated/kendra/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package kendra -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -94,126 +87,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/kendraranking/router.go b/internal/generated/kendraranking/router.go index 781fd974..042dd68d 100644 --- a/internal/generated/kendraranking/router.go +++ b/internal/generated/kendraranking/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package kendraranking -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -37,126 +30,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/kinesis/router.go b/internal/generated/kinesis/router.go index 42ded85c..1d113f44 100644 --- a/internal/generated/kinesis/router.go +++ b/internal/generated/kinesis/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package kinesis -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -67,126 +60,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/kinesisanalyticsv2/router.go b/internal/generated/kinesisanalyticsv2/router.go index 2a2f4e29..093c1018 100644 --- a/internal/generated/kinesisanalyticsv2/router.go +++ b/internal/generated/kinesisanalyticsv2/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package kinesisanalyticsv2 -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -61,126 +54,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/kms/router.go b/internal/generated/kms/router.go index 4f2a4e95..de38d9f5 100644 --- a/internal/generated/kms/router.go +++ b/internal/generated/kms/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package kms -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -81,126 +74,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/lakeformation/router.go b/internal/generated/lakeformation/router.go index c0e009cd..6f30239f 100644 --- a/internal/generated/lakeformation/router.go +++ b/internal/generated/lakeformation/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package lakeformation -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -89,126 +82,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/lambda/router.go b/internal/generated/lambda/router.go index bcdb9720..8b3f04d8 100644 --- a/internal/generated/lambda/router.go +++ b/internal/generated/lambda/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package lambda -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -113,126 +106,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/lexmodelbuildingservice/router.go b/internal/generated/lexmodelbuildingservice/router.go index 78572506..ec3085d7 100644 --- a/internal/generated/lexmodelbuildingservice/router.go +++ b/internal/generated/lexmodelbuildingservice/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package lexmodelbuildingservice -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -70,126 +63,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/lexmodelsv2/router.go b/internal/generated/lexmodelsv2/router.go index 7e4c09ab..41c08343 100644 --- a/internal/generated/lexmodelsv2/router.go +++ b/internal/generated/lexmodelsv2/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package lexmodelsv2 -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -135,126 +128,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/lexruntimeservice/router.go b/internal/generated/lexruntimeservice/router.go index 935beb45..9bada19b 100644 --- a/internal/generated/lexruntimeservice/router.go +++ b/internal/generated/lexruntimeservice/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package lexruntimeservice -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -33,126 +26,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/lexruntimev2/router.go b/internal/generated/lexruntimev2/router.go index 045b0c6d..00d3e310 100644 --- a/internal/generated/lexruntimev2/router.go +++ b/internal/generated/lexruntimev2/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package lexruntimev2 -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -34,126 +27,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/lookoutequipment/router.go b/internal/generated/lookoutequipment/router.go index 665597a5..a49134ab 100644 --- a/internal/generated/lookoutequipment/router.go +++ b/internal/generated/lookoutequipment/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package lookoutequipment -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -77,126 +70,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/managedblockchain/router.go b/internal/generated/managedblockchain/router.go index 62b78912..77baa239 100644 --- a/internal/generated/managedblockchain/router.go +++ b/internal/generated/managedblockchain/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package managedblockchain -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -55,126 +48,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/memorydb/router.go b/internal/generated/memorydb/router.go index 9ae1ebf7..99797bf6 100644 --- a/internal/generated/memorydb/router.go +++ b/internal/generated/memorydb/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package memorydb -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -73,126 +66,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/mq/router.go b/internal/generated/mq/router.go index 4720387f..23cf4aec 100644 --- a/internal/generated/mq/router.go +++ b/internal/generated/mq/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package mq -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -52,126 +45,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/mwaa/router.go b/internal/generated/mwaa/router.go index 72351c13..a36e1930 100644 --- a/internal/generated/mwaa/router.go +++ b/internal/generated/mwaa/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package mwaa -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -40,126 +33,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/neptune/router.go b/internal/generated/neptune/router.go index 499384d1..53c4efa6 100644 --- a/internal/generated/neptune/router.go +++ b/internal/generated/neptune/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package neptune -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -98,126 +91,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/omics/router.go b/internal/generated/omics/router.go index 8b350245..2931420b 100644 --- a/internal/generated/omics/router.go +++ b/internal/generated/omics/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package omics -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -135,126 +128,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/opensearch/router.go b/internal/generated/opensearch/router.go index d95df00d..ec6c27ff 100644 --- a/internal/generated/opensearch/router.go +++ b/internal/generated/opensearch/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package opensearch -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -115,126 +108,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/organizations/router.go b/internal/generated/organizations/router.go index 7ac5674e..2bb239c6 100644 --- a/internal/generated/organizations/router.go +++ b/internal/generated/organizations/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package organizations -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -91,126 +84,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/personalize/router.go b/internal/generated/personalize/router.go index fd5e3311..42a00416 100644 --- a/internal/generated/personalize/router.go +++ b/internal/generated/personalize/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package personalize -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -99,126 +92,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/personalizeevents/router.go b/internal/generated/personalizeevents/router.go index 83a0c6e8..f597ff51 100644 --- a/internal/generated/personalizeevents/router.go +++ b/internal/generated/personalizeevents/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package personalizeevents -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -33,126 +26,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/personalizeruntime/router.go b/internal/generated/personalizeruntime/router.go index e2466025..d6652d9c 100644 --- a/internal/generated/personalizeruntime/router.go +++ b/internal/generated/personalizeruntime/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package personalizeruntime -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -31,126 +24,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/pinpoint/router.go b/internal/generated/pinpoint/router.go index d2f1d86a..2ae44cab 100644 --- a/internal/generated/pinpoint/router.go +++ b/internal/generated/pinpoint/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package pinpoint -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -150,126 +143,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/polly/router.go b/internal/generated/polly/router.go index 4398dd0c..01ca2ef9 100644 --- a/internal/generated/polly/router.go +++ b/internal/generated/polly/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package polly -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -38,126 +31,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/qapps/router.go b/internal/generated/qapps/router.go index 91de7375..deae8eb1 100644 --- a/internal/generated/qapps/router.go +++ b/internal/generated/qapps/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package qapps -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -63,126 +56,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/qbusiness/router.go b/internal/generated/qbusiness/router.go index ba272db5..bab6b04c 100644 --- a/internal/generated/qbusiness/router.go +++ b/internal/generated/qbusiness/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package qbusiness -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -111,126 +104,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/ram/router.go b/internal/generated/ram/router.go index 17fdfe2a..80155097 100644 --- a/internal/generated/ram/router.go +++ b/internal/generated/ram/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package ram -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -63,126 +56,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/rds/router.go b/internal/generated/rds/router.go index 6bd85fa9..8f8ee8a0 100644 --- a/internal/generated/rds/router.go +++ b/internal/generated/rds/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package rds -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -191,126 +184,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/redshift/router.go b/internal/generated/redshift/router.go index 6361830b..2e048140 100644 --- a/internal/generated/redshift/router.go +++ b/internal/generated/redshift/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package redshift -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -169,126 +162,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/rekognition/router.go b/internal/generated/rekognition/router.go index a50f3187..ffd53d5c 100644 --- a/internal/generated/rekognition/router.go +++ b/internal/generated/rekognition/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package rekognition -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -103,126 +96,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/resourcegroups/router.go b/internal/generated/resourcegroups/router.go index a3ef894b..114443b0 100644 --- a/internal/generated/resourcegroups/router.go +++ b/internal/generated/resourcegroups/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package resourcegroups -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -51,126 +44,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/resourcegroupstaggingapi/router.go b/internal/generated/resourcegroupstaggingapi/router.go index a20a0b84..6af6ddd9 100644 --- a/internal/generated/resourcegroupstaggingapi/router.go +++ b/internal/generated/resourcegroupstaggingapi/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package resourcegroupstaggingapi -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -37,126 +30,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/route53/router.go b/internal/generated/route53/router.go index 0d33bac6..0f75aac1 100644 --- a/internal/generated/route53/router.go +++ b/internal/generated/route53/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package route53 -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -99,126 +92,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/route53resolver/router.go b/internal/generated/route53resolver/router.go index 012ac76c..bbea1075 100644 --- a/internal/generated/route53resolver/router.go +++ b/internal/generated/route53resolver/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package route53resolver -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -96,126 +89,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/s3/router.go b/internal/generated/s3/router.go index 22c4dbca..08e0e03e 100644 --- a/internal/generated/s3/router.go +++ b/internal/generated/s3/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package s3 -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -135,126 +128,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/sagemaker/router.go b/internal/generated/sagemaker/router.go index b8d03268..5c0d84a9 100644 --- a/internal/generated/sagemaker/router.go +++ b/internal/generated/sagemaker/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package sagemaker -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -409,126 +402,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/sagemakera2iruntime/router.go b/internal/generated/sagemakera2iruntime/router.go index cc5569f9..11ea7e66 100644 --- a/internal/generated/sagemakera2iruntime/router.go +++ b/internal/generated/sagemakera2iruntime/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package sagemakera2iruntime -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -33,126 +26,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/sagemakeredge/router.go b/internal/generated/sagemakeredge/router.go index b367e4fe..61a24510 100644 --- a/internal/generated/sagemakeredge/router.go +++ b/internal/generated/sagemakeredge/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package sagemakeredge -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -31,126 +24,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/sagemakerfeaturestoreruntime/router.go b/internal/generated/sagemakerfeaturestoreruntime/router.go index 0f22bb5f..5a281d2d 100644 --- a/internal/generated/sagemakerfeaturestoreruntime/router.go +++ b/internal/generated/sagemakerfeaturestoreruntime/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package sagemakerfeaturestoreruntime -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -35,126 +28,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/sagemakergeospatial/router.go b/internal/generated/sagemakergeospatial/router.go index 42e9020b..7d6217b6 100644 --- a/internal/generated/sagemakergeospatial/router.go +++ b/internal/generated/sagemakergeospatial/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package sagemakergeospatial -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -47,126 +40,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/sagemakerjobruntime/router.go b/internal/generated/sagemakerjobruntime/router.go index 765cdd95..84696097 100644 --- a/internal/generated/sagemakerjobruntime/router.go +++ b/internal/generated/sagemakerjobruntime/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package sagemakerjobruntime -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -32,126 +25,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/sagemakermetrics/router.go b/internal/generated/sagemakermetrics/router.go index 058b74aa..d808a3cf 100644 --- a/internal/generated/sagemakermetrics/router.go +++ b/internal/generated/sagemakermetrics/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package sagemakermetrics -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -30,126 +23,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/sagemakerruntime/router.go b/internal/generated/sagemakerruntime/router.go index 0146e830..6ab4a088 100644 --- a/internal/generated/sagemakerruntime/router.go +++ b/internal/generated/sagemakerruntime/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package sagemakerruntime -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -31,126 +24,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/sagemakerruntimehttp2/router.go b/internal/generated/sagemakerruntimehttp2/router.go index f0a1667f..e159fe0d 100644 --- a/internal/generated/sagemakerruntimehttp2/router.go +++ b/internal/generated/sagemakerruntimehttp2/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package sagemakerruntimehttp2 -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -29,126 +22,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/secretsmanager/router.go b/internal/generated/secretsmanager/router.go index 6a21c720..9cdd29e9 100644 --- a/internal/generated/secretsmanager/router.go +++ b/internal/generated/secretsmanager/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package secretsmanager -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -51,126 +44,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/servicediscovery/router.go b/internal/generated/servicediscovery/router.go index 55c3b9e9..ca224168 100644 --- a/internal/generated/servicediscovery/router.go +++ b/internal/generated/servicediscovery/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package servicediscovery -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -58,126 +51,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/ses/router.go b/internal/generated/ses/router.go index 995d9536..3cd96566 100644 --- a/internal/generated/ses/router.go +++ b/internal/generated/ses/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package ses -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -99,126 +92,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/sesv2/router.go b/internal/generated/sesv2/router.go index a9de8d0c..d9523d50 100644 --- a/internal/generated/sesv2/router.go +++ b/internal/generated/sesv2/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package sesv2 -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -138,126 +131,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/sfn/router.go b/internal/generated/sfn/router.go index afcdc077..d45a57b9 100644 --- a/internal/generated/sfn/router.go +++ b/internal/generated/sfn/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package sfn -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -65,126 +58,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/shield/router.go b/internal/generated/shield/router.go index 016db791..e1d42748 100644 --- a/internal/generated/shield/router.go +++ b/internal/generated/shield/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package shield -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -64,126 +57,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/sns/router.go b/internal/generated/sns/router.go index 538ff78f..996aecb9 100644 --- a/internal/generated/sns/router.go +++ b/internal/generated/sns/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package sns -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -70,126 +63,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/sqs/router.go b/internal/generated/sqs/router.go index 10845b17..a3ad87fd 100644 --- a/internal/generated/sqs/router.go +++ b/internal/generated/sqs/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package sqs -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -51,126 +44,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/ssm/router.go b/internal/generated/ssm/router.go index 95fdcaf9..d3a3c3c0 100644 --- a/internal/generated/ssm/router.go +++ b/internal/generated/ssm/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package ssm -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -174,126 +167,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/ssoadmin/router.go b/internal/generated/ssoadmin/router.go index 06534fff..c17178b9 100644 --- a/internal/generated/ssoadmin/router.go +++ b/internal/generated/ssoadmin/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package ssoadmin -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -107,126 +100,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/support/router.go b/internal/generated/support/router.go index 798fd37e..67d552cd 100644 --- a/internal/generated/support/router.go +++ b/internal/generated/support/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package support -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -44,126 +37,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/swf/router.go b/internal/generated/swf/router.go index e23e1cc6..3fd51b15 100644 --- a/internal/generated/swf/router.go +++ b/internal/generated/swf/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package swf -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -67,126 +60,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/textract/router.go b/internal/generated/textract/router.go index 4871026e..222023f5 100644 --- a/internal/generated/textract/router.go +++ b/internal/generated/textract/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package textract -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -53,126 +46,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/timestreamwrite/router.go b/internal/generated/timestreamwrite/router.go index 7f506eaa..00031e3a 100644 --- a/internal/generated/timestreamwrite/router.go +++ b/internal/generated/timestreamwrite/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package timestreamwrite -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -47,126 +40,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/transcribe/router.go b/internal/generated/transcribe/router.go index 8616414b..f13e4d22 100644 --- a/internal/generated/transcribe/router.go +++ b/internal/generated/transcribe/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package transcribe -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -71,126 +64,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/transcribestreaming/router.go b/internal/generated/transcribestreaming/router.go index de2f43d2..ccbe67c2 100644 --- a/internal/generated/transcribestreaming/router.go +++ b/internal/generated/transcribestreaming/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package transcribestreaming -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -33,126 +26,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/transfer/router.go b/internal/generated/transfer/router.go index 3b4c5b6e..d34e92d3 100644 --- a/internal/generated/transfer/router.go +++ b/internal/generated/transfer/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package transfer -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -99,126 +92,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/translate/router.go b/internal/generated/translate/router.go index ef8390f5..98b36c8c 100644 --- a/internal/generated/translate/router.go +++ b/internal/generated/translate/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package translate -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -47,126 +40,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/voiceid/router.go b/internal/generated/voiceid/router.go index 3e866e2d..2c8f9094 100644 --- a/internal/generated/voiceid/router.go +++ b/internal/generated/voiceid/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package voiceid -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -57,126 +50,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/waf/router.go b/internal/generated/waf/router.go index e5155e7a..ecd85f21 100644 --- a/internal/generated/waf/router.go +++ b/internal/generated/waf/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package waf -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -105,126 +98,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/wafv2/router.go b/internal/generated/wafv2/router.go index a6e98f05..aa2cb0e3 100644 --- a/internal/generated/wafv2/router.go +++ b/internal/generated/wafv2/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package wafv2 -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -83,126 +76,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/generated/xray/router.go b/internal/generated/xray/router.go index cf6425fa..a8bb195a 100644 --- a/internal/generated/xray/router.go +++ b/internal/generated/xray/router.go @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 package xray -import ( - "net/url" - "strings" -) +import "github.com/skyoo2003/devcloud/internal/shared/httproute" // PathParams holds the URL path parameters extracted by the router. -type PathParams map[string]string +type PathParams = httproute.Params // OperationRoute maps an HTTP method and URI pattern to an operation name. -type OperationRoute struct { - Method string - Pattern string - Operation string -} +type OperationRoute = httproute.Route // OperationRoutes is the list of all routes for this service. var OperationRoutes = []OperationRoute{ @@ -66,126 +59,10 @@ var OperationRoutes = []OperationRoute{ // Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are // distinguished only by a query string (".../tagging?Operation=Tag"), and a // bare path can never satisfy those routes. +// +// The matching itself lives in internal/shared/httproute so the generic CRUD +// engine resolves a rest-json operation exactly the way this router does, +// rather than carrying a second copy of the algorithm. func MatchOperation(method, uri string) (string, PathParams) { - // Two passes. A route that constrains the query is more specific than one - // that does not, and OperationRoutes is ordered by operation name rather - // than specificity — so trying constrained routes first keeps - // ".../distribution" from shadowing ".../distribution?WithTags". - for _, constrained := range []bool{true, false} { - for _, route := range OperationRoutes { - if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { - continue - } - if params, ok := matchURI(route.Pattern, uri); ok { - return route.Operation, params - } - } - } - return "", nil -} - -// matchURI matches a request URI against a pattern that may contain {Label} and -// {Label+} (greedy) segments, and may constrain the query string after a "?". -// Returns the extracted parameters and true on match, or nil and false -// otherwise. -func matchURI(pattern, uri string) (PathParams, bool) { - patPath, patQuery, _ := strings.Cut(pattern, "?") - uriPath, uriQuery, _ := strings.Cut(uri, "?") - if !matchQuery(patQuery, uriQuery) { - return nil, false - } - - patParts := splitPath(patPath) - pathParts := splitPath(uriPath) - - params := PathParams{} - pi := 0 - for i, pat := range patParts { - if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { - // Greedy label: consumes all remaining path segments. - label := pat[1 : len(pat)-2] - if pi >= len(pathParts) { - return nil, false - } - params[label] = joinPath(pathParts[pi:]) - pi = len(pathParts) - // Greedy must be the last pattern segment. - if i != len(patParts)-1 { - return nil, false - } - } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { - // Single-segment label. - label := pat[1 : len(pat)-1] - if pi >= len(pathParts) { - return nil, false - } - params[label] = pathParts[pi] - pi++ - } else { - // Literal segment. - if pi >= len(pathParts) || pathParts[pi] != pat { - return nil, false - } - pi++ - } - } - if pi != len(pathParts) { - return nil, false - } - return params, true -} - -// matchQuery reports whether a request's query string satisfies the constraint -// a route pattern carries after its "?". Each "&"-separated term is either a -// bare key that must be present ("?WithTags") or a key=value that must be -// present with that value ("?Operation=Tag"). An empty constraint matches -// anything, which is every route that has no "?". -func matchQuery(constraint, query string) bool { - if constraint == "" { - return true - } - // ParseQuery returns what it could parse alongside any error, so a - // malformed tail cannot hide a valid term earlier in the string. - values, _ := url.ParseQuery(query) - for _, term := range strings.Split(constraint, "&") { - if term == "" { - continue - } - key, want, hasValue := strings.Cut(term, "=") - got, present := values[key] - if !present { - return false - } - if !hasValue { - continue - } - matched := false - for _, v := range got { - if v == want { - matched = true - break - } - } - if !matched { - return false - } - } - return true -} - -// splitPath splits a URI path into non-empty segments. -func splitPath(path string) []string { - parts := strings.Split(strings.Trim(path, "/"), "/") - out := parts[:0] - for _, p := range parts { - if p != "" { - out = append(out, p) - } - } - return out -} - -// joinPath joins path segments back with "/" separators. -func joinPath(parts []string) string { - return strings.Join(parts, "/") + return httproute.Match(OperationRoutes, method, uri) } diff --git a/internal/shared/crud/crud.go b/internal/shared/crud/crud.go index df47d8f7..c0887795 100644 --- a/internal/shared/crud/crud.go +++ b/internal/shared/crud/crud.go @@ -17,9 +17,13 @@ import ( "encoding/json" "errors" "maps" + "net/url" + "sort" "strings" "sync" "time" + + "github.com/skyoo2003/devcloud/internal/shared/httproute" ) // ErrUnclassified means the engine has no CRUD handling for this operation; the @@ -33,6 +37,26 @@ type OpMeta struct { Resource string // singular resource key, e.g. "Database" OutputListKey string // output member holding the collection (List ops) OutputItemKey string // output member wrapping a single resource ("" = flat echo) + + // Method and URI are the operation's REST binding, empty for a service + // whose protocol has none. They are what lets the engine serve rest-json: + // that protocol puts the operation in the method and path instead of in an + // X-Amz-Target header, so without them there is nothing to classify. + Method string // e.g. "GET" + URI string // e.g. "/v1/graphs/{GraphName}" +} + +// Call is one request the engine may be asked to serve, in protocol-neutral +// terms. The JSON protocols name the operation in a header, so they set Op; the +// REST protocols put it in the method and path, so they set Method and URI and +// leave Op empty. +type Call struct { + Service string + Protocol string + Op string + Method string + URI string + Body []byte } // Result is a protocol-agnostic response the caller maps onto its transport. @@ -42,11 +66,18 @@ type Result struct { ContentType string } -const jsonContentType = "application/x-amz-json-1.1" +const ( + jsonContentType = "application/x-amz-json-1.1" + restJSONType = "application/json" + + protocolJSON10 = "json-1.0" + protocolRESTJSON = "rest-json" +) var ( mu sync.RWMutex registry = map[string]map[string]OpMeta{} // service -> op -> meta + routes = map[string][]httproute.Route{} // service -> REST routes, sorted by operation store = map[string]map[string]map[string]any{} // "service|resource" -> id -> doc ) @@ -56,6 +87,21 @@ func Register(service string, ops map[string]OpMeta) { mu.Lock() defer mu.Unlock() registry[service] = ops + + // Build the REST route table alongside the op map. Sorted by operation + // name because Go map iteration is randomised, and httproute.Match takes + // the first route that fits within a specificity pass — an unsorted table + // would make routing differ between runs of the same binary. The order + // mirrors what codegen emits for the generated per-service routers. + rs := make([]httproute.Route, 0, len(ops)) + for op, m := range ops { + if m.URI == "" { + continue + } + rs = append(rs, httproute.Route{Method: m.Method, Pattern: m.URI, Operation: op}) + } + sort.Slice(rs, func(i, j int) bool { return rs[i].Operation < rs[j].Operation }) + routes[service] = rs } // RegisteredOps returns the operation metadata registered for a service. @@ -65,46 +111,116 @@ func RegisteredOps(service string) map[string]OpMeta { return registry[service] } -// JSONProtocol reports whether the engine can serve requests for a protocol. -// Only the X-Amz-Target JSON protocols carry an operation name at the router, -// which the engine needs to classify. +// JSONProtocol reports whether a protocol carries the operation name in an +// X-Amz-Target header. It says nothing about whether the engine can serve the +// protocol — use Servable for that. func JSONProtocol(protocol string) bool { return strings.HasPrefix(protocol, "json") } -// Handle attempts to serve op for service from its request body. It returns -// ErrUnclassified when the operation is unknown or not CRUD-shaped. -func Handle(service, op, protocol string, body []byte) (*Result, error) { - if !JSONProtocol(protocol) { +// Servable reports whether the engine can serve requests for a protocol. +// +// The JSON protocols carry the operation name in a header. rest-json does not, +// but its model binds every operation to a method and URI template, which the +// route table turns back into an operation name. query and rest-xml have +// neither, so a request for one of them cannot be classified at all and is +// declined rather than guessed at. +func Servable(protocol string) bool { + return JSONProtocol(protocol) || protocol == protocolRESTJSON +} + +// Handle attempts to serve a call from the service's registered operations. It +// returns ErrUnclassified when the operation is unknown, not CRUD-shaped, or +// carried by a protocol the engine cannot read — never a fabricated success. +func Handle(c Call) (*Result, error) { + op := c.Op + var labels httproute.Params + rest := false + + switch { + case JSONProtocol(c.Protocol): + // The operation name arrived in X-Amz-Target; nothing to resolve. + case c.Protocol == protocolRESTJSON: + rest = true + mu.RLock() + rs := routes[c.Service] + mu.RUnlock() + // A miss here is any of: unregistered service, an operation codegen + // refused to classify, or a path this service does not model. All + // three must decline — see docs/coverage.md on why a registered + // service must never fabricate a success. + if op, labels = httproute.Match(rs, c.Method, c.URI); op == "" { + return nil, ErrUnclassified + } + default: return nil, ErrUnclassified } + mu.RLock() - m, ok := registry[service][op] + m, ok := registry[c.Service][op] mu.RUnlock() if !ok || m.Verb == "" { return nil, ErrUnclassified } - var params map[string]any - if len(body) > 0 { - if err := json.Unmarshal(body, ¶ms); err != nil { + params := map[string]any{} + // Three sources, least authoritative first: httpQuery values, then the + // JSON body, then the path labels — the URI is what addresses the + // resource, so it wins. A restJson1 model never binds one member to two of + // these, so real SDK traffic never exercises the precedence; it is here so + // a hand-rolled request cannot redirect a lookup from the body. + if rest { + maps.Copy(params, queryParams(c.URI)) + } + if len(c.Body) > 0 { + var body map[string]any + if err := json.Unmarshal(c.Body, &body); err != nil { // Malformed body: real services reject with SerializationException // rather than fabricating a success from empty params. - return withContentType(serializationError(), protocol), nil + return withContentType(serializationError(), c.Protocol), nil } + maps.Copy(params, body) + } + for k, v := range labels { + params[k] = v + } + + res, err := dispatch(c.Service, m, params) + return withContentType(res, c.Protocol), err +} + +// queryParams reads the request URI's query string as engine parameters. A +// repeated key keeps its first value: the engine has no list-valued parameter, +// and dropping the key entirely would lose a resource identifier. +func queryParams(uri string) map[string]any { + _, query, found := strings.Cut(uri, "?") + if !found || query == "" { + return nil } - if params == nil { - params = map[string]any{} + // ParseQuery returns what it could parse alongside any error, so a + // malformed tail cannot discard the terms before it. + values, _ := url.ParseQuery(query) + out := make(map[string]any, len(values)) + for k, vs := range values { + if len(vs) > 0 { + out[k] = vs[0] + } } - res, err := dispatch(service, m, params) - return withContentType(res, protocol), err + return out } -// withContentType stamps the protocol-appropriate amz-json version so a json-1.0 -// service is not served a 1.1 content type. dispatch/okJSON default to 1.1. +// withContentType stamps the protocol-appropriate content type so a json-1.0 +// service is not served a 1.1 one, and a rest-json service is not served an +// X-Amz-Target type it never uses. dispatch/okJSON default to amz-json 1.1. func withContentType(res *Result, protocol string) *Result { - if res != nil && protocol == "json-1.0" { + if res == nil { + return res + } + switch protocol { + case protocolJSON10: res.ContentType = "application/x-amz-json-1.0" + case protocolRESTJSON: + res.ContentType = restJSONType } return res } diff --git a/internal/shared/crud/crud_test.go b/internal/shared/crud/crud_test.go index 9a4a5d1b..f90d5429 100644 --- a/internal/shared/crud/crud_test.go +++ b/internal/shared/crud/crud_test.go @@ -11,7 +11,7 @@ import ( func handleJSON(t *testing.T, service, op string, params map[string]any) (*Result, error) { t.Helper() body, _ := json.Marshal(params) - return Handle(service, op, "json-1.1", body) + return Handle(Call{Service: service, Protocol: "json-1.1", Op: op, Body: body}) } func decode(t *testing.T, r *Result) map[string]any { @@ -86,7 +86,7 @@ func TestEngineUnclassified(t *testing.T) { if _, err := handleJSON(t, svc, "SomeCustomOp", nil); err != ErrUnclassified { t.Fatalf("unknown op: want ErrUnclassified, got %v", err) } - if _, err := Handle(svc, "CreateWidget", "query", []byte("{}")); err != ErrUnclassified { + if _, err := Handle(Call{Service: svc, Protocol: "query", Op: "CreateWidget", Body: []byte("{}")}); err != ErrUnclassified { t.Fatalf("non-json protocol: want ErrUnclassified, got %v", err) } if _, err := handleJSON(t, "unregistered", "CreateThing", nil); err != ErrUnclassified { @@ -110,7 +110,7 @@ func TestEngineConcurrentAccess(t *testing.T) { do := func(op string, params map[string]any) { body, _ := json.Marshal(params) - if _, err := Handle(svc, op, "json-1.1", body); err != nil { + if _, err := Handle(Call{Service: svc, Protocol: "json-1.1", Op: op, Body: body}); err != nil { t.Errorf("%s: %v", op, err) } } @@ -125,6 +125,193 @@ func TestEngineConcurrentAccess(t *testing.T) { wg.Wait() } +// --- rest-json --- + +func handleREST(t *testing.T, service, method, uri string, params map[string]any) (*Result, error) { + t.Helper() + var body []byte + if params != nil { + body, _ = json.Marshal(params) + } + return Handle(Call{Service: service, Protocol: "rest-json", Method: method, URI: uri, Body: body}) +} + +// TestEngineRESTJSONRoundTrip is the whole point of teaching the engine +// rest-json: the operation name is not in a header, so it has to come from the +// method and path, and the resource identifier has to come from the path label +// rather than the body. +func TestEngineRESTJSONRoundTrip(t *testing.T) { + const svc = "restsvc" + Register(svc, map[string]OpMeta{ + "CreateGraph": {Verb: "Create", Resource: "Graph", OutputItemKey: "Graph", + Method: "POST", URI: "/v1/graphs"}, + "GetGraph": {Verb: "Get", Resource: "Graph", OutputItemKey: "Graph", + Method: "GET", URI: "/v1/graphs/{GraphName}"}, + "ListGraphs": {Verb: "List", Resource: "Graph", OutputListKey: "Graphs", + Method: "GET", URI: "/v1/graphs"}, + "DeleteGraph": {Verb: "Delete", Resource: "Graph", + Method: "DELETE", URI: "/v1/graphs/{GraphName}"}, + }) + + // An empty store lists cleanly rather than erroring — the parameterless + // read every compat smoke test performs. + r, err := handleREST(t, svc, "GET", "/v1/graphs", nil) + if err != nil || r.Status != 200 { + t.Fatalf("list on empty store: status=%d err=%v", statusOf(r), err) + } + if got := decode(t, r)["Graphs"].([]any); len(got) != 0 { + t.Fatalf("empty store listed %d graphs", len(got)) + } + + // Create takes its parameters from the body. + r, err = handleREST(t, svc, "POST", "/v1/graphs", map[string]any{"GraphName": "g1", "Tier": "small"}) + if err != nil || r.Status != 200 { + t.Fatalf("create: status=%d err=%v", statusOf(r), err) + } + graph := decode(t, r)["Graph"].(map[string]any) + if graph["GraphName"] != "g1" || graph["Tier"] != "small" { + t.Fatalf("create echo wrong: %v", graph) + } + + // Get takes its identifier from the path label, with no body at all. This + // is the case a JSON-only engine could never serve. + r, err = handleREST(t, svc, "GET", "/v1/graphs/g1", nil) + if err != nil || r.Status != 200 { + t.Fatalf("get by path label: status=%d err=%v", statusOf(r), err) + } + if got := decode(t, r)["Graph"].(map[string]any); got["Tier"] != "small" { + t.Fatalf("get returned the wrong resource: %v", got) + } + + // Delete, also addressed by path label, and the list goes back to empty. + if _, err := handleREST(t, svc, "DELETE", "/v1/graphs/g1", nil); err != nil { + t.Fatalf("delete: %v", err) + } + r, _ = handleREST(t, svc, "GET", "/v1/graphs", nil) + if got := decode(t, r)["Graphs"].([]any); len(got) != 0 { + t.Fatalf("after delete, list returned %d graphs", len(got)) + } +} + +// TestEngineRESTJSONContentType guards against serving a rest-json caller the +// X-Amz-Target content type. botocore parses the body by the modelled protocol, +// but an amz-json content type on a REST response is wrong on the wire and +// misleads anyone reading a capture. +func TestEngineRESTJSONContentType(t *testing.T) { + const svc = "ctsvc" + Register(svc, map[string]OpMeta{ + "ListThings": {Verb: "List", Resource: "CtThing", OutputListKey: "Things", + Method: "GET", URI: "/things"}, + }) + + r, err := handleREST(t, svc, "GET", "/things", nil) + if err != nil { + t.Fatalf("list: %v", err) + } + if r.ContentType != "application/json" { + t.Errorf("ContentType = %q, want application/json", r.ContentType) + } +} + +// TestEngineRESTJSONPathLabelWinsOverBody pins which source of a parameter is +// authoritative. A restJson1 model never binds one member to both the URI and +// the body, so real SDK traffic cannot hit this — but the URI is what addresses +// the resource, so a request that does carry both must not be able to redirect +// the lookup from the body. +func TestEngineRESTJSONPathLabelWinsOverBody(t *testing.T) { + const svc = "authsvc" + Register(svc, map[string]OpMeta{ + "CreateItem": {Verb: "Create", Resource: "AItem", OutputItemKey: "Item", + Method: "POST", URI: "/items"}, + "UpdateItem": {Verb: "Update", Resource: "AItem", OutputItemKey: "Item", + Method: "PUT", URI: "/items/{AItemName}"}, + }) + + if _, err := handleREST(t, svc, "POST", "/items", map[string]any{"AItemName": "real"}); err != nil { + t.Fatalf("create: %v", err) + } + + r, err := handleREST(t, svc, "PUT", "/items/real", + map[string]any{"AItemName": "spoofed", "Colour": "blue"}) + if err != nil { + t.Fatalf("update: %v", err) + } + if got := decode(t, r)["Item"].(map[string]any); got["AItemName"] != "real" { + t.Errorf("body overrode the path label: AItemName = %v, want real", got["AItemName"]) + } +} + +// TestEngineRESTJSONQueryParams covers the third parameter source: values the +// model binds with httpQuery rather than into the body. +func TestEngineRESTJSONQueryParams(t *testing.T) { + const svc = "qsvc" + Register(svc, map[string]OpMeta{ + "CreateQThing": {Verb: "Create", Resource: "QThing", OutputItemKey: "Thing", + Method: "POST", URI: "/qthings"}, + }) + + r, err := handleREST(t, svc, "POST", "/qthings?QThingName=fromquery", nil) + if err != nil { + t.Fatalf("create: %v", err) + } + if got := decode(t, r)["Thing"].(map[string]any); got["QThingName"] != "fromquery" { + t.Errorf("query parameter ignored: %v", got) + } +} + +// TestEngineRESTJSONUnmatchedPathIsUnclassified is the guarantee the whole +// coverage claim rests on. A path the route table does not know must decline, +// never fabricate an empty success — see docs/coverage.md. +func TestEngineRESTJSONUnmatchedPathIsUnclassified(t *testing.T) { + const svc = "misssvc" + Register(svc, map[string]OpMeta{ + "ListThings": {Verb: "List", Resource: "MThing", OutputListKey: "Things", + Method: "GET", URI: "/things"}, + }) + + if _, err := handleREST(t, svc, "GET", "/not/a/known/path", nil); err != ErrUnclassified { + t.Errorf("unknown path: want ErrUnclassified, got %v", err) + } + if _, err := handleREST(t, svc, "POST", "/things", nil); err != ErrUnclassified { + t.Errorf("known path, wrong method: want ErrUnclassified, got %v", err) + } + if _, err := handleREST(t, "unregistered", "GET", "/things", nil); err != ErrUnclassified { + t.Errorf("unregistered service: want ErrUnclassified, got %v", err) + } +} + +// TestEngineRESTJSONUnroutedOperationIsUnclassified covers the operation that is +// reachable by path but not CRUD-shaped. codegen omits it from the registry, so +// it has no route, and the caller must get a clean error. +func TestEngineRESTJSONUnroutedOperationIsUnclassified(t *testing.T) { + const svc = "execsvc" + // Modelled on rds-data: every operation is a verb the classifier refuses, + // so nothing registers and nothing routes. + Register(svc, map[string]OpMeta{}) + + if _, err := handleREST(t, svc, "POST", "/Execute", nil); err != ErrUnclassified { + t.Errorf("want ErrUnclassified, got %v", err) + } +} + +// TestEngineRESTXMLStillDeclines pins the boundary. rest-xml and query carry no +// route table into the engine, and admitting them would serve S3 traffic from +// the generic store. +func TestEngineRESTXMLStillDeclines(t *testing.T) { + const svc = "xmlsvc" + Register(svc, map[string]OpMeta{ + "ListThings": {Verb: "List", Resource: "XThing", OutputListKey: "Things", + Method: "GET", URI: "/things"}, + }) + + for _, proto := range []string{"rest-xml", "query"} { + _, err := Handle(Call{Service: svc, Protocol: proto, Method: "GET", URI: "/things"}) + if err != ErrUnclassified { + t.Errorf("%s: want ErrUnclassified, got %v", proto, err) + } + } +} + func statusOf(r *Result) int { if r == nil { return 0 diff --git a/internal/shared/httproute/match.go b/internal/shared/httproute/match.go new file mode 100644 index 00000000..6eab1094 --- /dev/null +++ b/internal/shared/httproute/match.go @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: Apache-2.0 + +// Package httproute matches an HTTP request against a service's REST route +// table — the (method, URI template) pairs a model declares for each operation. +// +// It exists because two callers need the same answer from the same data. The +// generated per-service routers have always had it; the generic CRUD engine +// needs it too, because a rest-json request carries its operation name in the +// method and path rather than in an X-Amz-Target header. Emitting the algorithm +// into 148 generated packages and writing it a 149th time for the engine is how +// the two would drift. +package httproute + +import ( + "net/url" + "strings" +) + +// Params holds the URL path parameters extracted from a matched route. +type Params map[string]string + +// Route maps an HTTP method and URI pattern to an operation name. +type Route struct { + Method string + Pattern string + Operation string +} + +// Match returns the operation name and extracted path parameters for the given +// HTTP method and request URI. It returns ("", nil) if no route matches. +// +// Pass req.URL.RequestURI(), not req.URL.Path: some AWS operations are +// distinguished only by a query string (".../tagging?Operation=Tag"), and a +// bare path can never satisfy those routes. +func Match(routes []Route, method, uri string) (string, Params) { + // Two passes. A route that constrains the query is more specific than one + // that does not, and route tables are ordered by operation name rather + // than specificity — so trying constrained routes first keeps + // ".../distribution" from shadowing ".../distribution?WithTags". + for _, constrained := range []bool{true, false} { + for _, route := range routes { + if route.Method != method || strings.Contains(route.Pattern, "?") != constrained { + continue + } + if params, ok := MatchURI(route.Pattern, uri); ok { + return route.Operation, params + } + } + } + return "", nil +} + +// MatchURI matches a request URI against a pattern that may contain {Label} and +// {Label+} (greedy) segments, and may constrain the query string after a "?". +// Returns the extracted parameters and true on match, or nil and false +// otherwise. +func MatchURI(pattern, uri string) (Params, bool) { + patPath, patQuery, _ := strings.Cut(pattern, "?") + uriPath, uriQuery, _ := strings.Cut(uri, "?") + if !matchQuery(patQuery, uriQuery) { + return nil, false + } + + patParts := splitPath(patPath) + pathParts := splitPath(uriPath) + + params := Params{} + pi := 0 + for i, pat := range patParts { + if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "+}") { + // Greedy label: consumes all remaining path segments. + label := pat[1 : len(pat)-2] + if pi >= len(pathParts) { + return nil, false + } + params[label] = strings.Join(pathParts[pi:], "/") + pi = len(pathParts) + // Greedy must be the last pattern segment. + if i != len(patParts)-1 { + return nil, false + } + } else if strings.HasPrefix(pat, "{") && strings.HasSuffix(pat, "}") { + // Single-segment label. + label := pat[1 : len(pat)-1] + if pi >= len(pathParts) { + return nil, false + } + params[label] = pathParts[pi] + pi++ + } else { + // Literal segment. + if pi >= len(pathParts) || pathParts[pi] != pat { + return nil, false + } + pi++ + } + } + if pi != len(pathParts) { + return nil, false + } + return params, true +} + +// matchQuery reports whether a request's query string satisfies the constraint +// a route pattern carries after its "?". Each "&"-separated term is either a +// bare key that must be present ("?WithTags") or a key=value that must be +// present with that value ("?Operation=Tag"). An empty constraint matches +// anything, which is every route that has no "?". +func matchQuery(constraint, query string) bool { + if constraint == "" { + return true + } + // ParseQuery returns what it could parse alongside any error, so a + // malformed tail cannot hide a valid term earlier in the string. + values, _ := url.ParseQuery(query) + for _, term := range strings.Split(constraint, "&") { + if term == "" { + continue + } + key, want, hasValue := strings.Cut(term, "=") + got, present := values[key] + if !present { + return false + } + if !hasValue { + continue + } + matched := false + for _, v := range got { + if v == want { + matched = true + break + } + } + if !matched { + return false + } + } + return true +} + +// splitPath splits a URI path into non-empty segments. +func splitPath(path string) []string { + parts := strings.Split(strings.Trim(path, "/"), "/") + out := parts[:0] + for _, p := range parts { + if p != "" { + out = append(out, p) + } + } + return out +} diff --git a/internal/shared/httproute/match_test.go b/internal/shared/httproute/match_test.go new file mode 100644 index 00000000..5a1d2d7d --- /dev/null +++ b/internal/shared/httproute/match_test.go @@ -0,0 +1,202 @@ +// SPDX-License-Identifier: Apache-2.0 + +package httproute + +import "testing" + +func TestMatchURILabels(t *testing.T) { + tests := []struct { + name string + pattern string + uri string + want Params + ok bool + }{ + { + name: "literal path", + pattern: "/2020-05-31/distribution", + uri: "/2020-05-31/distribution", + want: Params{}, + ok: true, + }, + { + name: "single-segment label", + pattern: "/2020-05-31/distribution/{Id}", + uri: "/2020-05-31/distribution/E123", + want: Params{"Id": "E123"}, + ok: true, + }, + { + name: "two labels", + pattern: "/v1/{Bucket}/object/{Key}", + uri: "/v1/mybucket/object/mykey", + want: Params{"Bucket": "mybucket", "Key": "mykey"}, + ok: true, + }, + { + name: "greedy label consumes the remaining segments", + pattern: "/v1/objects/{Key+}", + uri: "/v1/objects/a/b/c.txt", + want: Params{"Key": "a/b/c.txt"}, + ok: true, + }, + { + name: "greedy label needs at least one segment", + pattern: "/v1/objects/{Key+}", + uri: "/v1/objects", + ok: false, + }, + { + name: "trailing slash is not an extra segment", + pattern: "/2020-05-31/distribution", + uri: "/2020-05-31/distribution/", + want: Params{}, + ok: true, + }, + { + name: "literal segment mismatch", + pattern: "/2020-05-31/distribution", + uri: "/2020-05-31/streaming-distribution", + ok: false, + }, + { + name: "request has too few segments", + pattern: "/2020-05-31/distribution/{Id}", + uri: "/2020-05-31/distribution", + ok: false, + }, + { + name: "request has too many segments", + pattern: "/2020-05-31/distribution/{Id}", + uri: "/2020-05-31/distribution/E123/config", + ok: false, + }, + { + name: "query string is ignored when the pattern does not constrain it", + pattern: "/2020-05-31/distribution", + uri: "/2020-05-31/distribution?Marker=abc&MaxItems=10", + want: Params{}, + ok: true, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + got, ok := MatchURI(tc.pattern, tc.uri) + if ok != tc.ok { + t.Fatalf("MatchURI(%q, %q) ok = %v, want %v", tc.pattern, tc.uri, ok, tc.ok) + } + if !ok { + return + } + if len(got) != len(tc.want) { + t.Fatalf("params = %v, want %v", got, tc.want) + } + for k, v := range tc.want { + if got[k] != v { + t.Errorf("params[%q] = %q, want %q", k, got[k], v) + } + } + }) + } +} + +func TestMatchURIQueryConstraints(t *testing.T) { + tests := []struct { + name string + pattern string + uri string + ok bool + }{ + { + name: "bare key must be present", + pattern: "/2020-05-31/distribution?WithTags", + uri: "/2020-05-31/distribution?WithTags", + ok: true, + }, + { + name: "bare key absent does not match", + pattern: "/2020-05-31/distribution?WithTags", + uri: "/2020-05-31/distribution", + ok: false, + }, + { + name: "key=value must match the value", + pattern: "/2020-05-31/tagging?Operation=Tag", + uri: "/2020-05-31/tagging?Operation=Tag&Resource=arn", + ok: true, + }, + { + name: "key present with the wrong value does not match", + pattern: "/2020-05-31/tagging?Operation=Tag", + uri: "/2020-05-31/tagging?Operation=Untag", + ok: false, + }, + { + name: "every term of a multi-term constraint must hold", + pattern: "/v1/thing?a=1&b=2", + uri: "/v1/thing?a=1", + ok: false, + }, + { + name: "a malformed tail cannot hide a valid earlier term", + pattern: "/v1/thing?a=1", + uri: "/v1/thing?a=1&%zz", + ok: true, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + if _, ok := MatchURI(tc.pattern, tc.uri); ok != tc.ok { + t.Errorf("MatchURI(%q, %q) ok = %v, want %v", tc.pattern, tc.uri, ok, tc.ok) + } + }) + } +} + +// TestMatchPrefersConstrainedRoutes locks the two-pass ordering the generated +// routers depend on. OperationRoutes is sorted by operation name, not by +// specificity, so an unconstrained "/distribution" route appears before +// "/distribution?WithTags" and would shadow it in a single pass. +func TestMatchPrefersConstrainedRoutes(t *testing.T) { + routes := []Route{ + // Deliberately in the order codegen emits: alphabetical by operation. + {Method: "POST", Pattern: "/2020-05-31/distribution", Operation: "CreateDistribution"}, + {Method: "POST", Pattern: "/2020-05-31/distribution?WithTags", Operation: "CreateDistributionWithTags"}, + } + + if op, _ := Match(routes, "POST", "/2020-05-31/distribution?WithTags"); op != "CreateDistributionWithTags" { + t.Errorf("constrained route lost to the unconstrained one: got %q", op) + } + if op, _ := Match(routes, "POST", "/2020-05-31/distribution"); op != "CreateDistribution" { + t.Errorf("unconstrained route did not match: got %q", op) + } +} + +func TestMatchMethodAndMiss(t *testing.T) { + routes := []Route{ + {Method: "GET", Pattern: "/2020-05-31/distribution/{Id}", Operation: "GetDistribution"}, + {Method: "DELETE", Pattern: "/2020-05-31/distribution/{Id}", Operation: "DeleteDistribution"}, + } + + op, params := Match(routes, "GET", "/2020-05-31/distribution/E123") + if op != "GetDistribution" { + t.Fatalf("op = %q, want GetDistribution", op) + } + if params["Id"] != "E123" { + t.Errorf("params[Id] = %q, want E123", params["Id"]) + } + + if op, _ := Match(routes, "PUT", "/2020-05-31/distribution/E123"); op != "" { + t.Errorf("method mismatch matched %q, want no match", op) + } + + // A miss must be an empty operation and nil params, never a zero-value + // route: the CRUD engine treats "" as unclassified, and a non-nil empty + // params map would read as a successful match with no labels. + op, params = Match(routes, "GET", "/some/other/path") + if op != "" || params != nil { + t.Errorf("miss returned (%q, %v), want (\"\", nil)", op, params) + } +} diff --git a/tests/compatibility/test_service_smoke.py b/tests/compatibility/test_service_smoke.py index c77bde01..af517749 100644 --- a/tests/compatibility/test_service_smoke.py +++ b/tests/compatibility/test_service_smoke.py @@ -19,11 +19,19 @@ # name is the point: the test asserts what a user typing it actually gets. # # Services whose coverage comes from the generic CRUD engine rather than a -# hand-written provider. The engine only serves the awsJson1_0 / awsJson1_1 -# protocols, which carry the operation name in X-Amz-Target; a rest-json, -# query, or rest-xml service cannot be listed here and be served. +# hand-written provider. The engine serves the awsJson1_0 / awsJson1_1 +# protocols, which carry the operation name in X-Amz-Target, and rest-json, +# whose operation is recovered from the request method and path via the model's +# route table. A query or rest-xml service cannot be listed here and be served. ENGINE_SERVED_SERVICES = [ "comprehend", + # rest-json, and the proof the engine reaches that protocol at all. All + # three sat in REGISTERED_ONLY_SERVICES until the engine learned to resolve + # an operation from the method and path; nothing about these three services + # changed, only what the engine can read. + "polly", + "qbusiness", + "codeguru-reviewer", # rekognition could not be onboarded at all before the alias table was # derived from the models: its X-Amz-Target prefix is RekognitionService, # which no hand-written gateway clause covered, so every call came back @@ -55,12 +63,19 @@ # never a fabricated success, and never an unrouted UnknownService, which would # send a caller back to real AWS. They are deliberately NOT counted as covered; # see docs/coverage.md. +# rest-json, so the engine can now read its requests — and still served by +# nothing, because it has no CRUD-shaped operation to classify. InvokeEndpoint, +# InvokeEndpointAsync and InvokeEndpointWithResponseStream are not +# Create/Get/List/Delete/Update, so codegen registers nothing and there is no +# route to match. Same case as forecastquery; see docs/coverage.md. +# +# personalize-runtime left this list when the engine gained rest-json: +# GetRecommendations classifies as a Get, so it is served now. It is not in +# ENGINE_SERVED_SERVICES either, because both its operations take required +# parameters and this harness has no parameterless read to prove it with — the +# fidelity manifest is its record, as for bedrock-data-automation-runtime. REGISTERED_ONLY_SERVICES = [ - "polly", - "qbusiness", "sagemaker-runtime", - "personalize-runtime", - "codeguru-reviewer", ]