From d47d459f4f9a700baf57a4262603e020fddeb479 Mon Sep 17 00:00:00 2001 From: Sung-Kyu Yoo Date: Sat, 5 Sep 2026 20:40:08 +0900 Subject: [PATCH 01/10] test: specify the AWS XML response encoder the engine lacks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RED: TestEncodeXMLEnvelopes / TestEncodeXMLValues (9 subtests) / TestEncodeXMLIsDeterministic / TestEncodeXMLDeclaresItsHeader all fail against an unimplemented encodeXML — got "", want the envelope. The engine's only serializer is okJSON, so query and rest-xml have no success path at all, which is why both are registered-only. The stub keeps the tree compiling (pre-commit runs go vet) so the RED is a real assertion diff rather than a build error. Decisions pinned here rather than discovered later: query gets the envelope botocore's query parser looks for, rest-xml the bare ; lists wrap in ; an empty list is an empty element, not an omitted key; keys are sorted for byte stability; dotted query keys are dropped; values are escaped. --- internal/shared/crud/xml.go | 19 ++++ internal/shared/crud/xml_test.go | 150 +++++++++++++++++++++++++++++++ 2 files changed, 169 insertions(+) create mode 100644 internal/shared/crud/xml.go create mode 100644 internal/shared/crud/xml_test.go diff --git a/internal/shared/crud/xml.go b/internal/shared/crud/xml.go new file mode 100644 index 00000000..fdc54c97 --- /dev/null +++ b/internal/shared/crud/xml.go @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: Apache-2.0 + +package crud + +const xmlHeader = `` + +const ( + protocolQuery = "query" + protocolRESTXML = "rest-xml" +) + +// encodeXML renders an engine response as an AWS XML body. +// +// Not implemented: this stub exists so the specification in xml_test.go +// compiles and fails at runtime against real assertions rather than as a build +// error. See that file for the dialects and value rules it must satisfy. +func encodeXML(protocol, op string, v map[string]any) []byte { + return nil +} diff --git a/internal/shared/crud/xml_test.go b/internal/shared/crud/xml_test.go new file mode 100644 index 00000000..9178df4a --- /dev/null +++ b/internal/shared/crud/xml_test.go @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: Apache-2.0 + +package crud + +import ( + "regexp" + "strings" + "testing" +) + +// requestIDPattern strips the synthesized RequestId so envelope assertions can +// compare a fixed string. +var requestIDPattern = regexp.MustCompile(`[0-9a-f]+`) + +func normalize(b []byte) string { + s := requestIDPattern.ReplaceAllString(string(b), "ID") + return strings.TrimPrefix(s, xmlHeader) +} + +// TestEncodeXMLEnvelopes pins the two dialects apart. botocore's query parser +// looks for inside ; its rest-xml parser +// maps the root element's children straight onto the output shape and ignores +// the root's name. +func TestEncodeXMLEnvelopes(t *testing.T) { + body := map[string]any{"DNSName": "lb-1.example.com"} + + got := normalize(encodeXML(protocolQuery, "CreateLoadBalancer", body)) + want := "" + + "lb-1.example.com" + + "ID" + + "" + if got != want { + t.Errorf("query envelope:\n got %s\nwant %s", got, want) + } + + got = normalize(encodeXML(protocolRESTXML, "CreateAccessPoint", body)) + want = "lb-1.example.com" + if got != want { + t.Errorf("rest-xml envelope:\n got %s\nwant %s", got, want) + } +} + +func TestEncodeXMLValues(t *testing.T) { + cases := []struct { + name string + in map[string]any + want string + }{ + { + // Keys are sorted so the same store produces the same bytes across + // runs — Go map iteration is randomised, same reason Register sorts + // the route table. + name: "keys_are_sorted", + in: map[string]any{"Zeta": "z", "Alpha": "a", "Mu": "m"}, + want: "amz", + }, + { + name: "scalars", + in: map[string]any{"B": true, "N": 42, "F": 1.5, "S": "x"}, + want: "true1.542x", + }, + { + // AWS wraps list entries in for both dialects unless the + // model flattens them. The engine has no flattening information, so + // it emits the default. + name: "list_wraps_members", + in: map[string]any{"Things": []map[string]any{ + {"Name": "a"}, {"Name": "b"}, + }}, + want: "ab", + }, + { + // The engine's own list() returns []map[string]any, but a value + // echoed back from a caller's JSON body arrives as []any. + name: "any_slice_wraps_members", + in: map[string]any{"Names": []any{"a", "b"}}, + want: "ab", + }, + { + // An empty collection must be an empty element, not an omitted one: + // botocore reads a missing key as absent rather than as empty. + name: "empty_list_is_an_empty_element", + in: map[string]any{"Things": []map[string]any{}}, + want: "", + }, + { + name: "nested_map", + in: map[string]any{"Outer": map[string]any{"Inner": "v"}}, + want: "v", + }, + { + // Query input is flat form-encoding, so a structured member arrives + // as "Listeners.member.1.Protocol". There is nowhere to put it in a + // generic store and it is not a name any SDK expects back, so it is + // dropped rather than emitted as a bogus element. + name: "dotted_keys_are_dropped", + in: map[string]any{ + "LoadBalancerName": "lb", + "Listeners.member.1.Protocol": "HTTP", + }, + want: "lb", + }, + { + // A caller controls these values. Emitting them raw produces a body + // botocore cannot parse at all, which reads as a transport failure + // rather than as the echo it is. + name: "values_are_escaped", + in: map[string]any{"S": `a"d"`}, + want: "a<b&c>"d"", + }, + { + // Nothing in the engine produces nil, but a caller's JSON body can. + name: "nil_is_an_empty_element", + in: map[string]any{"S": nil}, + want: "", + }, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + got := normalize(encodeXML(protocolRESTXML, "Op", c.in)) + want := "" + c.want + "" + if got != want { + t.Errorf("\n got %s\nwant %s", got, want) + } + }) + } +} + +// TestEncodeXMLIsDeterministic guards the sorting above against a regression +// that only shows up as a flaky diff between runs. +func TestEncodeXMLIsDeterministic(t *testing.T) { + in := map[string]any{"A": "1", "B": "2", "C": "3", "D": "4", "E": "5", "F": "6"} + first := normalize(encodeXML(protocolRESTXML, "Op", in)) + for i := 0; i < 50; i++ { + if got := normalize(encodeXML(protocolRESTXML, "Op", in)); got != first { + t.Fatalf("run %d differs:\n got %s\nfirst %s", i, got, first) + } + } +} + +// TestEncodeXMLDeclaresItsHeader keeps the XML declaration on the body: botocore +// tolerates its absence, but the gateway's own error envelopes emit it and a +// response that differs from an error only in that respect is a needless +// difference. +func TestEncodeXMLDeclaresItsHeader(t *testing.T) { + if !strings.HasPrefix(string(encodeXML(protocolQuery, "Op", nil)), xmlHeader) { + t.Error("body does not start with the XML declaration") + } +} From abf240f81c59a0293f67c2a683485da46dc70ed4 Mon Sep 17 00:00:00 2001 From: Sung-Kyu Yoo Date: Sat, 5 Sep 2026 20:40:50 +0900 Subject: [PATCH 02/10] feat: render engine responses as AWS XML GREEN: all 13 encodeXML tests pass (4 top-level, 9 value subtests); go test ./... fully green. One encoder, two dialects. query gets plus a ResponseMetadata/RequestId, because botocore's query parser reads the result out of that nesting and returns an empty one without it; rest-xml gets the bare , because its parser maps the root's children onto the output shape and ignores the root's name. No xmlns: botocore strips namespaces before matching element names, so declaring one is bytes nothing reads. If that changes it belongs on OpMeta from the model's trait, not guessed at in the encoder. --- internal/shared/crud/xml.go | 107 ++++++++++++++++++++++++++++++++++-- 1 file changed, 103 insertions(+), 4 deletions(-) diff --git a/internal/shared/crud/xml.go b/internal/shared/crud/xml.go index fdc54c97..333ab48a 100644 --- a/internal/shared/crud/xml.go +++ b/internal/shared/crud/xml.go @@ -2,6 +2,13 @@ package crud +import ( + "encoding/xml" + "fmt" + "sort" + "strings" +) + const xmlHeader = `` const ( @@ -11,9 +18,101 @@ const ( // encodeXML renders an engine response as an AWS XML body. // -// Not implemented: this stub exists so the specification in xml_test.go -// compiles and fails at runtime against real assertions rather than as a build -// error. See that file for the dialects and value rules it must satisfy. +// The two dialects differ only in the envelope. botocore's query parser looks +// for nested inside and returns a result +// with nothing in it when the nesting is absent; its rest-xml parser maps the +// root element's children straight onto the output shape and ignores the root's +// name. So query gets both wrappers and rest-xml gets one. +// +// No xmlns is emitted. botocore strips the namespace from every element before +// matching it, so declaring one would be bytes on the wire that nothing reads. +// If that ever stops being true the namespace belongs on OpMeta, from the +// model's xmlNamespace trait, rather than guessed at here. +// +// This is the same "plausible, not faithful" contract as the JSON path: the +// body echoes what the caller stored, in the shape an SDK can parse. It is not +// derived from the model's output shape, so a member the model flattens or +// renames is emitted in its default form. func encodeXML(protocol, op string, v map[string]any) []byte { - return nil + var b strings.Builder + b.WriteString(xmlHeader) + + if protocol == protocolQuery { + b.WriteString("<" + op + "Response>") + } + writeElement(&b, op+"Result", v) + if protocol == protocolQuery { + // RequestId is not optional: botocore's query parser reads + // ResponseMetadata into every response's metadata, and an SDK that logs + // or retries on it gets an empty string otherwise. + b.WriteString("" + randHex(8) + "") + b.WriteString("") + } + return []byte(b.String()) +} + +// writeElement writes one … element whose content is value. +func writeElement(b *strings.Builder, name string, value any) { + b.WriteString("<" + name + ">") + writeValue(b, value) + b.WriteString("") +} + +// writeValue writes the content of an element: nested elements for a map, +// entries for a list, escaped text for anything else. +func writeValue(b *strings.Builder, value any) { + switch val := value.(type) { + case nil: + + case map[string]any: + for _, k := range sortedKeys(val) { + writeElement(b, k, val[k]) + } + + case []map[string]any: + // AWS wraps list entries in for both dialects unless the model + // flattens the list. The engine has no flattening information, so it + // emits the default rather than guessing per service. + for _, item := range val { + writeElement(b, "member", item) + } + + case []any: + // The engine's own list() produces []map[string]any, but a list echoed + // back from a caller's JSON body arrives as []any. + for _, item := range val { + writeElement(b, "member", item) + } + + case string: + xml.EscapeText(b, []byte(val)) + + default: + // Numbers and bools. fmt renders these the way AWS does, and escaping + // is applied anyway because the branch is reachable from a caller's + // arbitrary JSON body, not only from the two types named. + xml.EscapeText(b, []byte(fmt.Sprint(val))) + } +} + +// sortedKeys returns the emittable keys of a response map in a stable order. +// +// Sorted because Go map iteration is randomised and an unsorted body would make +// the same stored resource serialize differently between runs of the same +// binary — the same reason Register sorts the route table. +// +// A key containing "." is dropped. Query input is flat form-encoding, so a +// structured member arrives as "Listeners.member.1.Protocol"; there is nowhere +// to put it in a generic store, and no SDK expects an element by that name, so +// echoing it back would be noise in a response rather than information. +func sortedKeys(m map[string]any) []string { + keys := make([]string, 0, len(m)) + for k := range m { + if strings.Contains(k, ".") { + continue + } + keys = append(keys, k) + } + sort.Strings(keys) + return keys } From b99c7e85e94a60162f69e25b23d52afa5e147e9f Mon Sep 17 00:00:00 2001 From: Sung-Kyu Yoo Date: Sat, 5 Sep 2026 20:43:05 +0900 Subject: [PATCH 03/10] test: specify rest-xml as engine-servable, and split the buffering predicate RED: Servable("rest-xml") = false, want true; NeedsBody("query") = false, want true; TestEngineRESTXMLRoundTrip and TestEngineRESTXMLContentType fail. Replaces TestEngineRESTXMLStillDeclines, which pinned the old boundary. rest-xml is not on the wrong side of it: all 97 of s3-control's operations are bound to a method and URI template, so the route table that classifies rest-json classifies it too. What survives is TestEngineQueryStillDeclines, until Task 4. The new predicate is the point of this task. "Can the engine serve this protocol" and "must the gateway buffer the body" are different questions, and rest-xml is where they come apart: S3 speaks it, and S3 bodies are large binary uploads that must keep streaming. --- internal/shared/crud/crud.go | 11 ++ internal/shared/crud/crud_test.go | 170 ++++++++++++++++++++++++++++-- 2 files changed, 170 insertions(+), 11 deletions(-) diff --git a/internal/shared/crud/crud.go b/internal/shared/crud/crud.go index efeb04df..70f0d17e 100644 --- a/internal/shared/crud/crud.go +++ b/internal/shared/crud/crud.go @@ -141,6 +141,17 @@ func Servable(protocol string) bool { return JSONProtocol(protocol) || protocol == protocolRESTJSON } +// NeedsBody reports whether the gateway must buffer the request body before +// calling Handle. +// +// Not yet separated from Servable: this is the extraction point for the +// distinction, and it currently states the gateway's existing behaviour +// unchanged so the specification in crud_test.go fails against real values +// rather than as a build error. +func NeedsBody(protocol string) bool { + return Servable(protocol) +} + // 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. diff --git a/internal/shared/crud/crud_test.go b/internal/shared/crud/crud_test.go index f90d5429..e0ac9b6e 100644 --- a/internal/shared/crud/crud_test.go +++ b/internal/shared/crud/crud_test.go @@ -4,6 +4,7 @@ package crud import ( "encoding/json" + "strings" "sync" "testing" ) @@ -294,21 +295,168 @@ func TestEngineRESTJSONUnroutedOperationIsUnclassified(t *testing.T) { } } -// 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" +// TestEngineQueryStillDeclines pins what is left of the boundary. query names +// its operation in the form body rather than in the path, so until the engine +// learns to read that, a query call must decline. +// +// This replaces TestEngineRESTXMLStillDeclines: rest-xml is no longer on the +// wrong side of the line. Every one of its operations is bound to a method and +// a URI template, exactly like rest-json, so the same route table classifies it. +func TestEngineQueryStillDeclines(t *testing.T) { + const svc = "querysvc" Register(svc, map[string]OpMeta{ - "ListThings": {Verb: "List", Resource: "XThing", OutputListKey: "Things", + "ListThings": {Verb: "List", Resource: "QYThing", 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) - } + _, err := Handle(Call{Service: svc, Protocol: "query", Method: "GET", URI: "/things"}) + if err != ErrUnclassified { + t.Errorf("query: want ErrUnclassified, got %v", err) + } +} + +// TestServableAndNeedsBody separates two questions the engine used to answer +// with one predicate. +// +// "Can the engine serve this protocol" and "must the gateway buffer the body +// before calling it" are not the same question, and rest-xml is where they come +// apart: the engine can classify it from the route table, but S3 speaks it and +// S3 bodies are large binary uploads. Buffering those to serve a service that +// never reaches the engine would turn a streaming path into a memory one. +func TestServableAndNeedsBody(t *testing.T) { + cases := []struct { + protocol string + servable, needsBody bool + }{ + {"json-1.0", true, true}, + {"json-1.1", true, true}, + {"json", true, true}, + {"rest-json", true, true}, + // The whole reason the predicates are separate. + {"rest-xml", true, false}, + // Admitted in Task 4; its operation name is in the body, so it must be + // buffered before it can be read. + {"query", false, true}, + {"ec2-query", false, false}, + {"nonsense", false, false}, + } + for _, c := range cases { + t.Run(c.protocol, func(t *testing.T) { + if got := Servable(c.protocol); got != c.servable { + t.Errorf("Servable(%q) = %v, want %v", c.protocol, got, c.servable) + } + if got := NeedsBody(c.protocol); got != c.needsBody { + t.Errorf("NeedsBody(%q) = %v, want %v", c.protocol, got, c.needsBody) + } + }) + } +} + +// --- rest-xml --- + +func handleXML(t *testing.T, service, method, uri string) (*Result, error) { + t.Helper() + // Deliberately no body: rest-xml is not buffered by the gateway, so the + // engine must serve it from the path and query alone. + return Handle(Call{Service: service, Protocol: "rest-xml", Method: method, URI: uri}) +} + +// TestEngineRESTXMLRoundTrip uses S3 Control's own routes, because it is the +// service this unlocks and its identifiers all arrive as path labels. +func TestEngineRESTXMLRoundTrip(t *testing.T) { + const svc = "s3controltest" + Register(svc, map[string]OpMeta{ + "CreateAccessPoint": {Verb: "Create", Resource: "AccessPoint", OutputItemKey: "AccessPoint", + Method: "PUT", URI: "/v20180820/accesspoint/{Name}"}, + "GetAccessPoint": {Verb: "Get", Resource: "AccessPoint", OutputItemKey: "AccessPoint", + Method: "GET", URI: "/v20180820/accesspoint/{Name}"}, + "ListAccessPoints": {Verb: "List", Resource: "AccessPoint", OutputListKey: "AccessPointList", + Method: "GET", URI: "/v20180820/accesspoint"}, + "DeleteAccessPoint": {Verb: "Delete", Resource: "AccessPoint", + Method: "DELETE", URI: "/v20180820/accesspoint/{Name}"}, + }) + + // The parameterless read on an empty store, which is what the compat smoke + // test performs for every engine-served service. + r, err := handleXML(t, svc, "GET", "/v20180820/accesspoint") + if err != nil || r.Status != 200 { + t.Fatalf("list on empty store: status=%d err=%v", statusOf(r), err) + } + if got := string(r.Body); !strings.Contains(got, "") { + t.Fatalf("empty list not rendered as an empty element: %s", got) + } + + // Create: the only parameter is the path label, and there is no body at all. + r, err = handleXML(t, svc, "PUT", "/v20180820/accesspoint/ap1") + if err != nil || r.Status != 200 { + t.Fatalf("create: status=%d err=%v", statusOf(r), err) + } + if got := string(r.Body); !strings.Contains(got, "ap1") { + t.Fatalf("create did not echo the path label: %s", got) + } + + // Get addresses the same resource by the same label. + r, err = handleXML(t, svc, "GET", "/v20180820/accesspoint/ap1") + if err != nil || r.Status != 200 { + t.Fatalf("get: status=%d err=%v", statusOf(r), err) + } + if got := string(r.Body); !strings.Contains(got, "ap1") { + t.Fatalf("get returned the wrong resource: %s", got) + } + + // It is in the list, wrapped as a member. + r, _ = handleXML(t, svc, "GET", "/v20180820/accesspoint") + if got := string(r.Body); !strings.Contains(got, "") { + t.Fatalf("created resource is not in the list: %s", got) + } + + // Delete, then the list is empty again. + if _, err := handleXML(t, svc, "DELETE", "/v20180820/accesspoint/ap1"); err != nil { + t.Fatalf("delete: %v", err) + } + r, _ = handleXML(t, svc, "GET", "/v20180820/accesspoint") + if got := string(r.Body); strings.Contains(got, "") { + t.Fatalf("resource survived delete: %s", got) + } +} + +func TestEngineRESTXMLContentType(t *testing.T) { + const svc = "xmlctsvc" + Register(svc, map[string]OpMeta{ + "ListThings": {Verb: "List", Resource: "XCThing", OutputListKey: "Things", + Method: "GET", URI: "/things"}, + }) + + r, err := handleXML(t, svc, "GET", "/things") + if err != nil { + t.Fatalf("list: %v", err) + } + if r.ContentType != "application/xml" { + t.Errorf("ContentType = %q, want application/xml", r.ContentType) + } + if !strings.HasPrefix(string(r.Body), xmlHeader) { + t.Errorf("body is not XML: %s", r.Body) + } +} + +// TestEngineRESTXMLUnmatchedPathIsUnclassified is the guarantee that matters +// most for this protocol, because S3 speaks it. A path the route table does not +// know must decline rather than answer from the generic store. +func TestEngineRESTXMLUnmatchedPathIsUnclassified(t *testing.T) { + const svc = "xmlmisssvc" + Register(svc, map[string]OpMeta{ + "ListThings": {Verb: "List", Resource: "XMThing", OutputListKey: "Things", + Method: "GET", URI: "/v20180820/things"}, + }) + + if _, err := handleXML(t, svc, "GET", "/my-bucket/my-key"); err != ErrUnclassified { + t.Errorf("an S3-shaped path: want ErrUnclassified, got %v", err) + } + if _, err := handleXML(t, svc, "POST", "/v20180820/things"); err != ErrUnclassified { + t.Errorf("known path, wrong method: want ErrUnclassified, got %v", err) + } + if _, err := handleXML(t, "unregistered", "GET", "/v20180820/things"); err != ErrUnclassified { + t.Errorf("unregistered service: want ErrUnclassified, got %v", err) } } From f9204cab53fc966b3e30c1e3cc328ba5331c0b01 Mon Sep 17 00:00:00 2001 From: Sung-Kyu Yoo Date: Sat, 5 Sep 2026 20:48:50 +0900 Subject: [PATCH 04/10] feat: serve rest-xml from the generic CRUD engine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GREEN: go test ./... fully green; make build clean; codegen idempotent (identical hashes across two runs); imports.go unchanged. rest-xml was excluded on the assumption that it had no modelled path. It has one — all 97 of s3-control's operations carry a method and URI template — so the route table that classifies rest-json classifies it too. 94 operations move unimplemented -> auto-crud. Blast radius is exactly one service, measured rather than assumed. s3, cloudfront and route53 gain registry entries but not a single manifest change, because BuildFidelityData gates auto-crud on EngineWired and none of their providers returns ErrUnhandledOp. The gate written for this case did its job. Servable and NeedsBody are now separate questions and the router asks the second one. The engine serves rest-xml without the body, which is what keeps S3's large binary uploads streaming; a test double that fails on Read proves the gateway never touches them. --- internal/codegen/gen_crud_meta.go | 18 +- internal/codegen/gen_crud_meta_test.go | 46 +- internal/gateway/router.go | 17 +- internal/gateway/router_test.go | 46 +- .../generated/crudregistry/registry_gen.go | 415 ++++++++++++++++++ internal/generated/fidelity/manifest_gen.go | 188 ++++---- internal/shared/crud/crud.go | 119 +++-- 7 files changed, 691 insertions(+), 158 deletions(-) diff --git a/internal/codegen/gen_crud_meta.go b/internal/codegen/gen_crud_meta.go index 3cb06ccb..658bdb77 100644 --- a/internal/codegen/gen_crud_meta.go +++ b/internal/codegen/gen_crud_meta.go @@ -132,18 +132,24 @@ func classifyOps(model *ir.Model) []crudOpData { // 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. +// The JSON protocols carry the operation name in X-Amz-Target. rest-json and +// rest-xml do not, but every one of their 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 them too. rest-xml was excluded +// on the assumption that it had no modelled path; it has one, and all 97 of +// s3-control's operations carry it. +// +// query is what is left of PRD Milestone 5. Its operation is a field in the +// form body rather than a header or a path, so nothing here can match a request +// to it and admitting it 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" + return strings.HasPrefix(protocol, "json") || + protocol == "rest-json" || protocol == "rest-xml" } // ServiceCRUDData classifies an engine-servable model's CRUD operations. It diff --git a/internal/codegen/gen_crud_meta_test.go b/internal/codegen/gen_crud_meta_test.go index 932b60df..28c6ed54 100644 --- a/internal/codegen/gen_crud_meta_test.go +++ b/internal/codegen/gen_crud_meta_test.go @@ -92,22 +92,40 @@ func TestServiceCRUDDataJSONUnchanged(t *testing.T) { } } -// 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"}, - ) +// TestServiceCRUDDataAdmitsRESTXML is the codegen half of the rest-xml change. +// This gate and crud.Servable answer the same question and must agree: a +// protocol admitted here but refused there registers operations nothing can +// reach, and the fidelity manifest would publish them as auto-crud. +func TestServiceCRUDDataAdmitsRESTXML(t *testing.T) { + model := crudModel("rest-xml", + ir.Operation{Name: "ListAccessPoints", OutputName: "ListAccessPointsOutput", + HTTPMethod: "GET", HTTPUri: "/v20180820/accesspoint"}, + ) - _, ok := ServiceCRUDData(model) - assert.False(t, ok, "%s must not be engine-servable", protocol) - }) + data, ok := ServiceCRUDData(model) + require.True(t, ok, "rest-xml service must be engine-servable") + + ops := map[string]crudOpData{} + for _, op := range data.Ops { + ops[op.Op] = op } + // The route is the whole classification story for rest-xml, so it has to + // survive into the registry the same way rest-json's does. + assert.Equal(t, "GET", ops["ListAccessPoints"].Method) + assert.Equal(t, "/v20180820/accesspoint", ops["ListAccessPoints"].URI) +} + +// TestServiceCRUDDataRejectsQuery holds what is left of the boundary Milestone 5 +// owns. query puts the operation neither in a header nor in a modelled path — +// it is a field in the form body — so until the engine reads that, admitting it +// would register operations no request can be matched to. +func TestServiceCRUDDataRejectsQuery(t *testing.T) { + model := crudModel("query", + ir.Operation{Name: "DescribeLoadBalancers", OutputName: "DescribeLoadBalancersOutput"}, + ) + + _, ok := ServiceCRUDData(model) + assert.False(t, ok, "query must not be engine-servable yet") } // TestServiceCRUDDataSkipsUnclassifiableService is the rds-data case: a diff --git a/internal/gateway/router.go b/internal/gateway/router.go index 6d59d943..aec4a877 100644 --- a/internal/gateway/router.go +++ b/internal/gateway/router.go @@ -54,12 +54,19 @@ func (sr *ServiceRouter) ServeHTTP(w http.ResponseWriter, r *http.Request) { op := extractOperationName(r, protocol) - // 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. + // Buffer the body for the protocols whose parameters live in it, so the + // engine can re-read it if the provider does not handle the operation. Cheap + // for JSON, rest-json and query payloads. + // + // This asks crud.NeedsBody, not crud.Servable, and the difference is + // rest-xml. The engine serves rest-xml — it classifies the operation from + // the method and path like rest-json — but it must do so without the body: + // S3 speaks rest-xml, its bodies are large binary uploads, and every + // CRUD-shaped S3 Control operation addresses its resource with a path label + // or a query term anyway. Asking the servable question here would buffer + // every PutObject to serve a provider that never reaches the engine. var body []byte - if crud.Servable(protocol) { + if crud.NeedsBody(protocol) { var rerr error if body, rerr = io.ReadAll(r.Body); rerr != nil { writeAWSError(w, protocol, http.StatusBadRequest, "SerializationException", "failed to read request body") diff --git a/internal/gateway/router_test.go b/internal/gateway/router_test.go index 561531ea..b806c637 100644 --- a/internal/gateway/router_test.go +++ b/internal/gateway/router_test.go @@ -219,9 +219,49 @@ func TestServiceRouter_RESTJSONUnmatchedPathDeclinesCleanly(t *testing.T) { 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. +// TestServiceRouter_RESTXMLReachesEngineWithoutBuffering is the gateway half of +// the rest-xml change, and it asserts two things that have to hold together. +// +// The engine must serve the request — it can, because every rest-xml operation +// is bound to a method and URI template — and the gateway must not have read +// the body to let it. Those pull in opposite directions under one predicate, +// which is why Servable and NeedsBody are now separate: S3 speaks rest-xml, and +// buffering a multi-gigabyte PutObject to serve a provider that never reaches +// the engine would be a straight regression. +func TestServiceRouter_RESTXMLReachesEngineWithoutBuffering(t *testing.T) { + const svc = "s3control" + crud.Register(svc, map[string]crud.OpMeta{ + "ListAccessPoints": {Verb: "List", Resource: "GwAccessPoint", OutputListKey: "AccessPointList", + Method: "GET", URI: "/v20180820/accesspoint"}, + }) + router := NewServiceRouter(newDecliningRegistry(svc, plugin.ProtocolRESTXML), nil) + + req := httptest.NewRequest(http.MethodGet, "/v20180820/accesspoint", &failOnReadBody{t: t}) + req.Header.Set("Authorization", + "AWS4-HMAC-SHA256 Credential=AKIA/20130524/us-east-1/s3/aws4_request, Signature=abc") + + w := httptest.NewRecorder() + router.ServeHTTP(w, req) + + require.Equal(t, http.StatusOK, w.Code, "body: %s", w.Body.String()) + assert.Contains(t, w.Body.String(), "", + "rest-xml response is not the engine's XML") + assert.Equal(t, "application/xml", w.Header().Get("Content-Type")) +} + +// failOnReadBody fails the test if anything reads it. It is how "the gateway did +// not buffer this" is made observable: a length check on a captured body cannot +// tell "never read" from "read and restored". +type failOnReadBody struct{ t *testing.T } + +func (f *failOnReadBody) Read([]byte) (int, error) { + f.t.Error("the gateway read a rest-xml request body; S3 uploads must keep streaming") + return 0, io.EOF +} + +// TestServiceRouter_RESTXMLBodyStillUnbuffered pins the exception for the +// service the exception exists for. S3's provider never returns ErrUnhandledOp, +// so it never reaches the engine, and its bodies must keep streaming. func TestServiceRouter_RESTXMLBodyStillUnbuffered(t *testing.T) { var seen []byte reg := plugin.NewRegistry() diff --git a/internal/generated/crudregistry/registry_gen.go b/internal/generated/crudregistry/registry_gen.go index f7fbb548..75c40de0 100644 --- a/internal/generated/crudregistry/registry_gen.go +++ b/internal/generated/crudregistry/registry_gen.go @@ -1263,6 +1263,164 @@ func init() { "UpdateProtectedJob": {Verb: "Update", Resource: "ProtectedJob", OutputListKey: "", OutputItemKey: "protectedJob", Method: "PATCH", URI: "/memberships/{membershipIdentifier}/protectedJobs/{protectedJobIdentifier}"}, "UpdateProtectedQuery": {Verb: "Update", Resource: "ProtectedQuery", OutputListKey: "", OutputItemKey: "protectedQuery", Method: "PATCH", URI: "/memberships/{membershipIdentifier}/protectedQueries/{protectedQueryIdentifier}"}, }) + crud.Register("cloudfront", map[string]crud.OpMeta{ + "CreateAnycastIpList": {Verb: "Create", Resource: "AnycastIpList", OutputListKey: "", OutputItemKey: "AnycastIpList", Method: "POST", URI: "/2020-05-31/anycast-ip-list"}, + "CreateCachePolicy": {Verb: "Create", Resource: "CachePolicy", OutputListKey: "", OutputItemKey: "CachePolicy", Method: "POST", URI: "/2020-05-31/cache-policy"}, + "CreateCloudFrontOriginAccessIdentity": {Verb: "Create", Resource: "CloudFrontOriginAccessIdentity", OutputListKey: "", OutputItemKey: "CloudFrontOriginAccessIdentity", Method: "POST", URI: "/2020-05-31/origin-access-identity/cloudfront"}, + "CreateConnectionFunction": {Verb: "Create", Resource: "ConnectionFunction", OutputListKey: "", OutputItemKey: "ConnectionFunctionSummary", Method: "POST", URI: "/2020-05-31/connection-function"}, + "CreateConnectionGroup": {Verb: "Create", Resource: "ConnectionGroup", OutputListKey: "", OutputItemKey: "ConnectionGroup", Method: "POST", URI: "/2020-05-31/connection-group"}, + "CreateContinuousDeploymentPolicy": {Verb: "Create", Resource: "ContinuousDeploymentPolicy", OutputListKey: "", OutputItemKey: "ContinuousDeploymentPolicy", Method: "POST", URI: "/2020-05-31/continuous-deployment-policy"}, + "CreateDistribution": {Verb: "Create", Resource: "Distribution", OutputListKey: "", OutputItemKey: "Distribution", Method: "POST", URI: "/2020-05-31/distribution"}, + "CreateDistributionTenant": {Verb: "Create", Resource: "DistributionTenant", OutputListKey: "", OutputItemKey: "DistributionTenant", Method: "POST", URI: "/2020-05-31/distribution-tenant"}, + "CreateDistributionWithTags": {Verb: "Create", Resource: "DistributionWithTag", OutputListKey: "", OutputItemKey: "Distribution", Method: "POST", URI: "/2020-05-31/distribution?WithTags"}, + "CreateFieldLevelEncryptionConfig": {Verb: "Create", Resource: "FieldLevelEncryptionConfig", OutputListKey: "", OutputItemKey: "FieldLevelEncryption", Method: "POST", URI: "/2020-05-31/field-level-encryption"}, + "CreateFieldLevelEncryptionProfile": {Verb: "Create", Resource: "FieldLevelEncryptionProfile", OutputListKey: "", OutputItemKey: "FieldLevelEncryptionProfile", Method: "POST", URI: "/2020-05-31/field-level-encryption-profile"}, + "CreateFunction": {Verb: "Create", Resource: "Function", OutputListKey: "", OutputItemKey: "FunctionSummary", Method: "POST", URI: "/2020-05-31/function"}, + "CreateInvalidation": {Verb: "Create", Resource: "Invalidation", OutputListKey: "", OutputItemKey: "Invalidation", Method: "POST", URI: "/2020-05-31/distribution/{DistributionId}/invalidation"}, + "CreateInvalidationForDistributionTenant": {Verb: "Create", Resource: "InvalidationForDistributionTenant", OutputListKey: "", OutputItemKey: "Invalidation", Method: "POST", URI: "/2020-05-31/distribution-tenant/{Id}/invalidation"}, + "CreateKeyGroup": {Verb: "Create", Resource: "KeyGroup", OutputListKey: "", OutputItemKey: "KeyGroup", Method: "POST", URI: "/2020-05-31/key-group"}, + "CreateKeyValueStore": {Verb: "Create", Resource: "KeyValueStore", OutputListKey: "", OutputItemKey: "KeyValueStore", Method: "POST", URI: "/2020-05-31/key-value-store"}, + "CreateMonitoringSubscription": {Verb: "Create", Resource: "MonitoringSubscription", OutputListKey: "", OutputItemKey: "MonitoringSubscription", Method: "POST", URI: "/2020-05-31/distributions/{DistributionId}/monitoring-subscription"}, + "CreateOriginAccessControl": {Verb: "Create", Resource: "OriginAccessControl", OutputListKey: "", OutputItemKey: "OriginAccessControl", Method: "POST", URI: "/2020-05-31/origin-access-control"}, + "CreateOriginRequestPolicy": {Verb: "Create", Resource: "OriginRequestPolicy", OutputListKey: "", OutputItemKey: "OriginRequestPolicy", Method: "POST", URI: "/2020-05-31/origin-request-policy"}, + "CreatePublicKey": {Verb: "Create", Resource: "PublicKey", OutputListKey: "", OutputItemKey: "PublicKey", Method: "POST", URI: "/2020-05-31/public-key"}, + "CreateRealtimeLogConfig": {Verb: "Create", Resource: "RealtimeLogConfig", OutputListKey: "", OutputItemKey: "RealtimeLogConfig", Method: "POST", URI: "/2020-05-31/realtime-log-config"}, + "CreateResponseHeadersPolicy": {Verb: "Create", Resource: "ResponseHeadersPolicy", OutputListKey: "", OutputItemKey: "ResponseHeadersPolicy", Method: "POST", URI: "/2020-05-31/response-headers-policy"}, + "CreateStreamingDistribution": {Verb: "Create", Resource: "StreamingDistribution", OutputListKey: "", OutputItemKey: "StreamingDistribution", Method: "POST", URI: "/2020-05-31/streaming-distribution"}, + "CreateStreamingDistributionWithTags": {Verb: "Create", Resource: "StreamingDistributionWithTag", OutputListKey: "", OutputItemKey: "StreamingDistribution", Method: "POST", URI: "/2020-05-31/streaming-distribution?WithTags"}, + "CreateTrustStore": {Verb: "Create", Resource: "TrustStore", OutputListKey: "", OutputItemKey: "TrustStore", Method: "POST", URI: "/2020-05-31/trust-store"}, + "CreateVpcOrigin": {Verb: "Create", Resource: "VpcOrigin", OutputListKey: "", OutputItemKey: "VpcOrigin", Method: "POST", URI: "/2020-05-31/vpc-origin"}, + "DeleteAnycastIpList": {Verb: "Delete", Resource: "AnycastIpList", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2020-05-31/anycast-ip-list/{Id}"}, + "DeleteCachePolicy": {Verb: "Delete", Resource: "CachePolicy", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2020-05-31/cache-policy/{Id}"}, + "DeleteCloudFrontOriginAccessIdentity": {Verb: "Delete", Resource: "CloudFrontOriginAccessIdentity", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2020-05-31/origin-access-identity/cloudfront/{Id}"}, + "DeleteConnectionFunction": {Verb: "Delete", Resource: "ConnectionFunction", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2020-05-31/connection-function/{Id}"}, + "DeleteConnectionGroup": {Verb: "Delete", Resource: "ConnectionGroup", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2020-05-31/connection-group/{Id}"}, + "DeleteContinuousDeploymentPolicy": {Verb: "Delete", Resource: "ContinuousDeploymentPolicy", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2020-05-31/continuous-deployment-policy/{Id}"}, + "DeleteDistribution": {Verb: "Delete", Resource: "Distribution", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2020-05-31/distribution/{Id}"}, + "DeleteDistributionTenant": {Verb: "Delete", Resource: "DistributionTenant", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2020-05-31/distribution-tenant/{Id}"}, + "DeleteFieldLevelEncryptionConfig": {Verb: "Delete", Resource: "FieldLevelEncryptionConfig", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2020-05-31/field-level-encryption/{Id}"}, + "DeleteFieldLevelEncryptionProfile": {Verb: "Delete", Resource: "FieldLevelEncryptionProfile", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2020-05-31/field-level-encryption-profile/{Id}"}, + "DeleteFunction": {Verb: "Delete", Resource: "Function", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2020-05-31/function/{Name}"}, + "DeleteKeyGroup": {Verb: "Delete", Resource: "KeyGroup", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2020-05-31/key-group/{Id}"}, + "DeleteKeyValueStore": {Verb: "Delete", Resource: "KeyValueStore", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2020-05-31/key-value-store/{Name}"}, + "DeleteMonitoringSubscription": {Verb: "Delete", Resource: "MonitoringSubscription", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2020-05-31/distributions/{DistributionId}/monitoring-subscription"}, + "DeleteOriginAccessControl": {Verb: "Delete", Resource: "OriginAccessControl", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2020-05-31/origin-access-control/{Id}"}, + "DeleteOriginRequestPolicy": {Verb: "Delete", Resource: "OriginRequestPolicy", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2020-05-31/origin-request-policy/{Id}"}, + "DeletePublicKey": {Verb: "Delete", Resource: "PublicKey", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2020-05-31/public-key/{Id}"}, + "DeleteRealtimeLogConfig": {Verb: "Delete", Resource: "RealtimeLogConfig", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/2020-05-31/delete-realtime-log-config"}, + "DeleteResourcePolicy": {Verb: "Delete", Resource: "ResourcePolicy", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/2020-05-31/delete-resource-policy"}, + "DeleteResponseHeadersPolicy": {Verb: "Delete", Resource: "ResponseHeadersPolicy", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2020-05-31/response-headers-policy/{Id}"}, + "DeleteStreamingDistribution": {Verb: "Delete", Resource: "StreamingDistribution", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2020-05-31/streaming-distribution/{Id}"}, + "DeleteTrustStore": {Verb: "Delete", Resource: "TrustStore", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2020-05-31/trust-store/{Id}"}, + "DeleteVpcOrigin": {Verb: "Delete", Resource: "VpcOrigin", OutputListKey: "", OutputItemKey: "VpcOrigin", Method: "DELETE", URI: "/2020-05-31/vpc-origin/{Id}"}, + "DescribeConnectionFunction": {Verb: "Get", Resource: "ConnectionFunction", OutputListKey: "", OutputItemKey: "ConnectionFunctionSummary", Method: "GET", URI: "/2020-05-31/connection-function/{Identifier}/describe"}, + "DescribeFunction": {Verb: "Get", Resource: "Function", OutputListKey: "", OutputItemKey: "FunctionSummary", Method: "GET", URI: "/2020-05-31/function/{Name}/describe"}, + "DescribeKeyValueStore": {Verb: "Get", Resource: "KeyValueStore", OutputListKey: "", OutputItemKey: "KeyValueStore", Method: "GET", URI: "/2020-05-31/key-value-store/{Name}"}, + "GetAnycastIpList": {Verb: "Get", Resource: "AnycastIpList", OutputListKey: "", OutputItemKey: "AnycastIpList", Method: "GET", URI: "/2020-05-31/anycast-ip-list/{Id}"}, + "GetCachePolicy": {Verb: "Get", Resource: "CachePolicy", OutputListKey: "", OutputItemKey: "CachePolicy", Method: "GET", URI: "/2020-05-31/cache-policy/{Id}"}, + "GetCachePolicyConfig": {Verb: "Get", Resource: "CachePolicyConfig", OutputListKey: "", OutputItemKey: "CachePolicyConfig", Method: "GET", URI: "/2020-05-31/cache-policy/{Id}/config"}, + "GetCloudFrontOriginAccessIdentity": {Verb: "Get", Resource: "CloudFrontOriginAccessIdentity", OutputListKey: "", OutputItemKey: "CloudFrontOriginAccessIdentity", Method: "GET", URI: "/2020-05-31/origin-access-identity/cloudfront/{Id}"}, + "GetCloudFrontOriginAccessIdentityConfig": {Verb: "Get", Resource: "CloudFrontOriginAccessIdentityConfig", OutputListKey: "", OutputItemKey: "CloudFrontOriginAccessIdentityConfig", Method: "GET", URI: "/2020-05-31/origin-access-identity/cloudfront/{Id}/config"}, + "GetConnectionFunction": {Verb: "Get", Resource: "ConnectionFunction", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/2020-05-31/connection-function/{Identifier}"}, + "GetConnectionGroup": {Verb: "Get", Resource: "ConnectionGroup", OutputListKey: "", OutputItemKey: "ConnectionGroup", Method: "GET", URI: "/2020-05-31/connection-group/{Identifier}"}, + "GetConnectionGroupByRoutingEndpoint": {Verb: "Get", Resource: "ConnectionGroupByRoutingEndpoint", OutputListKey: "", OutputItemKey: "ConnectionGroup", Method: "GET", URI: "/2020-05-31/connection-group"}, + "GetContinuousDeploymentPolicy": {Verb: "Get", Resource: "ContinuousDeploymentPolicy", OutputListKey: "", OutputItemKey: "ContinuousDeploymentPolicy", Method: "GET", URI: "/2020-05-31/continuous-deployment-policy/{Id}"}, + "GetContinuousDeploymentPolicyConfig": {Verb: "Get", Resource: "ContinuousDeploymentPolicyConfig", OutputListKey: "", OutputItemKey: "ContinuousDeploymentPolicyConfig", Method: "GET", URI: "/2020-05-31/continuous-deployment-policy/{Id}/config"}, + "GetDistribution": {Verb: "Get", Resource: "Distribution", OutputListKey: "", OutputItemKey: "Distribution", Method: "GET", URI: "/2020-05-31/distribution/{Id}"}, + "GetDistributionConfig": {Verb: "Get", Resource: "DistributionConfig", OutputListKey: "", OutputItemKey: "DistributionConfig", Method: "GET", URI: "/2020-05-31/distribution/{Id}/config"}, + "GetDistributionTenant": {Verb: "Get", Resource: "DistributionTenant", OutputListKey: "", OutputItemKey: "DistributionTenant", Method: "GET", URI: "/2020-05-31/distribution-tenant/{Identifier}"}, + "GetDistributionTenantByDomain": {Verb: "Get", Resource: "DistributionTenantByDomain", OutputListKey: "", OutputItemKey: "DistributionTenant", Method: "GET", URI: "/2020-05-31/distribution-tenant"}, + "GetFieldLevelEncryption": {Verb: "Get", Resource: "FieldLevelEncryption", OutputListKey: "", OutputItemKey: "FieldLevelEncryption", Method: "GET", URI: "/2020-05-31/field-level-encryption/{Id}"}, + "GetFieldLevelEncryptionConfig": {Verb: "Get", Resource: "FieldLevelEncryptionConfig", OutputListKey: "", OutputItemKey: "FieldLevelEncryptionConfig", Method: "GET", URI: "/2020-05-31/field-level-encryption/{Id}/config"}, + "GetFieldLevelEncryptionProfile": {Verb: "Get", Resource: "FieldLevelEncryptionProfile", OutputListKey: "", OutputItemKey: "FieldLevelEncryptionProfile", Method: "GET", URI: "/2020-05-31/field-level-encryption-profile/{Id}"}, + "GetFieldLevelEncryptionProfileConfig": {Verb: "Get", Resource: "FieldLevelEncryptionProfileConfig", OutputListKey: "", OutputItemKey: "FieldLevelEncryptionProfileConfig", Method: "GET", URI: "/2020-05-31/field-level-encryption-profile/{Id}/config"}, + "GetFunction": {Verb: "Get", Resource: "Function", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/2020-05-31/function/{Name}"}, + "GetInvalidation": {Verb: "Get", Resource: "Invalidation", OutputListKey: "", OutputItemKey: "Invalidation", Method: "GET", URI: "/2020-05-31/distribution/{DistributionId}/invalidation/{Id}"}, + "GetInvalidationForDistributionTenant": {Verb: "Get", Resource: "InvalidationForDistributionTenant", OutputListKey: "", OutputItemKey: "Invalidation", Method: "GET", URI: "/2020-05-31/distribution-tenant/{DistributionTenantId}/invalidation/{Id}"}, + "GetKeyGroup": {Verb: "Get", Resource: "KeyGroup", OutputListKey: "", OutputItemKey: "KeyGroup", Method: "GET", URI: "/2020-05-31/key-group/{Id}"}, + "GetKeyGroupConfig": {Verb: "Get", Resource: "KeyGroupConfig", OutputListKey: "", OutputItemKey: "KeyGroupConfig", Method: "GET", URI: "/2020-05-31/key-group/{Id}/config"}, + "GetManagedCertificateDetails": {Verb: "Get", Resource: "ManagedCertificateDetail", OutputListKey: "", OutputItemKey: "ManagedCertificateDetails", Method: "GET", URI: "/2020-05-31/managed-certificate/{Identifier}"}, + "GetMonitoringSubscription": {Verb: "Get", Resource: "MonitoringSubscription", OutputListKey: "", OutputItemKey: "MonitoringSubscription", Method: "GET", URI: "/2020-05-31/distributions/{DistributionId}/monitoring-subscription"}, + "GetOriginAccessControl": {Verb: "Get", Resource: "OriginAccessControl", OutputListKey: "", OutputItemKey: "OriginAccessControl", Method: "GET", URI: "/2020-05-31/origin-access-control/{Id}"}, + "GetOriginAccessControlConfig": {Verb: "Get", Resource: "OriginAccessControlConfig", OutputListKey: "", OutputItemKey: "OriginAccessControlConfig", Method: "GET", URI: "/2020-05-31/origin-access-control/{Id}/config"}, + "GetOriginRequestPolicy": {Verb: "Get", Resource: "OriginRequestPolicy", OutputListKey: "", OutputItemKey: "OriginRequestPolicy", Method: "GET", URI: "/2020-05-31/origin-request-policy/{Id}"}, + "GetOriginRequestPolicyConfig": {Verb: "Get", Resource: "OriginRequestPolicyConfig", OutputListKey: "", OutputItemKey: "OriginRequestPolicyConfig", Method: "GET", URI: "/2020-05-31/origin-request-policy/{Id}/config"}, + "GetPublicKey": {Verb: "Get", Resource: "PublicKey", OutputListKey: "", OutputItemKey: "PublicKey", Method: "GET", URI: "/2020-05-31/public-key/{Id}"}, + "GetPublicKeyConfig": {Verb: "Get", Resource: "PublicKeyConfig", OutputListKey: "", OutputItemKey: "PublicKeyConfig", Method: "GET", URI: "/2020-05-31/public-key/{Id}/config"}, + "GetRealtimeLogConfig": {Verb: "Get", Resource: "RealtimeLogConfig", OutputListKey: "", OutputItemKey: "RealtimeLogConfig", Method: "POST", URI: "/2020-05-31/get-realtime-log-config"}, + "GetResourcePolicy": {Verb: "Get", Resource: "ResourcePolicy", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/2020-05-31/get-resource-policy"}, + "GetResponseHeadersPolicy": {Verb: "Get", Resource: "ResponseHeadersPolicy", OutputListKey: "", OutputItemKey: "ResponseHeadersPolicy", Method: "GET", URI: "/2020-05-31/response-headers-policy/{Id}"}, + "GetResponseHeadersPolicyConfig": {Verb: "Get", Resource: "ResponseHeadersPolicyConfig", OutputListKey: "", OutputItemKey: "ResponseHeadersPolicyConfig", Method: "GET", URI: "/2020-05-31/response-headers-policy/{Id}/config"}, + "GetStreamingDistribution": {Verb: "Get", Resource: "StreamingDistribution", OutputListKey: "", OutputItemKey: "StreamingDistribution", Method: "GET", URI: "/2020-05-31/streaming-distribution/{Id}"}, + "GetStreamingDistributionConfig": {Verb: "Get", Resource: "StreamingDistributionConfig", OutputListKey: "", OutputItemKey: "StreamingDistributionConfig", Method: "GET", URI: "/2020-05-31/streaming-distribution/{Id}/config"}, + "GetTrustStore": {Verb: "Get", Resource: "TrustStore", OutputListKey: "", OutputItemKey: "TrustStore", Method: "GET", URI: "/2020-05-31/trust-store/{Identifier}"}, + "GetVpcOrigin": {Verb: "Get", Resource: "VpcOrigin", OutputListKey: "", OutputItemKey: "VpcOrigin", Method: "GET", URI: "/2020-05-31/vpc-origin/{Id}"}, + "ListAnycastIpLists": {Verb: "List", Resource: "AnycastIpList", OutputListKey: "", OutputItemKey: "AnycastIpLists", Method: "GET", URI: "/2020-05-31/anycast-ip-list"}, + "ListCachePolicies": {Verb: "List", Resource: "CachePolicy", OutputListKey: "", OutputItemKey: "CachePolicyList", Method: "GET", URI: "/2020-05-31/cache-policy"}, + "ListCloudFrontOriginAccessIdentities": {Verb: "List", Resource: "CloudFrontOriginAccessIdentity", OutputListKey: "", OutputItemKey: "CloudFrontOriginAccessIdentityList", Method: "GET", URI: "/2020-05-31/origin-access-identity/cloudfront"}, + "ListConflictingAliases": {Verb: "List", Resource: "ConflictingAliase", OutputListKey: "", OutputItemKey: "ConflictingAliasesList", Method: "GET", URI: "/2020-05-31/conflicting-alias"}, + "ListConnectionFunctions": {Verb: "List", Resource: "ConnectionFunction", OutputListKey: "ConnectionFunctions", OutputItemKey: "", Method: "POST", URI: "/2020-05-31/connection-functions"}, + "ListConnectionGroups": {Verb: "List", Resource: "ConnectionGroup", OutputListKey: "ConnectionGroups", OutputItemKey: "", Method: "POST", URI: "/2020-05-31/connection-groups"}, + "ListContinuousDeploymentPolicies": {Verb: "List", Resource: "ContinuousDeploymentPolicy", OutputListKey: "", OutputItemKey: "ContinuousDeploymentPolicyList", Method: "GET", URI: "/2020-05-31/continuous-deployment-policy"}, + "ListDistributionTenants": {Verb: "List", Resource: "DistributionTenant", OutputListKey: "DistributionTenantList", OutputItemKey: "", Method: "POST", URI: "/2020-05-31/distribution-tenants"}, + "ListDistributionTenantsByCustomization": {Verb: "List", Resource: "DistributionTenantsByCustomization", OutputListKey: "DistributionTenantList", OutputItemKey: "", Method: "POST", URI: "/2020-05-31/distribution-tenants-by-customization"}, + "ListDistributions": {Verb: "List", Resource: "Distribution", OutputListKey: "", OutputItemKey: "DistributionList", Method: "GET", URI: "/2020-05-31/distribution"}, + "ListDistributionsByAnycastIpListId": {Verb: "List", Resource: "DistributionsByAnycastIpListId", OutputListKey: "", OutputItemKey: "DistributionList", Method: "GET", URI: "/2020-05-31/distributionsByAnycastIpListId/{AnycastIpListId}"}, + "ListDistributionsByCachePolicyId": {Verb: "List", Resource: "DistributionsByCachePolicyId", OutputListKey: "", OutputItemKey: "DistributionIdList", Method: "GET", URI: "/2020-05-31/distributionsByCachePolicyId/{CachePolicyId}"}, + "ListDistributionsByConnectionFunction": {Verb: "List", Resource: "DistributionsByConnectionFunction", OutputListKey: "", OutputItemKey: "DistributionList", Method: "GET", URI: "/2020-05-31/distributionsByConnectionFunction"}, + "ListDistributionsByConnectionMode": {Verb: "List", Resource: "DistributionsByConnectionMode", OutputListKey: "", OutputItemKey: "DistributionList", Method: "GET", URI: "/2020-05-31/distributionsByConnectionMode/{ConnectionMode}"}, + "ListDistributionsByKeyGroup": {Verb: "List", Resource: "DistributionsByKeyGroup", OutputListKey: "", OutputItemKey: "DistributionIdList", Method: "GET", URI: "/2020-05-31/distributionsByKeyGroupId/{KeyGroupId}"}, + "ListDistributionsByOriginRequestPolicyId": {Verb: "List", Resource: "DistributionsByOriginRequestPolicyId", OutputListKey: "", OutputItemKey: "DistributionIdList", Method: "GET", URI: "/2020-05-31/distributionsByOriginRequestPolicyId/{OriginRequestPolicyId}"}, + "ListDistributionsByOwnedResource": {Verb: "List", Resource: "DistributionsByOwnedResource", OutputListKey: "", OutputItemKey: "DistributionList", Method: "GET", URI: "/2020-05-31/distributionsByOwnedResource/{ResourceArn}"}, + "ListDistributionsByRealtimeLogConfig": {Verb: "List", Resource: "DistributionsByRealtimeLogConfig", OutputListKey: "", OutputItemKey: "DistributionList", Method: "POST", URI: "/2020-05-31/distributionsByRealtimeLogConfig"}, + "ListDistributionsByResponseHeadersPolicyId": {Verb: "List", Resource: "DistributionsByResponseHeadersPolicyId", OutputListKey: "", OutputItemKey: "DistributionIdList", Method: "GET", URI: "/2020-05-31/distributionsByResponseHeadersPolicyId/{ResponseHeadersPolicyId}"}, + "ListDistributionsByTrustStore": {Verb: "List", Resource: "DistributionsByTrustStore", OutputListKey: "", OutputItemKey: "DistributionList", Method: "GET", URI: "/2020-05-31/distributionsByTrustStore"}, + "ListDistributionsByVpcOriginId": {Verb: "List", Resource: "DistributionsByVpcOriginId", OutputListKey: "", OutputItemKey: "DistributionIdList", Method: "GET", URI: "/2020-05-31/distributionsByVpcOriginId/{VpcOriginId}"}, + "ListDistributionsByWebACLId": {Verb: "List", Resource: "DistributionsByWebACLId", OutputListKey: "", OutputItemKey: "DistributionList", Method: "GET", URI: "/2020-05-31/distributionsByWebACLId/{WebACLId}"}, + "ListDomainConflicts": {Verb: "List", Resource: "DomainConflict", OutputListKey: "DomainConflicts", OutputItemKey: "", Method: "POST", URI: "/2020-05-31/domain-conflicts"}, + "ListFieldLevelEncryptionConfigs": {Verb: "List", Resource: "FieldLevelEncryptionConfig", OutputListKey: "", OutputItemKey: "FieldLevelEncryptionList", Method: "GET", URI: "/2020-05-31/field-level-encryption"}, + "ListFieldLevelEncryptionProfiles": {Verb: "List", Resource: "FieldLevelEncryptionProfile", OutputListKey: "", OutputItemKey: "FieldLevelEncryptionProfileList", Method: "GET", URI: "/2020-05-31/field-level-encryption-profile"}, + "ListFunctions": {Verb: "List", Resource: "Function", OutputListKey: "", OutputItemKey: "FunctionList", Method: "GET", URI: "/2020-05-31/function"}, + "ListInvalidations": {Verb: "List", Resource: "Invalidation", OutputListKey: "", OutputItemKey: "InvalidationList", Method: "GET", URI: "/2020-05-31/distribution/{DistributionId}/invalidation"}, + "ListInvalidationsForDistributionTenant": {Verb: "List", Resource: "InvalidationsForDistributionTenant", OutputListKey: "", OutputItemKey: "InvalidationList", Method: "GET", URI: "/2020-05-31/distribution-tenant/{Id}/invalidation"}, + "ListKeyGroups": {Verb: "List", Resource: "KeyGroup", OutputListKey: "", OutputItemKey: "KeyGroupList", Method: "GET", URI: "/2020-05-31/key-group"}, + "ListKeyValueStores": {Verb: "List", Resource: "KeyValueStore", OutputListKey: "", OutputItemKey: "KeyValueStoreList", Method: "GET", URI: "/2020-05-31/key-value-store"}, + "ListOriginAccessControls": {Verb: "List", Resource: "OriginAccessControl", OutputListKey: "", OutputItemKey: "OriginAccessControlList", Method: "GET", URI: "/2020-05-31/origin-access-control"}, + "ListOriginRequestPolicies": {Verb: "List", Resource: "OriginRequestPolicy", OutputListKey: "", OutputItemKey: "OriginRequestPolicyList", Method: "GET", URI: "/2020-05-31/origin-request-policy"}, + "ListPublicKeys": {Verb: "List", Resource: "PublicKey", OutputListKey: "", OutputItemKey: "PublicKeyList", Method: "GET", URI: "/2020-05-31/public-key"}, + "ListRealtimeLogConfigs": {Verb: "List", Resource: "RealtimeLogConfig", OutputListKey: "", OutputItemKey: "RealtimeLogConfigs", Method: "GET", URI: "/2020-05-31/realtime-log-config"}, + "ListResponseHeadersPolicies": {Verb: "List", Resource: "ResponseHeadersPolicy", OutputListKey: "", OutputItemKey: "ResponseHeadersPolicyList", Method: "GET", URI: "/2020-05-31/response-headers-policy"}, + "ListStreamingDistributions": {Verb: "List", Resource: "StreamingDistribution", OutputListKey: "", OutputItemKey: "StreamingDistributionList", Method: "GET", URI: "/2020-05-31/streaming-distribution"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "", OutputItemKey: "Tags", Method: "GET", URI: "/2020-05-31/tagging"}, + "ListTrustStores": {Verb: "List", Resource: "TrustStore", OutputListKey: "TrustStoreList", OutputItemKey: "", Method: "POST", URI: "/2020-05-31/trust-stores"}, + "ListVpcOrigins": {Verb: "List", Resource: "VpcOrigin", OutputListKey: "", OutputItemKey: "VpcOriginList", Method: "GET", URI: "/2020-05-31/vpc-origin"}, + "PutResourcePolicy": {Verb: "Update", Resource: "ResourcePolicy", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/2020-05-31/put-resource-policy"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/2020-05-31/tagging?Operation=Tag"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/2020-05-31/tagging?Operation=Untag"}, + "UpdateAnycastIpList": {Verb: "Update", Resource: "AnycastIpList", OutputListKey: "", OutputItemKey: "AnycastIpList", Method: "PUT", URI: "/2020-05-31/anycast-ip-list/{Id}"}, + "UpdateCachePolicy": {Verb: "Update", Resource: "CachePolicy", OutputListKey: "", OutputItemKey: "CachePolicy", Method: "PUT", URI: "/2020-05-31/cache-policy/{Id}"}, + "UpdateCloudFrontOriginAccessIdentity": {Verb: "Update", Resource: "CloudFrontOriginAccessIdentity", OutputListKey: "", OutputItemKey: "CloudFrontOriginAccessIdentity", Method: "PUT", URI: "/2020-05-31/origin-access-identity/cloudfront/{Id}/config"}, + "UpdateConnectionFunction": {Verb: "Update", Resource: "ConnectionFunction", OutputListKey: "", OutputItemKey: "ConnectionFunctionSummary", Method: "PUT", URI: "/2020-05-31/connection-function/{Id}"}, + "UpdateConnectionGroup": {Verb: "Update", Resource: "ConnectionGroup", OutputListKey: "", OutputItemKey: "ConnectionGroup", Method: "PUT", URI: "/2020-05-31/connection-group/{Id}"}, + "UpdateContinuousDeploymentPolicy": {Verb: "Update", Resource: "ContinuousDeploymentPolicy", OutputListKey: "", OutputItemKey: "ContinuousDeploymentPolicy", Method: "PUT", URI: "/2020-05-31/continuous-deployment-policy/{Id}"}, + "UpdateDistribution": {Verb: "Update", Resource: "Distribution", OutputListKey: "", OutputItemKey: "Distribution", Method: "PUT", URI: "/2020-05-31/distribution/{Id}/config"}, + "UpdateDistributionTenant": {Verb: "Update", Resource: "DistributionTenant", OutputListKey: "", OutputItemKey: "DistributionTenant", Method: "PUT", URI: "/2020-05-31/distribution-tenant/{Id}"}, + "UpdateDistributionWithStagingConfig": {Verb: "Update", Resource: "DistributionWithStagingConfig", OutputListKey: "", OutputItemKey: "Distribution", Method: "PUT", URI: "/2020-05-31/distribution/{Id}/promote-staging-config"}, + "UpdateDomainAssociation": {Verb: "Update", Resource: "DomainAssociation", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/2020-05-31/domain-association"}, + "UpdateFieldLevelEncryptionConfig": {Verb: "Update", Resource: "FieldLevelEncryptionConfig", OutputListKey: "", OutputItemKey: "FieldLevelEncryption", Method: "PUT", URI: "/2020-05-31/field-level-encryption/{Id}/config"}, + "UpdateFieldLevelEncryptionProfile": {Verb: "Update", Resource: "FieldLevelEncryptionProfile", OutputListKey: "", OutputItemKey: "FieldLevelEncryptionProfile", Method: "PUT", URI: "/2020-05-31/field-level-encryption-profile/{Id}/config"}, + "UpdateFunction": {Verb: "Update", Resource: "Function", OutputListKey: "", OutputItemKey: "FunctionSummary", Method: "PUT", URI: "/2020-05-31/function/{Name}"}, + "UpdateKeyGroup": {Verb: "Update", Resource: "KeyGroup", OutputListKey: "", OutputItemKey: "KeyGroup", Method: "PUT", URI: "/2020-05-31/key-group/{Id}"}, + "UpdateKeyValueStore": {Verb: "Update", Resource: "KeyValueStore", OutputListKey: "", OutputItemKey: "KeyValueStore", Method: "PUT", URI: "/2020-05-31/key-value-store/{Name}"}, + "UpdateOriginAccessControl": {Verb: "Update", Resource: "OriginAccessControl", OutputListKey: "", OutputItemKey: "OriginAccessControl", Method: "PUT", URI: "/2020-05-31/origin-access-control/{Id}/config"}, + "UpdateOriginRequestPolicy": {Verb: "Update", Resource: "OriginRequestPolicy", OutputListKey: "", OutputItemKey: "OriginRequestPolicy", Method: "PUT", URI: "/2020-05-31/origin-request-policy/{Id}"}, + "UpdatePublicKey": {Verb: "Update", Resource: "PublicKey", OutputListKey: "", OutputItemKey: "PublicKey", Method: "PUT", URI: "/2020-05-31/public-key/{Id}/config"}, + "UpdateRealtimeLogConfig": {Verb: "Update", Resource: "RealtimeLogConfig", OutputListKey: "", OutputItemKey: "RealtimeLogConfig", Method: "PUT", URI: "/2020-05-31/realtime-log-config"}, + "UpdateResponseHeadersPolicy": {Verb: "Update", Resource: "ResponseHeadersPolicy", OutputListKey: "", OutputItemKey: "ResponseHeadersPolicy", Method: "PUT", URI: "/2020-05-31/response-headers-policy/{Id}"}, + "UpdateStreamingDistribution": {Verb: "Update", Resource: "StreamingDistribution", OutputListKey: "", OutputItemKey: "StreamingDistribution", Method: "PUT", URI: "/2020-05-31/streaming-distribution/{Id}/config"}, + "UpdateTrustStore": {Verb: "Update", Resource: "TrustStore", OutputListKey: "", OutputItemKey: "TrustStore", Method: "PUT", URI: "/2020-05-31/trust-store/{Id}"}, + "UpdateVpcOrigin": {Verb: "Update", Resource: "VpcOrigin", OutputListKey: "", OutputItemKey: "VpcOrigin", Method: "PUT", URI: "/2020-05-31/vpc-origin/{Id}"}, + }) crud.Register("cloudhsmv2", map[string]crud.OpMeta{ "CreateCluster": {Verb: "Create", Resource: "Cluster", OutputListKey: "", OutputItemKey: "Cluster"}, "CreateHsm": {Verb: "Create", Resource: "Hsm", OutputListKey: "", OutputItemKey: "Hsm"}, @@ -6428,6 +6586,69 @@ func init() { "TagResources": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/TagResources"}, "UntagResources": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/UntagResources"}, }) + crud.Register("route53", map[string]crud.OpMeta{ + "CreateCidrCollection": {Verb: "Create", Resource: "CidrCollection", OutputListKey: "", OutputItemKey: "Collection", Method: "POST", URI: "/2013-04-01/cidrcollection"}, + "CreateHealthCheck": {Verb: "Create", Resource: "HealthCheck", OutputListKey: "", OutputItemKey: "HealthCheck", Method: "POST", URI: "/2013-04-01/healthcheck"}, + "CreateHostedZone": {Verb: "Create", Resource: "HostedZone", OutputListKey: "", OutputItemKey: "ChangeInfo", Method: "POST", URI: "/2013-04-01/hostedzone"}, + "CreateKeySigningKey": {Verb: "Create", Resource: "KeySigningKey", OutputListKey: "", OutputItemKey: "ChangeInfo", Method: "POST", URI: "/2013-04-01/keysigningkey"}, + "CreateQueryLoggingConfig": {Verb: "Create", Resource: "QueryLoggingConfig", OutputListKey: "", OutputItemKey: "QueryLoggingConfig", Method: "POST", URI: "/2013-04-01/queryloggingconfig"}, + "CreateReusableDelegationSet": {Verb: "Create", Resource: "ReusableDelegationSet", OutputListKey: "", OutputItemKey: "DelegationSet", Method: "POST", URI: "/2013-04-01/delegationset"}, + "CreateTrafficPolicy": {Verb: "Create", Resource: "TrafficPolicy", OutputListKey: "", OutputItemKey: "TrafficPolicy", Method: "POST", URI: "/2013-04-01/trafficpolicy"}, + "CreateTrafficPolicyInstance": {Verb: "Create", Resource: "TrafficPolicyInstance", OutputListKey: "", OutputItemKey: "TrafficPolicyInstance", Method: "POST", URI: "/2013-04-01/trafficpolicyinstance"}, + "CreateTrafficPolicyVersion": {Verb: "Create", Resource: "TrafficPolicyVersion", OutputListKey: "", OutputItemKey: "TrafficPolicy", Method: "POST", URI: "/2013-04-01/trafficpolicy/{Id}"}, + "CreateVPCAssociationAuthorization": {Verb: "Create", Resource: "VPCAssociationAuthorization", OutputListKey: "", OutputItemKey: "VPC", Method: "POST", URI: "/2013-04-01/hostedzone/{HostedZoneId}/authorizevpcassociation"}, + "DeleteCidrCollection": {Verb: "Delete", Resource: "CidrCollection", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2013-04-01/cidrcollection/{Id}"}, + "DeleteHealthCheck": {Verb: "Delete", Resource: "HealthCheck", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2013-04-01/healthcheck/{HealthCheckId}"}, + "DeleteHostedZone": {Verb: "Delete", Resource: "HostedZone", OutputListKey: "", OutputItemKey: "ChangeInfo", Method: "DELETE", URI: "/2013-04-01/hostedzone/{Id}"}, + "DeleteKeySigningKey": {Verb: "Delete", Resource: "KeySigningKey", OutputListKey: "", OutputItemKey: "ChangeInfo", Method: "DELETE", URI: "/2013-04-01/keysigningkey/{HostedZoneId}/{Name}"}, + "DeleteQueryLoggingConfig": {Verb: "Delete", Resource: "QueryLoggingConfig", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2013-04-01/queryloggingconfig/{Id}"}, + "DeleteReusableDelegationSet": {Verb: "Delete", Resource: "ReusableDelegationSet", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2013-04-01/delegationset/{Id}"}, + "DeleteTrafficPolicy": {Verb: "Delete", Resource: "TrafficPolicy", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2013-04-01/trafficpolicy/{Id}/{Version}"}, + "DeleteTrafficPolicyInstance": {Verb: "Delete", Resource: "TrafficPolicyInstance", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/2013-04-01/trafficpolicyinstance/{Id}"}, + "DeleteVPCAssociationAuthorization": {Verb: "Delete", Resource: "VPCAssociationAuthorization", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/2013-04-01/hostedzone/{HostedZoneId}/deauthorizevpcassociation"}, + "GetAccountLimit": {Verb: "Get", Resource: "AccountLimit", OutputListKey: "", OutputItemKey: "Limit", Method: "GET", URI: "/2013-04-01/accountlimit/{Type}"}, + "GetChange": {Verb: "Get", Resource: "Change", OutputListKey: "", OutputItemKey: "ChangeInfo", Method: "GET", URI: "/2013-04-01/change/{Id}"}, + "GetCheckerIpRanges": {Verb: "Get", Resource: "CheckerIpRange", OutputListKey: "CheckerIpRanges", OutputItemKey: "", Method: "GET", URI: "/2013-04-01/checkeripranges"}, + "GetDNSSEC": {Verb: "Get", Resource: "DNSSEC", OutputListKey: "KeySigningKeys", OutputItemKey: "Status", Method: "GET", URI: "/2013-04-01/hostedzone/{HostedZoneId}/dnssec"}, + "GetGeoLocation": {Verb: "Get", Resource: "GeoLocation", OutputListKey: "", OutputItemKey: "GeoLocationDetails", Method: "GET", URI: "/2013-04-01/geolocation"}, + "GetHealthCheck": {Verb: "Get", Resource: "HealthCheck", OutputListKey: "", OutputItemKey: "HealthCheck", Method: "GET", URI: "/2013-04-01/healthcheck/{HealthCheckId}"}, + "GetHealthCheckCount": {Verb: "Get", Resource: "HealthCheckCount", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/2013-04-01/healthcheckcount"}, + "GetHealthCheckLastFailureReason": {Verb: "Get", Resource: "HealthCheckLastFailureReason", OutputListKey: "HealthCheckObservations", OutputItemKey: "", Method: "GET", URI: "/2013-04-01/healthcheck/{HealthCheckId}/lastfailurereason"}, + "GetHealthCheckStatus": {Verb: "Get", Resource: "HealthCheckStatu", OutputListKey: "HealthCheckObservations", OutputItemKey: "", Method: "GET", URI: "/2013-04-01/healthcheck/{HealthCheckId}/status"}, + "GetHostedZone": {Verb: "Get", Resource: "HostedZone", OutputListKey: "VPCs", OutputItemKey: "DelegationSet", Method: "GET", URI: "/2013-04-01/hostedzone/{Id}"}, + "GetHostedZoneCount": {Verb: "Get", Resource: "HostedZoneCount", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/2013-04-01/hostedzonecount"}, + "GetHostedZoneLimit": {Verb: "Get", Resource: "HostedZoneLimit", OutputListKey: "", OutputItemKey: "Limit", Method: "GET", URI: "/2013-04-01/hostedzonelimit/{HostedZoneId}/{Type}"}, + "GetQueryLoggingConfig": {Verb: "Get", Resource: "QueryLoggingConfig", OutputListKey: "", OutputItemKey: "QueryLoggingConfig", Method: "GET", URI: "/2013-04-01/queryloggingconfig/{Id}"}, + "GetReusableDelegationSet": {Verb: "Get", Resource: "ReusableDelegationSet", OutputListKey: "", OutputItemKey: "DelegationSet", Method: "GET", URI: "/2013-04-01/delegationset/{Id}"}, + "GetReusableDelegationSetLimit": {Verb: "Get", Resource: "ReusableDelegationSetLimit", OutputListKey: "", OutputItemKey: "Limit", Method: "GET", URI: "/2013-04-01/reusabledelegationsetlimit/{DelegationSetId}/{Type}"}, + "GetTrafficPolicy": {Verb: "Get", Resource: "TrafficPolicy", OutputListKey: "", OutputItemKey: "TrafficPolicy", Method: "GET", URI: "/2013-04-01/trafficpolicy/{Id}/{Version}"}, + "GetTrafficPolicyInstance": {Verb: "Get", Resource: "TrafficPolicyInstance", OutputListKey: "", OutputItemKey: "TrafficPolicyInstance", Method: "GET", URI: "/2013-04-01/trafficpolicyinstance/{Id}"}, + "GetTrafficPolicyInstanceCount": {Verb: "Get", Resource: "TrafficPolicyInstanceCount", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/2013-04-01/trafficpolicyinstancecount"}, + "ListCidrBlocks": {Verb: "List", Resource: "CidrBlock", OutputListKey: "CidrBlocks", OutputItemKey: "", Method: "GET", URI: "/2013-04-01/cidrcollection/{CollectionId}/cidrblocks"}, + "ListCidrCollections": {Verb: "List", Resource: "CidrCollection", OutputListKey: "CidrCollections", OutputItemKey: "", Method: "GET", URI: "/2013-04-01/cidrcollection"}, + "ListCidrLocations": {Verb: "List", Resource: "CidrLocation", OutputListKey: "CidrLocations", OutputItemKey: "", Method: "GET", URI: "/2013-04-01/cidrcollection/{CollectionId}"}, + "ListGeoLocations": {Verb: "List", Resource: "GeoLocation", OutputListKey: "GeoLocationDetailsList", OutputItemKey: "", Method: "GET", URI: "/2013-04-01/geolocations"}, + "ListHealthChecks": {Verb: "List", Resource: "HealthCheck", OutputListKey: "HealthChecks", OutputItemKey: "", Method: "GET", URI: "/2013-04-01/healthcheck"}, + "ListHostedZones": {Verb: "List", Resource: "HostedZone", OutputListKey: "HostedZones", OutputItemKey: "", Method: "GET", URI: "/2013-04-01/hostedzone"}, + "ListHostedZonesByName": {Verb: "List", Resource: "HostedZonesByName", OutputListKey: "HostedZones", OutputItemKey: "", Method: "GET", URI: "/2013-04-01/hostedzonesbyname"}, + "ListHostedZonesByVPC": {Verb: "List", Resource: "HostedZonesByVPC", OutputListKey: "HostedZoneSummaries", OutputItemKey: "", Method: "GET", URI: "/2013-04-01/hostedzonesbyvpc"}, + "ListQueryLoggingConfigs": {Verb: "List", Resource: "QueryLoggingConfig", OutputListKey: "QueryLoggingConfigs", OutputItemKey: "", Method: "GET", URI: "/2013-04-01/queryloggingconfig"}, + "ListResourceRecordSets": {Verb: "List", Resource: "ResourceRecordSet", OutputListKey: "ResourceRecordSets", OutputItemKey: "", Method: "GET", URI: "/2013-04-01/hostedzone/{HostedZoneId}/rrset"}, + "ListReusableDelegationSets": {Verb: "List", Resource: "ReusableDelegationSet", OutputListKey: "DelegationSets", OutputItemKey: "", Method: "GET", URI: "/2013-04-01/delegationset"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "", OutputItemKey: "ResourceTagSet", Method: "GET", URI: "/2013-04-01/tags/{ResourceType}/{ResourceId}"}, + "ListTagsForResources": {Verb: "List", Resource: "TagsForResource", OutputListKey: "ResourceTagSets", OutputItemKey: "", Method: "POST", URI: "/2013-04-01/tags/{ResourceType}"}, + "ListTrafficPolicies": {Verb: "List", Resource: "TrafficPolicy", OutputListKey: "TrafficPolicySummaries", OutputItemKey: "", Method: "GET", URI: "/2013-04-01/trafficpolicies"}, + "ListTrafficPolicyInstances": {Verb: "List", Resource: "TrafficPolicyInstance", OutputListKey: "TrafficPolicyInstances", OutputItemKey: "", Method: "GET", URI: "/2013-04-01/trafficpolicyinstances"}, + "ListTrafficPolicyInstancesByHostedZone": {Verb: "List", Resource: "TrafficPolicyInstancesByHostedZone", OutputListKey: "TrafficPolicyInstances", OutputItemKey: "", Method: "GET", URI: "/2013-04-01/trafficpolicyinstances/hostedzone"}, + "ListTrafficPolicyInstancesByPolicy": {Verb: "List", Resource: "TrafficPolicyInstancesByPolicy", OutputListKey: "TrafficPolicyInstances", OutputItemKey: "", Method: "GET", URI: "/2013-04-01/trafficpolicyinstances/trafficpolicy"}, + "ListTrafficPolicyVersions": {Verb: "List", Resource: "TrafficPolicyVersion", OutputListKey: "TrafficPolicies", OutputItemKey: "", Method: "GET", URI: "/2013-04-01/trafficpolicies/{Id}/versions"}, + "ListVPCAssociationAuthorizations": {Verb: "List", Resource: "VPCAssociationAuthorization", OutputListKey: "VPCs", OutputItemKey: "", Method: "GET", URI: "/2013-04-01/hostedzone/{HostedZoneId}/authorizevpcassociation"}, + "UpdateHealthCheck": {Verb: "Update", Resource: "HealthCheck", OutputListKey: "", OutputItemKey: "HealthCheck", Method: "POST", URI: "/2013-04-01/healthcheck/{HealthCheckId}"}, + "UpdateHostedZoneComment": {Verb: "Update", Resource: "HostedZoneComment", OutputListKey: "", OutputItemKey: "HostedZone", Method: "POST", URI: "/2013-04-01/hostedzone/{Id}"}, + "UpdateHostedZoneFeatures": {Verb: "Update", Resource: "HostedZoneFeature", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/2013-04-01/hostedzone/{HostedZoneId}/features"}, + "UpdateTrafficPolicyComment": {Verb: "Update", Resource: "TrafficPolicyComment", OutputListKey: "", OutputItemKey: "TrafficPolicy", Method: "POST", URI: "/2013-04-01/trafficpolicy/{Id}/{Version}"}, + "UpdateTrafficPolicyInstance": {Verb: "Update", Resource: "TrafficPolicyInstance", OutputListKey: "", OutputItemKey: "TrafficPolicyInstance", Method: "POST", URI: "/2013-04-01/trafficpolicyinstance/{Id}"}, + }) crud.Register("route53domains", map[string]crud.OpMeta{ "DeleteDomain": {Verb: "Delete", Resource: "Domain", OutputListKey: "", OutputItemKey: ""}, "DeleteTagsForDomain": {Verb: "Delete", Resource: "TagsForDomain", OutputListKey: "", OutputItemKey: ""}, @@ -6506,6 +6727,200 @@ func init() { "UpdateResolverEndpoint": {Verb: "Update", Resource: "ResolverEndpoint", OutputListKey: "", OutputItemKey: "ResolverEndpoint"}, "UpdateResolverRule": {Verb: "Update", Resource: "ResolverRule", OutputListKey: "", OutputItemKey: "ResolverRule"}, }) + crud.Register("s3", map[string]crud.OpMeta{ + "CreateBucket": {Verb: "Create", Resource: "Bucket", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}"}, + "CreateBucketMetadataConfiguration": {Verb: "Create", Resource: "BucketMetadataConfiguration", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/{Bucket}?metadataConfiguration"}, + "CreateBucketMetadataTableConfiguration": {Verb: "Create", Resource: "BucketMetadataTableConfiguration", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/{Bucket}?metadataTable"}, + "CreateMultipartUpload": {Verb: "Create", Resource: "MultipartUpload", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/{Bucket}/{Key+}?uploads"}, + "CreateSession": {Verb: "Create", Resource: "Session", OutputListKey: "", OutputItemKey: "Credentials", Method: "GET", URI: "/{Bucket}?session"}, + "DeleteBucket": {Verb: "Delete", Resource: "Bucket", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/{Bucket}"}, + "DeleteBucketAnalyticsConfiguration": {Verb: "Delete", Resource: "BucketAnalyticsConfiguration", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/{Bucket}?analytics"}, + "DeleteBucketCors": {Verb: "Delete", Resource: "BucketCor", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/{Bucket}?cors"}, + "DeleteBucketEncryption": {Verb: "Delete", Resource: "BucketEncryption", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/{Bucket}?encryption"}, + "DeleteBucketIntelligentTieringConfiguration": {Verb: "Delete", Resource: "BucketIntelligentTieringConfiguration", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/{Bucket}?intelligent-tiering"}, + "DeleteBucketInventoryConfiguration": {Verb: "Delete", Resource: "BucketInventoryConfiguration", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/{Bucket}?inventory"}, + "DeleteBucketLifecycle": {Verb: "Delete", Resource: "BucketLifecycle", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/{Bucket}?lifecycle"}, + "DeleteBucketMetadataConfiguration": {Verb: "Delete", Resource: "BucketMetadataConfiguration", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/{Bucket}?metadataConfiguration"}, + "DeleteBucketMetadataTableConfiguration": {Verb: "Delete", Resource: "BucketMetadataTableConfiguration", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/{Bucket}?metadataTable"}, + "DeleteBucketMetricsConfiguration": {Verb: "Delete", Resource: "BucketMetricsConfiguration", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/{Bucket}?metrics"}, + "DeleteBucketOwnershipControls": {Verb: "Delete", Resource: "BucketOwnershipControl", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/{Bucket}?ownershipControls"}, + "DeleteBucketPolicy": {Verb: "Delete", Resource: "BucketPolicy", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/{Bucket}?policy"}, + "DeleteBucketReplication": {Verb: "Delete", Resource: "BucketReplication", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/{Bucket}?replication"}, + "DeleteBucketTagging": {Verb: "Delete", Resource: "BucketTagging", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/{Bucket}?tagging"}, + "DeleteBucketWebsite": {Verb: "Delete", Resource: "BucketWebsite", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/{Bucket}?website"}, + "DeleteObject": {Verb: "Delete", Resource: "Object", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/{Bucket}/{Key+}?x-id=DeleteObject"}, + "DeleteObjectTagging": {Verb: "Delete", Resource: "ObjectTagging", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/{Bucket}/{Key+}?tagging"}, + "DeleteObjects": {Verb: "Delete", Resource: "Object", OutputListKey: "Deleted", OutputItemKey: "", Method: "POST", URI: "/{Bucket}?delete"}, + "DeletePublicAccessBlock": {Verb: "Delete", Resource: "PublicAccessBlock", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/{Bucket}?publicAccessBlock"}, + "GetBucketAbac": {Verb: "Get", Resource: "BucketAbac", OutputListKey: "", OutputItemKey: "AbacStatus", Method: "GET", URI: "/{Bucket}?abac"}, + "GetBucketAccelerateConfiguration": {Verb: "Get", Resource: "BucketAccelerateConfiguration", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/{Bucket}?accelerate"}, + "GetBucketAcl": {Verb: "Get", Resource: "BucketAcl", OutputListKey: "Grants", OutputItemKey: "Owner", Method: "GET", URI: "/{Bucket}?acl"}, + "GetBucketAnalyticsConfiguration": {Verb: "Get", Resource: "BucketAnalyticsConfiguration", OutputListKey: "", OutputItemKey: "AnalyticsConfiguration", Method: "GET", URI: "/{Bucket}?analytics&x-id=GetBucketAnalyticsConfiguration"}, + "GetBucketCors": {Verb: "Get", Resource: "BucketCor", OutputListKey: "CORSRules", OutputItemKey: "", Method: "GET", URI: "/{Bucket}?cors"}, + "GetBucketEncryption": {Verb: "Get", Resource: "BucketEncryption", OutputListKey: "", OutputItemKey: "ServerSideEncryptionConfiguration", Method: "GET", URI: "/{Bucket}?encryption"}, + "GetBucketIntelligentTieringConfiguration": {Verb: "Get", Resource: "BucketIntelligentTieringConfiguration", OutputListKey: "", OutputItemKey: "IntelligentTieringConfiguration", Method: "GET", URI: "/{Bucket}?intelligent-tiering&x-id=GetBucketIntelligentTieringConfiguration"}, + "GetBucketInventoryConfiguration": {Verb: "Get", Resource: "BucketInventoryConfiguration", OutputListKey: "", OutputItemKey: "InventoryConfiguration", Method: "GET", URI: "/{Bucket}?inventory&x-id=GetBucketInventoryConfiguration"}, + "GetBucketLifecycleConfiguration": {Verb: "Get", Resource: "BucketLifecycleConfiguration", OutputListKey: "Rules", OutputItemKey: "", Method: "GET", URI: "/{Bucket}?lifecycle"}, + "GetBucketLocation": {Verb: "Get", Resource: "BucketLocation", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/{Bucket}?location"}, + "GetBucketLogging": {Verb: "Get", Resource: "BucketLogging", OutputListKey: "", OutputItemKey: "LoggingEnabled", Method: "GET", URI: "/{Bucket}?logging"}, + "GetBucketMetadataConfiguration": {Verb: "Get", Resource: "BucketMetadataConfiguration", OutputListKey: "", OutputItemKey: "GetBucketMetadataConfigurationResult", Method: "GET", URI: "/{Bucket}?metadataConfiguration"}, + "GetBucketMetadataTableConfiguration": {Verb: "Get", Resource: "BucketMetadataTableConfiguration", OutputListKey: "", OutputItemKey: "GetBucketMetadataTableConfigurationResult", Method: "GET", URI: "/{Bucket}?metadataTable"}, + "GetBucketMetricsConfiguration": {Verb: "Get", Resource: "BucketMetricsConfiguration", OutputListKey: "", OutputItemKey: "MetricsConfiguration", Method: "GET", URI: "/{Bucket}?metrics&x-id=GetBucketMetricsConfiguration"}, + "GetBucketNotificationConfiguration": {Verb: "Get", Resource: "BucketNotificationConfiguration", OutputListKey: "LambdaFunctionConfigurations", OutputItemKey: "EventBridgeConfiguration", Method: "GET", URI: "/{Bucket}?notification"}, + "GetBucketOwnershipControls": {Verb: "Get", Resource: "BucketOwnershipControl", OutputListKey: "", OutputItemKey: "OwnershipControls", Method: "GET", URI: "/{Bucket}?ownershipControls"}, + "GetBucketPolicy": {Verb: "Get", Resource: "BucketPolicy", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/{Bucket}?policy"}, + "GetBucketPolicyStatus": {Verb: "Get", Resource: "BucketPolicyStatu", OutputListKey: "", OutputItemKey: "PolicyStatus", Method: "GET", URI: "/{Bucket}?policyStatus"}, + "GetBucketReplication": {Verb: "Get", Resource: "BucketReplication", OutputListKey: "", OutputItemKey: "ReplicationConfiguration", Method: "GET", URI: "/{Bucket}?replication"}, + "GetBucketRequestPayment": {Verb: "Get", Resource: "BucketRequestPayment", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/{Bucket}?requestPayment"}, + "GetBucketTagging": {Verb: "Get", Resource: "BucketTagging", OutputListKey: "TagSet", OutputItemKey: "", Method: "GET", URI: "/{Bucket}?tagging"}, + "GetBucketVersioning": {Verb: "Get", Resource: "BucketVersioning", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/{Bucket}?versioning"}, + "GetBucketWebsite": {Verb: "Get", Resource: "BucketWebsite", OutputListKey: "RoutingRules", OutputItemKey: "ErrorDocument", Method: "GET", URI: "/{Bucket}?website"}, + "GetObject": {Verb: "Get", Resource: "Object", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/{Bucket}/{Key+}?x-id=GetObject"}, + "GetObjectAcl": {Verb: "Get", Resource: "ObjectAcl", OutputListKey: "Grants", OutputItemKey: "Owner", Method: "GET", URI: "/{Bucket}/{Key+}?acl"}, + "GetObjectAttributes": {Verb: "Get", Resource: "ObjectAttribute", OutputListKey: "", OutputItemKey: "Checksum", Method: "GET", URI: "/{Bucket}/{Key+}?attributes"}, + "GetObjectLegalHold": {Verb: "Get", Resource: "ObjectLegalHold", OutputListKey: "", OutputItemKey: "LegalHold", Method: "GET", URI: "/{Bucket}/{Key+}?legal-hold"}, + "GetObjectLockConfiguration": {Verb: "Get", Resource: "ObjectLockConfiguration", OutputListKey: "", OutputItemKey: "ObjectLockConfiguration", Method: "GET", URI: "/{Bucket}?object-lock"}, + "GetObjectRetention": {Verb: "Get", Resource: "ObjectRetention", OutputListKey: "", OutputItemKey: "Retention", Method: "GET", URI: "/{Bucket}/{Key+}?retention"}, + "GetObjectTagging": {Verb: "Get", Resource: "ObjectTagging", OutputListKey: "TagSet", OutputItemKey: "", Method: "GET", URI: "/{Bucket}/{Key+}?tagging"}, + "GetObjectTorrent": {Verb: "Get", Resource: "ObjectTorrent", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/{Bucket}/{Key+}?torrent"}, + "GetPublicAccessBlock": {Verb: "Get", Resource: "PublicAccessBlock", OutputListKey: "", OutputItemKey: "PublicAccessBlockConfiguration", Method: "GET", URI: "/{Bucket}?publicAccessBlock"}, + "ListBucketAnalyticsConfigurations": {Verb: "List", Resource: "BucketAnalyticsConfiguration", OutputListKey: "AnalyticsConfigurationList", OutputItemKey: "", Method: "GET", URI: "/{Bucket}?analytics&x-id=ListBucketAnalyticsConfigurations"}, + "ListBucketIntelligentTieringConfigurations": {Verb: "List", Resource: "BucketIntelligentTieringConfiguration", OutputListKey: "IntelligentTieringConfigurationList", OutputItemKey: "", Method: "GET", URI: "/{Bucket}?intelligent-tiering&x-id=ListBucketIntelligentTieringConfigurations"}, + "ListBucketInventoryConfigurations": {Verb: "List", Resource: "BucketInventoryConfiguration", OutputListKey: "InventoryConfigurationList", OutputItemKey: "", Method: "GET", URI: "/{Bucket}?inventory&x-id=ListBucketInventoryConfigurations"}, + "ListBucketMetricsConfigurations": {Verb: "List", Resource: "BucketMetricsConfiguration", OutputListKey: "MetricsConfigurationList", OutputItemKey: "", Method: "GET", URI: "/{Bucket}?metrics&x-id=ListBucketMetricsConfigurations"}, + "ListBuckets": {Verb: "List", Resource: "Bucket", OutputListKey: "Buckets", OutputItemKey: "Owner", Method: "GET", URI: "/?x-id=ListBuckets"}, + "ListDirectoryBuckets": {Verb: "List", Resource: "DirectoryBucket", OutputListKey: "Buckets", OutputItemKey: "", Method: "GET", URI: "/?x-id=ListDirectoryBuckets"}, + "ListMultipartUploads": {Verb: "List", Resource: "MultipartUpload", OutputListKey: "CommonPrefixes", OutputItemKey: "", Method: "GET", URI: "/{Bucket}?uploads"}, + "ListObjectVersions": {Verb: "List", Resource: "ObjectVersion", OutputListKey: "CommonPrefixes", OutputItemKey: "", Method: "GET", URI: "/{Bucket}?versions"}, + "ListObjects": {Verb: "List", Resource: "Object", OutputListKey: "CommonPrefixes", OutputItemKey: "", Method: "GET", URI: "/{Bucket}"}, + "ListObjectsV2": {Verb: "List", Resource: "ObjectsV2", OutputListKey: "CommonPrefixes", OutputItemKey: "", Method: "GET", URI: "/{Bucket}?list-type=2"}, + "ListParts": {Verb: "List", Resource: "Part", OutputListKey: "Parts", OutputItemKey: "Initiator", Method: "GET", URI: "/{Bucket}/{Key+}?x-id=ListParts"}, + "PutBucketAbac": {Verb: "Update", Resource: "BucketAbac", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}?abac"}, + "PutBucketAccelerateConfiguration": {Verb: "Update", Resource: "BucketAccelerateConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}?accelerate"}, + "PutBucketAcl": {Verb: "Update", Resource: "BucketAcl", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}?acl"}, + "PutBucketAnalyticsConfiguration": {Verb: "Update", Resource: "BucketAnalyticsConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}?analytics"}, + "PutBucketCors": {Verb: "Update", Resource: "BucketCor", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}?cors"}, + "PutBucketEncryption": {Verb: "Update", Resource: "BucketEncryption", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}?encryption"}, + "PutBucketIntelligentTieringConfiguration": {Verb: "Update", Resource: "BucketIntelligentTieringConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}?intelligent-tiering"}, + "PutBucketInventoryConfiguration": {Verb: "Update", Resource: "BucketInventoryConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}?inventory"}, + "PutBucketLifecycleConfiguration": {Verb: "Update", Resource: "BucketLifecycleConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}?lifecycle"}, + "PutBucketLogging": {Verb: "Update", Resource: "BucketLogging", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}?logging"}, + "PutBucketMetricsConfiguration": {Verb: "Update", Resource: "BucketMetricsConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}?metrics"}, + "PutBucketNotificationConfiguration": {Verb: "Update", Resource: "BucketNotificationConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}?notification"}, + "PutBucketOwnershipControls": {Verb: "Update", Resource: "BucketOwnershipControl", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}?ownershipControls"}, + "PutBucketPolicy": {Verb: "Update", Resource: "BucketPolicy", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}?policy"}, + "PutBucketReplication": {Verb: "Update", Resource: "BucketReplication", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}?replication"}, + "PutBucketRequestPayment": {Verb: "Update", Resource: "BucketRequestPayment", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}?requestPayment"}, + "PutBucketTagging": {Verb: "Update", Resource: "BucketTagging", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}?tagging"}, + "PutBucketVersioning": {Verb: "Update", Resource: "BucketVersioning", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}?versioning"}, + "PutBucketWebsite": {Verb: "Update", Resource: "BucketWebsite", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}?website"}, + "PutObject": {Verb: "Update", Resource: "Object", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}/{Key+}?x-id=PutObject"}, + "PutObjectAcl": {Verb: "Update", Resource: "ObjectAcl", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}/{Key+}?acl"}, + "PutObjectLegalHold": {Verb: "Update", Resource: "ObjectLegalHold", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}/{Key+}?legal-hold"}, + "PutObjectLockConfiguration": {Verb: "Update", Resource: "ObjectLockConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}?object-lock"}, + "PutObjectRetention": {Verb: "Update", Resource: "ObjectRetention", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}/{Key+}?retention"}, + "PutObjectTagging": {Verb: "Update", Resource: "ObjectTagging", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}/{Key+}?tagging"}, + "PutPublicAccessBlock": {Verb: "Update", Resource: "PublicAccessBlock", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}?publicAccessBlock"}, + "UpdateBucketMetadataInventoryTableConfiguration": {Verb: "Update", Resource: "BucketMetadataInventoryTableConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}?metadataInventoryTable"}, + "UpdateBucketMetadataJournalTableConfiguration": {Verb: "Update", Resource: "BucketMetadataJournalTableConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}?metadataJournalTable"}, + "UpdateObjectEncryption": {Verb: "Update", Resource: "ObjectEncryption", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/{Bucket}/{Key+}?encryption"}, + }) + crud.Register("s3control", map[string]crud.OpMeta{ + "CreateAccessGrant": {Verb: "Create", Resource: "AccessGrant", OutputListKey: "", OutputItemKey: "AccessGrantsLocationConfiguration", Method: "POST", URI: "/v20180820/accessgrantsinstance/grant"}, + "CreateAccessGrantsInstance": {Verb: "Create", Resource: "AccessGrantsInstance", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v20180820/accessgrantsinstance"}, + "CreateAccessGrantsLocation": {Verb: "Create", Resource: "AccessGrantsLocation", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v20180820/accessgrantsinstance/location"}, + "CreateAccessPoint": {Verb: "Create", Resource: "AccessPoint", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v20180820/accesspoint/{Name}"}, + "CreateAccessPointForObjectLambda": {Verb: "Create", Resource: "AccessPointForObjectLambda", OutputListKey: "", OutputItemKey: "Alias", Method: "PUT", URI: "/v20180820/accesspointforobjectlambda/{Name}"}, + "CreateBucket": {Verb: "Create", Resource: "Bucket", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v20180820/bucket/{Bucket}"}, + "CreateJob": {Verb: "Create", Resource: "Job", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v20180820/jobs"}, + "CreateMultiRegionAccessPoint": {Verb: "Create", Resource: "MultiRegionAccessPoint", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v20180820/async-requests/mrap/create"}, + "CreateStorageLensGroup": {Verb: "Create", Resource: "StorageLensGroup", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v20180820/storagelensgroup"}, + "DeleteAccessGrant": {Verb: "Delete", Resource: "AccessGrant", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v20180820/accessgrantsinstance/grant/{AccessGrantId}"}, + "DeleteAccessGrantsInstance": {Verb: "Delete", Resource: "AccessGrantsInstance", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v20180820/accessgrantsinstance"}, + "DeleteAccessGrantsInstanceResourcePolicy": {Verb: "Delete", Resource: "AccessGrantsInstanceResourcePolicy", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v20180820/accessgrantsinstance/resourcepolicy"}, + "DeleteAccessGrantsLocation": {Verb: "Delete", Resource: "AccessGrantsLocation", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v20180820/accessgrantsinstance/location/{AccessGrantsLocationId}"}, + "DeleteAccessPoint": {Verb: "Delete", Resource: "AccessPoint", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v20180820/accesspoint/{Name}"}, + "DeleteAccessPointForObjectLambda": {Verb: "Delete", Resource: "AccessPointForObjectLambda", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v20180820/accesspointforobjectlambda/{Name}"}, + "DeleteAccessPointPolicy": {Verb: "Delete", Resource: "AccessPointPolicy", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v20180820/accesspoint/{Name}/policy"}, + "DeleteAccessPointPolicyForObjectLambda": {Verb: "Delete", Resource: "AccessPointPolicyForObjectLambda", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v20180820/accesspointforobjectlambda/{Name}/policy"}, + "DeleteAccessPointScope": {Verb: "Delete", Resource: "AccessPointScope", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v20180820/accesspoint/{Name}/scope"}, + "DeleteBucket": {Verb: "Delete", Resource: "Bucket", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v20180820/bucket/{Bucket}"}, + "DeleteBucketLifecycleConfiguration": {Verb: "Delete", Resource: "BucketLifecycleConfiguration", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v20180820/bucket/{Bucket}/lifecycleconfiguration"}, + "DeleteBucketPolicy": {Verb: "Delete", Resource: "BucketPolicy", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v20180820/bucket/{Bucket}/policy"}, + "DeleteBucketReplication": {Verb: "Delete", Resource: "BucketReplication", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v20180820/bucket/{Bucket}/replication"}, + "DeleteBucketTagging": {Verb: "Delete", Resource: "BucketTagging", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v20180820/bucket/{Bucket}/tagging"}, + "DeleteJobTagging": {Verb: "Delete", Resource: "JobTagging", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v20180820/jobs/{JobId}/tagging"}, + "DeleteMultiRegionAccessPoint": {Verb: "Delete", Resource: "MultiRegionAccessPoint", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v20180820/async-requests/mrap/delete"}, + "DeletePublicAccessBlock": {Verb: "Delete", Resource: "PublicAccessBlock", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v20180820/configuration/publicAccessBlock"}, + "DeleteStorageLensConfiguration": {Verb: "Delete", Resource: "StorageLensConfiguration", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v20180820/storagelens/{ConfigId}"}, + "DeleteStorageLensConfigurationTagging": {Verb: "Delete", Resource: "StorageLensConfigurationTagging", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v20180820/storagelens/{ConfigId}/tagging"}, + "DeleteStorageLensGroup": {Verb: "Delete", Resource: "StorageLensGroup", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v20180820/storagelensgroup/{Name}"}, + "DescribeJob": {Verb: "Get", Resource: "Job", OutputListKey: "", OutputItemKey: "Job", Method: "GET", URI: "/v20180820/jobs/{JobId}"}, + "DescribeMultiRegionAccessPointOperation": {Verb: "Get", Resource: "MultiRegionAccessPointOperation", OutputListKey: "", OutputItemKey: "AsyncOperation", Method: "GET", URI: "/v20180820/async-requests/mrap/{RequestTokenARN+}"}, + "GetAccessGrant": {Verb: "Get", Resource: "AccessGrant", OutputListKey: "", OutputItemKey: "AccessGrantsLocationConfiguration", Method: "GET", URI: "/v20180820/accessgrantsinstance/grant/{AccessGrantId}"}, + "GetAccessGrantsInstance": {Verb: "Get", Resource: "AccessGrantsInstance", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v20180820/accessgrantsinstance"}, + "GetAccessGrantsInstanceForPrefix": {Verb: "Get", Resource: "AccessGrantsInstanceForPrefix", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v20180820/accessgrantsinstance/prefix"}, + "GetAccessGrantsInstanceResourcePolicy": {Verb: "Get", Resource: "AccessGrantsInstanceResourcePolicy", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v20180820/accessgrantsinstance/resourcepolicy"}, + "GetAccessGrantsLocation": {Verb: "Get", Resource: "AccessGrantsLocation", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v20180820/accessgrantsinstance/location/{AccessGrantsLocationId}"}, + "GetAccessPoint": {Verb: "Get", Resource: "AccessPoint", OutputListKey: "", OutputItemKey: "PublicAccessBlockConfiguration", Method: "GET", URI: "/v20180820/accesspoint/{Name}"}, + "GetAccessPointConfigurationForObjectLambda": {Verb: "Get", Resource: "AccessPointConfigurationForObjectLambda", OutputListKey: "", OutputItemKey: "Configuration", Method: "GET", URI: "/v20180820/accesspointforobjectlambda/{Name}/configuration"}, + "GetAccessPointForObjectLambda": {Verb: "Get", Resource: "AccessPointForObjectLambda", OutputListKey: "", OutputItemKey: "Alias", Method: "GET", URI: "/v20180820/accesspointforobjectlambda/{Name}"}, + "GetAccessPointPolicy": {Verb: "Get", Resource: "AccessPointPolicy", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v20180820/accesspoint/{Name}/policy"}, + "GetAccessPointPolicyForObjectLambda": {Verb: "Get", Resource: "AccessPointPolicyForObjectLambda", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v20180820/accesspointforobjectlambda/{Name}/policy"}, + "GetAccessPointPolicyStatus": {Verb: "Get", Resource: "AccessPointPolicyStatu", OutputListKey: "", OutputItemKey: "PolicyStatus", Method: "GET", URI: "/v20180820/accesspoint/{Name}/policyStatus"}, + "GetAccessPointPolicyStatusForObjectLambda": {Verb: "Get", Resource: "AccessPointPolicyStatusForObjectLambda", OutputListKey: "", OutputItemKey: "PolicyStatus", Method: "GET", URI: "/v20180820/accesspointforobjectlambda/{Name}/policyStatus"}, + "GetAccessPointScope": {Verb: "Get", Resource: "AccessPointScope", OutputListKey: "", OutputItemKey: "Scope", Method: "GET", URI: "/v20180820/accesspoint/{Name}/scope"}, + "GetBucket": {Verb: "Get", Resource: "Bucket", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v20180820/bucket/{Bucket}"}, + "GetBucketLifecycleConfiguration": {Verb: "Get", Resource: "BucketLifecycleConfiguration", OutputListKey: "Rules", OutputItemKey: "", Method: "GET", URI: "/v20180820/bucket/{Bucket}/lifecycleconfiguration"}, + "GetBucketPolicy": {Verb: "Get", Resource: "BucketPolicy", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v20180820/bucket/{Bucket}/policy"}, + "GetBucketReplication": {Verb: "Get", Resource: "BucketReplication", OutputListKey: "", OutputItemKey: "ReplicationConfiguration", Method: "GET", URI: "/v20180820/bucket/{Bucket}/replication"}, + "GetBucketTagging": {Verb: "Get", Resource: "BucketTagging", OutputListKey: "TagSet", OutputItemKey: "", Method: "GET", URI: "/v20180820/bucket/{Bucket}/tagging"}, + "GetBucketVersioning": {Verb: "Get", Resource: "BucketVersioning", OutputListKey: "", OutputItemKey: "", Method: "GET", URI: "/v20180820/bucket/{Bucket}/versioning"}, + "GetDataAccess": {Verb: "Get", Resource: "DataAccess", OutputListKey: "", OutputItemKey: "Credentials", Method: "GET", URI: "/v20180820/accessgrantsinstance/dataaccess"}, + "GetJobTagging": {Verb: "Get", Resource: "JobTagging", OutputListKey: "Tags", OutputItemKey: "", Method: "GET", URI: "/v20180820/jobs/{JobId}/tagging"}, + "GetMultiRegionAccessPoint": {Verb: "Get", Resource: "MultiRegionAccessPoint", OutputListKey: "", OutputItemKey: "AccessPoint", Method: "GET", URI: "/v20180820/mrap/instances/{Name+}"}, + "GetMultiRegionAccessPointPolicy": {Verb: "Get", Resource: "MultiRegionAccessPointPolicy", OutputListKey: "", OutputItemKey: "Policy", Method: "GET", URI: "/v20180820/mrap/instances/{Name+}/policy"}, + "GetMultiRegionAccessPointPolicyStatus": {Verb: "Get", Resource: "MultiRegionAccessPointPolicyStatu", OutputListKey: "", OutputItemKey: "Established", Method: "GET", URI: "/v20180820/mrap/instances/{Name+}/policystatus"}, + "GetMultiRegionAccessPointRoutes": {Verb: "Get", Resource: "MultiRegionAccessPointRoute", OutputListKey: "Routes", OutputItemKey: "", Method: "GET", URI: "/v20180820/mrap/instances/{Mrap+}/routes"}, + "GetPublicAccessBlock": {Verb: "Get", Resource: "PublicAccessBlock", OutputListKey: "", OutputItemKey: "PublicAccessBlockConfiguration", Method: "GET", URI: "/v20180820/configuration/publicAccessBlock"}, + "GetStorageLensConfiguration": {Verb: "Get", Resource: "StorageLensConfiguration", OutputListKey: "", OutputItemKey: "StorageLensConfiguration", Method: "GET", URI: "/v20180820/storagelens/{ConfigId}"}, + "GetStorageLensConfigurationTagging": {Verb: "Get", Resource: "StorageLensConfigurationTagging", OutputListKey: "Tags", OutputItemKey: "", Method: "GET", URI: "/v20180820/storagelens/{ConfigId}/tagging"}, + "GetStorageLensGroup": {Verb: "Get", Resource: "StorageLensGroup", OutputListKey: "", OutputItemKey: "StorageLensGroup", Method: "GET", URI: "/v20180820/storagelensgroup/{Name}"}, + "ListAccessGrants": {Verb: "List", Resource: "AccessGrant", OutputListKey: "AccessGrantsList", OutputItemKey: "", Method: "GET", URI: "/v20180820/accessgrantsinstance/grants"}, + "ListAccessGrantsInstances": {Verb: "List", Resource: "AccessGrantsInstance", OutputListKey: "AccessGrantsInstancesList", OutputItemKey: "", Method: "GET", URI: "/v20180820/accessgrantsinstances"}, + "ListAccessGrantsLocations": {Verb: "List", Resource: "AccessGrantsLocation", OutputListKey: "AccessGrantsLocationsList", OutputItemKey: "", Method: "GET", URI: "/v20180820/accessgrantsinstance/locations"}, + "ListAccessPoints": {Verb: "List", Resource: "AccessPoint", OutputListKey: "AccessPointList", OutputItemKey: "", Method: "GET", URI: "/v20180820/accesspoint"}, + "ListAccessPointsForDirectoryBuckets": {Verb: "List", Resource: "AccessPointsForDirectoryBucket", OutputListKey: "AccessPointList", OutputItemKey: "", Method: "GET", URI: "/v20180820/accesspointfordirectory"}, + "ListAccessPointsForObjectLambda": {Verb: "List", Resource: "AccessPointsForObjectLambda", OutputListKey: "ObjectLambdaAccessPointList", OutputItemKey: "", Method: "GET", URI: "/v20180820/accesspointforobjectlambda"}, + "ListCallerAccessGrants": {Verb: "List", Resource: "CallerAccessGrant", OutputListKey: "CallerAccessGrantsList", OutputItemKey: "", Method: "GET", URI: "/v20180820/accessgrantsinstance/caller/grants"}, + "ListJobs": {Verb: "List", Resource: "Job", OutputListKey: "Jobs", OutputItemKey: "", Method: "GET", URI: "/v20180820/jobs"}, + "ListMultiRegionAccessPoints": {Verb: "List", Resource: "MultiRegionAccessPoint", OutputListKey: "AccessPoints", OutputItemKey: "", Method: "GET", URI: "/v20180820/mrap/instances"}, + "ListRegionalBuckets": {Verb: "List", Resource: "RegionalBucket", OutputListKey: "RegionalBucketList", OutputItemKey: "", Method: "GET", URI: "/v20180820/bucket"}, + "ListStorageLensConfigurations": {Verb: "List", Resource: "StorageLensConfiguration", OutputListKey: "StorageLensConfigurationList", OutputItemKey: "", Method: "GET", URI: "/v20180820/storagelens"}, + "ListStorageLensGroups": {Verb: "List", Resource: "StorageLensGroup", OutputListKey: "StorageLensGroupList", OutputItemKey: "", Method: "GET", URI: "/v20180820/storagelensgroup"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "Tags", OutputItemKey: "", Method: "GET", URI: "/v20180820/tags/{ResourceArn+}"}, + "PutAccessGrantsInstanceResourcePolicy": {Verb: "Update", Resource: "AccessGrantsInstanceResourcePolicy", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v20180820/accessgrantsinstance/resourcepolicy"}, + "PutAccessPointConfigurationForObjectLambda": {Verb: "Update", Resource: "AccessPointConfigurationForObjectLambda", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v20180820/accesspointforobjectlambda/{Name}/configuration"}, + "PutAccessPointPolicy": {Verb: "Update", Resource: "AccessPointPolicy", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v20180820/accesspoint/{Name}/policy"}, + "PutAccessPointPolicyForObjectLambda": {Verb: "Update", Resource: "AccessPointPolicyForObjectLambda", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v20180820/accesspointforobjectlambda/{Name}/policy"}, + "PutAccessPointScope": {Verb: "Update", Resource: "AccessPointScope", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v20180820/accesspoint/{Name}/scope"}, + "PutBucketLifecycleConfiguration": {Verb: "Update", Resource: "BucketLifecycleConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v20180820/bucket/{Bucket}/lifecycleconfiguration"}, + "PutBucketPolicy": {Verb: "Update", Resource: "BucketPolicy", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v20180820/bucket/{Bucket}/policy"}, + "PutBucketReplication": {Verb: "Update", Resource: "BucketReplication", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v20180820/bucket/{Bucket}/replication"}, + "PutBucketTagging": {Verb: "Update", Resource: "BucketTagging", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v20180820/bucket/{Bucket}/tagging"}, + "PutBucketVersioning": {Verb: "Update", Resource: "BucketVersioning", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v20180820/bucket/{Bucket}/versioning"}, + "PutJobTagging": {Verb: "Update", Resource: "JobTagging", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v20180820/jobs/{JobId}/tagging"}, + "PutMultiRegionAccessPointPolicy": {Verb: "Update", Resource: "MultiRegionAccessPointPolicy", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v20180820/async-requests/mrap/put-policy"}, + "PutPublicAccessBlock": {Verb: "Update", Resource: "PublicAccessBlock", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v20180820/configuration/publicAccessBlock"}, + "PutStorageLensConfiguration": {Verb: "Update", Resource: "StorageLensConfiguration", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v20180820/storagelens/{ConfigId}"}, + "PutStorageLensConfigurationTagging": {Verb: "Update", Resource: "StorageLensConfigurationTagging", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v20180820/storagelens/{ConfigId}/tagging"}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v20180820/tags/{ResourceArn+}"}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: "", Method: "DELETE", URI: "/v20180820/tags/{ResourceArn+}"}, + "UpdateAccessGrantsLocation": {Verb: "Update", Resource: "AccessGrantsLocation", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v20180820/accessgrantsinstance/location/{AccessGrantsLocationId}"}, + "UpdateJobPriority": {Verb: "Update", Resource: "JobPriority", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v20180820/jobs/{JobId}/priority"}, + "UpdateJobStatus": {Verb: "Update", Resource: "JobStatu", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/v20180820/jobs/{JobId}/status"}, + "UpdateStorageLensGroup": {Verb: "Update", Resource: "StorageLensGroup", OutputListKey: "", OutputItemKey: "", Method: "PUT", URI: "/v20180820/storagelensgroup/{Name}"}, + }) crud.Register("s3vectors", map[string]crud.OpMeta{ "CreateIndex": {Verb: "Create", Resource: "Index", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/CreateIndex"}, "CreateVectorBucket": {Verb: "Create", Resource: "VectorBucket", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/CreateVectorBucket"}, diff --git a/internal/generated/fidelity/manifest_gen.go b/internal/generated/fidelity/manifest_gen.go index 2d772a95..9dd4a8d6 100644 --- a/internal/generated/fidelity/manifest_gen.go +++ b/internal/generated/fidelity/manifest_gen.go @@ -10403,102 +10403,102 @@ var Services = map[string]Service{ }}, "s3control": {Protocol: "rest-xml", ModelBacked: true, EngineWired: true, Operations: map[string]Tier{ "AssociateAccessGrantsIdentityCenter": TierUnimplemented, - "CreateAccessGrant": TierUnimplemented, - "CreateAccessGrantsInstance": TierUnimplemented, - "CreateAccessGrantsLocation": TierUnimplemented, - "CreateAccessPoint": TierUnimplemented, - "CreateAccessPointForObjectLambda": TierUnimplemented, - "CreateBucket": TierUnimplemented, - "CreateJob": TierUnimplemented, - "CreateMultiRegionAccessPoint": TierUnimplemented, - "CreateStorageLensGroup": TierUnimplemented, - "DeleteAccessGrant": TierUnimplemented, - "DeleteAccessGrantsInstance": TierUnimplemented, - "DeleteAccessGrantsInstanceResourcePolicy": TierUnimplemented, - "DeleteAccessGrantsLocation": TierUnimplemented, - "DeleteAccessPoint": TierUnimplemented, - "DeleteAccessPointForObjectLambda": TierUnimplemented, - "DeleteAccessPointPolicy": TierUnimplemented, - "DeleteAccessPointPolicyForObjectLambda": TierUnimplemented, - "DeleteAccessPointScope": TierUnimplemented, - "DeleteBucket": TierUnimplemented, - "DeleteBucketLifecycleConfiguration": TierUnimplemented, - "DeleteBucketPolicy": TierUnimplemented, - "DeleteBucketReplication": TierUnimplemented, - "DeleteBucketTagging": TierUnimplemented, - "DeleteJobTagging": TierUnimplemented, - "DeleteMultiRegionAccessPoint": TierUnimplemented, - "DeletePublicAccessBlock": TierUnimplemented, - "DeleteStorageLensConfiguration": TierUnimplemented, - "DeleteStorageLensConfigurationTagging": TierUnimplemented, - "DeleteStorageLensGroup": TierUnimplemented, - "DescribeJob": TierUnimplemented, - "DescribeMultiRegionAccessPointOperation": TierUnimplemented, + "CreateAccessGrant": TierAutoCRUD, + "CreateAccessGrantsInstance": TierAutoCRUD, + "CreateAccessGrantsLocation": TierAutoCRUD, + "CreateAccessPoint": TierAutoCRUD, + "CreateAccessPointForObjectLambda": TierAutoCRUD, + "CreateBucket": TierAutoCRUD, + "CreateJob": TierAutoCRUD, + "CreateMultiRegionAccessPoint": TierAutoCRUD, + "CreateStorageLensGroup": TierAutoCRUD, + "DeleteAccessGrant": TierAutoCRUD, + "DeleteAccessGrantsInstance": TierAutoCRUD, + "DeleteAccessGrantsInstanceResourcePolicy": TierAutoCRUD, + "DeleteAccessGrantsLocation": TierAutoCRUD, + "DeleteAccessPoint": TierAutoCRUD, + "DeleteAccessPointForObjectLambda": TierAutoCRUD, + "DeleteAccessPointPolicy": TierAutoCRUD, + "DeleteAccessPointPolicyForObjectLambda": TierAutoCRUD, + "DeleteAccessPointScope": TierAutoCRUD, + "DeleteBucket": TierAutoCRUD, + "DeleteBucketLifecycleConfiguration": TierAutoCRUD, + "DeleteBucketPolicy": TierAutoCRUD, + "DeleteBucketReplication": TierAutoCRUD, + "DeleteBucketTagging": TierAutoCRUD, + "DeleteJobTagging": TierAutoCRUD, + "DeleteMultiRegionAccessPoint": TierAutoCRUD, + "DeletePublicAccessBlock": TierAutoCRUD, + "DeleteStorageLensConfiguration": TierAutoCRUD, + "DeleteStorageLensConfigurationTagging": TierAutoCRUD, + "DeleteStorageLensGroup": TierAutoCRUD, + "DescribeJob": TierAutoCRUD, + "DescribeMultiRegionAccessPointOperation": TierAutoCRUD, "DissociateAccessGrantsIdentityCenter": TierUnimplemented, - "GetAccessGrant": TierUnimplemented, - "GetAccessGrantsInstance": TierUnimplemented, - "GetAccessGrantsInstanceForPrefix": TierUnimplemented, - "GetAccessGrantsInstanceResourcePolicy": TierUnimplemented, - "GetAccessGrantsLocation": TierUnimplemented, - "GetAccessPoint": TierUnimplemented, - "GetAccessPointConfigurationForObjectLambda": TierUnimplemented, - "GetAccessPointForObjectLambda": TierUnimplemented, - "GetAccessPointPolicy": TierUnimplemented, - "GetAccessPointPolicyForObjectLambda": TierUnimplemented, - "GetAccessPointPolicyStatus": TierUnimplemented, - "GetAccessPointPolicyStatusForObjectLambda": TierUnimplemented, - "GetAccessPointScope": TierUnimplemented, - "GetBucket": TierUnimplemented, - "GetBucketLifecycleConfiguration": TierUnimplemented, - "GetBucketPolicy": TierUnimplemented, - "GetBucketReplication": TierUnimplemented, - "GetBucketTagging": TierUnimplemented, - "GetBucketVersioning": TierUnimplemented, - "GetDataAccess": TierUnimplemented, - "GetJobTagging": TierUnimplemented, - "GetMultiRegionAccessPoint": TierUnimplemented, - "GetMultiRegionAccessPointPolicy": TierUnimplemented, - "GetMultiRegionAccessPointPolicyStatus": TierUnimplemented, - "GetMultiRegionAccessPointRoutes": TierUnimplemented, - "GetPublicAccessBlock": TierUnimplemented, - "GetStorageLensConfiguration": TierUnimplemented, - "GetStorageLensConfigurationTagging": TierUnimplemented, - "GetStorageLensGroup": TierUnimplemented, - "ListAccessGrants": TierUnimplemented, - "ListAccessGrantsInstances": TierUnimplemented, - "ListAccessGrantsLocations": TierUnimplemented, - "ListAccessPoints": TierUnimplemented, - "ListAccessPointsForDirectoryBuckets": TierUnimplemented, - "ListAccessPointsForObjectLambda": TierUnimplemented, - "ListCallerAccessGrants": TierUnimplemented, - "ListJobs": TierUnimplemented, - "ListMultiRegionAccessPoints": TierUnimplemented, - "ListRegionalBuckets": TierUnimplemented, - "ListStorageLensConfigurations": TierUnimplemented, - "ListStorageLensGroups": TierUnimplemented, - "ListTagsForResource": TierUnimplemented, - "PutAccessGrantsInstanceResourcePolicy": TierUnimplemented, - "PutAccessPointConfigurationForObjectLambda": TierUnimplemented, - "PutAccessPointPolicy": TierUnimplemented, - "PutAccessPointPolicyForObjectLambda": TierUnimplemented, - "PutAccessPointScope": TierUnimplemented, - "PutBucketLifecycleConfiguration": TierUnimplemented, - "PutBucketPolicy": TierUnimplemented, - "PutBucketReplication": TierUnimplemented, - "PutBucketTagging": TierUnimplemented, - "PutBucketVersioning": TierUnimplemented, - "PutJobTagging": TierUnimplemented, - "PutMultiRegionAccessPointPolicy": TierUnimplemented, - "PutPublicAccessBlock": TierUnimplemented, - "PutStorageLensConfiguration": TierUnimplemented, - "PutStorageLensConfigurationTagging": TierUnimplemented, + "GetAccessGrant": TierAutoCRUD, + "GetAccessGrantsInstance": TierAutoCRUD, + "GetAccessGrantsInstanceForPrefix": TierAutoCRUD, + "GetAccessGrantsInstanceResourcePolicy": TierAutoCRUD, + "GetAccessGrantsLocation": TierAutoCRUD, + "GetAccessPoint": TierAutoCRUD, + "GetAccessPointConfigurationForObjectLambda": TierAutoCRUD, + "GetAccessPointForObjectLambda": TierAutoCRUD, + "GetAccessPointPolicy": TierAutoCRUD, + "GetAccessPointPolicyForObjectLambda": TierAutoCRUD, + "GetAccessPointPolicyStatus": TierAutoCRUD, + "GetAccessPointPolicyStatusForObjectLambda": TierAutoCRUD, + "GetAccessPointScope": TierAutoCRUD, + "GetBucket": TierAutoCRUD, + "GetBucketLifecycleConfiguration": TierAutoCRUD, + "GetBucketPolicy": TierAutoCRUD, + "GetBucketReplication": TierAutoCRUD, + "GetBucketTagging": TierAutoCRUD, + "GetBucketVersioning": TierAutoCRUD, + "GetDataAccess": TierAutoCRUD, + "GetJobTagging": TierAutoCRUD, + "GetMultiRegionAccessPoint": TierAutoCRUD, + "GetMultiRegionAccessPointPolicy": TierAutoCRUD, + "GetMultiRegionAccessPointPolicyStatus": TierAutoCRUD, + "GetMultiRegionAccessPointRoutes": TierAutoCRUD, + "GetPublicAccessBlock": TierAutoCRUD, + "GetStorageLensConfiguration": TierAutoCRUD, + "GetStorageLensConfigurationTagging": TierAutoCRUD, + "GetStorageLensGroup": TierAutoCRUD, + "ListAccessGrants": TierAutoCRUD, + "ListAccessGrantsInstances": TierAutoCRUD, + "ListAccessGrantsLocations": TierAutoCRUD, + "ListAccessPoints": TierAutoCRUD, + "ListAccessPointsForDirectoryBuckets": TierAutoCRUD, + "ListAccessPointsForObjectLambda": TierAutoCRUD, + "ListCallerAccessGrants": TierAutoCRUD, + "ListJobs": TierAutoCRUD, + "ListMultiRegionAccessPoints": TierAutoCRUD, + "ListRegionalBuckets": TierAutoCRUD, + "ListStorageLensConfigurations": TierAutoCRUD, + "ListStorageLensGroups": TierAutoCRUD, + "ListTagsForResource": TierAutoCRUD, + "PutAccessGrantsInstanceResourcePolicy": TierAutoCRUD, + "PutAccessPointConfigurationForObjectLambda": TierAutoCRUD, + "PutAccessPointPolicy": TierAutoCRUD, + "PutAccessPointPolicyForObjectLambda": TierAutoCRUD, + "PutAccessPointScope": TierAutoCRUD, + "PutBucketLifecycleConfiguration": TierAutoCRUD, + "PutBucketPolicy": TierAutoCRUD, + "PutBucketReplication": TierAutoCRUD, + "PutBucketTagging": TierAutoCRUD, + "PutBucketVersioning": TierAutoCRUD, + "PutJobTagging": TierAutoCRUD, + "PutMultiRegionAccessPointPolicy": TierAutoCRUD, + "PutPublicAccessBlock": TierAutoCRUD, + "PutStorageLensConfiguration": TierAutoCRUD, + "PutStorageLensConfigurationTagging": TierAutoCRUD, "SubmitMultiRegionAccessPointRoutes": TierUnimplemented, - "TagResource": TierUnimplemented, - "UntagResource": TierUnimplemented, - "UpdateAccessGrantsLocation": TierUnimplemented, - "UpdateJobPriority": TierUnimplemented, - "UpdateJobStatus": TierUnimplemented, - "UpdateStorageLensGroup": TierUnimplemented, + "TagResource": TierAutoCRUD, + "UntagResource": TierAutoCRUD, + "UpdateAccessGrantsLocation": TierAutoCRUD, + "UpdateJobPriority": TierAutoCRUD, + "UpdateJobStatus": TierAutoCRUD, + "UpdateStorageLensGroup": TierAutoCRUD, }}, "s3tables": {Protocol: "", ModelBacked: false, EngineWired: false, Operations: map[string]Tier{ "CreateNamespace": TierHandVerified, diff --git a/internal/shared/crud/crud.go b/internal/shared/crud/crud.go index 70f0d17e..04f1c858 100644 --- a/internal/shared/crud/crud.go +++ b/internal/shared/crud/crud.go @@ -69,6 +69,7 @@ type Result struct { const ( jsonContentType = "application/x-amz-json-1.1" restJSONType = "application/json" + xmlContentType = "application/xml" protocolJSON10 = "json-1.0" protocolRESTJSON = "rest-json" @@ -132,24 +133,36 @@ func JSONProtocol(protocol string) bool { // 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. +// The JSON protocols carry the operation name in a header. rest-json and +// rest-xml do not, but their models bind every operation to a method and URI +// template, which the route table turns back into an operation name. query has +// neither a target header nor a modelled path — its operation is a form field — +// so a query request cannot be classified here and is declined rather than +// guessed at. +// +// This is deliberately the same question codegen's engineServable answers. The +// two must agree: a protocol admitted there but refused here registers +// operations nothing can reach, and the fidelity manifest would call them +// auto-crud. func Servable(protocol string) bool { - return JSONProtocol(protocol) || protocol == protocolRESTJSON + return JSONProtocol(protocol) || protocol == protocolRESTJSON || protocol == protocolRESTXML } // NeedsBody reports whether the gateway must buffer the request body before // calling Handle. // -// Not yet separated from Servable: this is the extraction point for the -// distinction, and it currently states the gateway's existing behaviour -// unchanged so the specification in crud_test.go fails against real values -// rather than as a build error. +// It is not the same question as Servable, and rest-xml is where the two come +// apart. The engine can classify a rest-xml request from its route table, but +// S3 speaks rest-xml and S3 bodies are large binary uploads; buffering those +// would turn a streaming path into a memory one, to serve a provider that never +// returns ErrUnhandledOp in the first place. Nothing is lost by it: every +// CRUD-shaped S3 Control operation addresses its resource with a path label or +// a query term, so the engine has what it needs without the body. +// +// query is the mirror image — not servable yet, but its operation name is a +// field in the form body, so it cannot be read without buffering. func NeedsBody(protocol string) bool { - return Servable(protocol) + return JSONProtocol(protocol) || protocol == protocolRESTJSON || protocol == protocolQuery } // Handle attempts to serve a call from the service's registered operations. It @@ -163,7 +176,7 @@ func Handle(c Call) (*Result, error) { switch { case JSONProtocol(c.Protocol): // The operation name arrived in X-Amz-Target; nothing to resolve. - case c.Protocol == protocolRESTJSON: + case c.Protocol == protocolRESTJSON, c.Protocol == protocolRESTXML: rest = true mu.RLock() rs := routes[c.Service] @@ -172,6 +185,10 @@ func Handle(c Call) (*Result, error) { // 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. + // + // It matters most for rest-xml, because S3 speaks it: an S3-shaped + // path reaching this engine must come back unclassified rather than be + // answered out of the generic store. if op, labels = httproute.Match(rs, c.Method, c.URI); op == "" { return nil, ErrUnclassified } @@ -200,7 +217,7 @@ func Handle(c Call) (*Result, error) { 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(), c.Protocol), nil + return withContentType(serializationError(c.Protocol), c.Protocol), nil } maps.Copy(params, body) } @@ -208,7 +225,7 @@ func Handle(c Call) (*Result, error) { params[k] = v } - res, err := dispatch(c.Service, m, params) + res, err := dispatch(c.Service, c.Protocol, op, m, params) return withContentType(res, c.Protocol), err } @@ -232,9 +249,16 @@ func queryParams(uri string) map[string]any { return out } +// xmlProtocol reports whether a protocol's bodies are XML. It is the +// serialization question, not the routing one: query and rest-xml resolve their +// operation in completely different ways but write the same kind of body. +func xmlProtocol(protocol string) bool { + return protocol == protocolRESTXML || protocol == protocolQuery +} + // 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. +// X-Amz-Target type it never uses. dispatch/okBody default to amz-json 1.1. func withContentType(res *Result, protocol string) *Result { if res == nil { return res @@ -248,40 +272,44 @@ func withContentType(res *Result, protocol string) *Result { return res } -func dispatch(service string, m OpMeta, params map[string]any) (*Result, error) { +// dispatch runs the generic CRUD behaviour for one classified operation. It +// takes the protocol and operation name only to serialize the result: the two +// XML dialects need the operation to build their envelope, and the behaviour +// above the serializer is identical for every protocol. +func dispatch(service, protocol, op string, m OpMeta, params map[string]any) (*Result, error) { switch m.Verb { case "Create": id := resourceID(m.Resource, params) item := maps.Clone(params) stamp(item, service, m.Resource, id) put(service, m.Resource, id, item) - return okJSON(wrapItem(m, item)) + return okBody(protocol, op, wrapItem(m, item)) case "Get": // A Describe*/Get* whose output is a collection (list key, no single-item // wrapper) returns the stored list, not a single-resource lookup — a fresh // store yields an empty collection (200), not ResourceNotFoundException. if m.OutputItemKey == "" && m.OutputListKey != "" { - return okJSON(map[string]any{m.OutputListKey: list(service, m.Resource)}) + return okBody(protocol, op, map[string]any{m.OutputListKey: list(service, m.Resource)}) } id := resourceID(m.Resource, params) item, found := get(service, m.Resource, id) if !found { - return notFound(m.Resource), nil + return notFound(protocol, m.Resource), nil } - return okJSON(wrapItem(m, item)) + return okBody(protocol, op, wrapItem(m, item)) case "List": key := m.OutputListKey if key == "" { key = m.Resource + "s" } - return okJSON(map[string]any{key: list(service, m.Resource)}) + return okBody(protocol, op, map[string]any{key: list(service, m.Resource)}) case "Delete": id := resourceID(m.Resource, params) del(service, m.Resource, id) - return okJSON(map[string]any{}) + return okBody(protocol, op, map[string]any{}) case "Update": id := resourceID(m.Resource, params) @@ -295,11 +323,11 @@ func dispatch(service string, m OpMeta, params map[string]any) (*Result, error) } } put(service, m.Resource, id, item) - return okJSON(wrapItem(m, item)) + return okBody(protocol, op, wrapItem(m, item)) case "Tag", "Untag", "Relate", "Toggle": // Relationship / tag / status flips: acknowledge without modelling state. - return okJSON(map[string]any{}) + return okBody(protocol, op, map[string]any{}) default: return nil, ErrUnclassified @@ -382,7 +410,13 @@ func list(service, resource string) []map[string]any { // --- helpers --- -func okJSON(v any) (*Result, error) { +// okBody serializes a successful response in the protocol's own encoding. The +// JSON protocols marshal the map directly; the XML dialects go through +// encodeXML, which needs the operation name to build its envelope. +func okBody(protocol, op string, v map[string]any) (*Result, error) { + if xmlProtocol(protocol) { + return &Result{Status: 200, Body: encodeXML(protocol, op, v), ContentType: xmlContentType}, nil + } b, err := json.Marshal(v) if err != nil { return nil, err @@ -390,19 +424,32 @@ func okJSON(v any) (*Result, error) { return &Result{Status: 200, Body: b, ContentType: jsonContentType}, nil } -func notFound(resource string) *Result { - b, _ := json.Marshal(map[string]string{ - "__type": "ResourceNotFoundException", - "message": resource + " not found", - }) - return &Result{Status: 400, Body: b, ContentType: jsonContentType} +func notFound(protocol, resource string) *Result { + return errorResult(protocol, "ResourceNotFoundException", resource+" not found") } -func serializationError() *Result { - b, _ := json.Marshal(map[string]string{ - "__type": "SerializationException", - "message": "failed to deserialize request body", - }) +func serializationError(protocol string) *Result { + return errorResult(protocol, "SerializationException", "failed to deserialize request body") +} + +// errorResult renders one of the engine's own errors in the protocol's error +// vocabulary. The XML dialects do not share an envelope: botocore's query +// parser looks for Error *inside* ErrorResponse and returns a code-less +// ClientError given a bare Error, while rest-xml expects the bare one. The +// gateway's writeAWSError makes the same distinction for the errors it writes; +// these are the ones the engine produces after it has already taken the request. +func errorResult(protocol, code, message string) *Result { + if xmlProtocol(protocol) { + body := xmlHeader + if protocol == protocolQuery { + body += "Sender" + code + + "" + message + "" + } else { + body += "" + code + "" + message + "" + } + return &Result{Status: 400, Body: []byte(body), ContentType: xmlContentType} + } + b, _ := json.Marshal(map[string]string{"__type": code, "message": message}) return &Result{Status: 400, Body: b, ContentType: jsonContentType} } From 4c973492b2500b83c1dce10a3e13dcfc865e0307 Mon Sep 17 00:00:00 2001 From: Sung-Kyu Yoo Date: Sat, 5 Sep 2026 20:50:05 +0900 Subject: [PATCH 05/10] test: specify query as engine-servable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RED: Servable("query") = false, want true; TestEngineQueryRoundTrip, TestEngineQueryDropsProtocolFields, TestEngineQueryBodyIsNotJSON and TestEngineQueryContentType all fail. query is the last protocol and the odd one: its operation is neither a header nor a path but the Action field of a form body. Two traps are specified rather than left to be hit — Action and Version describe the request, not the resource, so they must not be stored and echoed back as members; and Handle's JSON body parse must not treat a form-encoded body as a malformed JSON one, which would decline every query call with a SerializationException. --- internal/shared/crud/crud_test.go | 179 ++++++++++++++++++++++++++---- 1 file changed, 160 insertions(+), 19 deletions(-) diff --git a/internal/shared/crud/crud_test.go b/internal/shared/crud/crud_test.go index e0ac9b6e..0f45798e 100644 --- a/internal/shared/crud/crud_test.go +++ b/internal/shared/crud/crud_test.go @@ -4,6 +4,7 @@ package crud import ( "encoding/json" + "net/url" "strings" "sync" "testing" @@ -87,8 +88,10 @@ 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(Call{Service: svc, Protocol: "query", Op: "CreateWidget", Body: []byte("{}")}); err != ErrUnclassified { - t.Fatalf("non-json protocol: want ErrUnclassified, got %v", err) + // ec2-query is the protocol still outside the engine: unlike query, it is + // not form-encoded with an Action field the engine can read. + if _, err := Handle(Call{Service: svc, Protocol: "ec2-query", Op: "CreateWidget", Body: []byte("{}")}); err != ErrUnclassified { + t.Fatalf("unservable protocol: want ErrUnclassified, got %v", err) } if _, err := handleJSON(t, "unregistered", "CreateThing", nil); err != ErrUnclassified { t.Fatalf("unregistered service: want ErrUnclassified, got %v", err) @@ -295,23 +298,161 @@ func TestEngineRESTJSONUnroutedOperationIsUnclassified(t *testing.T) { } } -// TestEngineQueryStillDeclines pins what is left of the boundary. query names -// its operation in the form body rather than in the path, so until the engine -// learns to read that, a query call must decline. -// -// This replaces TestEngineRESTXMLStillDeclines: rest-xml is no longer on the -// wrong side of the line. Every one of its operations is bound to a method and -// a URI template, exactly like rest-json, so the same route table classifies it. -func TestEngineQueryStillDeclines(t *testing.T) { - const svc = "querysvc" +// --- query --- + +func handleQuery(t *testing.T, service string, form url.Values) (*Result, error) { + t.Helper() + // Query is a form POST to "/": no path, no header, everything in the body. + return Handle(Call{ + Service: service, Protocol: "query", + Method: "POST", URI: "/", Body: []byte(form.Encode()), + }) +} + +// TestEngineQueryRoundTrip is the last protocol. query is the one that names +// its operation neither in a header nor in a path — Action is a field in the +// form body, which is why it outlived rest-json and rest-xml as a gap. +func TestEngineQueryRoundTrip(t *testing.T) { + const svc = "elbtest" Register(svc, map[string]OpMeta{ - "ListThings": {Verb: "List", Resource: "QYThing", OutputListKey: "Things", - Method: "GET", URI: "/things"}, + "CreateLoadBalancer": {Verb: "Create", Resource: "LoadBalancer", OutputItemKey: "LoadBalancer"}, + "DescribeLoadBalancers": {Verb: "Get", Resource: "LoadBalancer", + OutputListKey: "LoadBalancerDescriptions"}, + "DeleteLoadBalancer": {Verb: "Delete", Resource: "LoadBalancer"}, + }) + + // A Describe whose output is a collection reads as a list, so an empty + // store answers 200 with an empty element rather than NotFound. + r, err := handleQuery(t, svc, url.Values{ + "Action": {"DescribeLoadBalancers"}, + "Version": {"2012-06-01"}, + }) + if err != nil || r.Status != 200 { + t.Fatalf("describe on empty store: status=%d err=%v", statusOf(r), err) + } + if got := string(r.Body); !strings.Contains(got, "") { + t.Fatalf("not a query envelope: %s", got) + } + + r, err = handleQuery(t, svc, url.Values{ + "Action": {"CreateLoadBalancer"}, + "Version": {"2012-06-01"}, + "LoadBalancerName": {"my-lb"}, + }) + if err != nil || r.Status != 200 { + t.Fatalf("create: status=%d err=%v", statusOf(r), err) + } + if got := string(r.Body); !strings.Contains(got, "my-lb") { + t.Fatalf("create did not echo the form parameter: %s", got) + } + + // The round trip that matters: the name the caller sent comes back. + r, _ = handleQuery(t, svc, url.Values{"Action": {"DescribeLoadBalancers"}}) + if got := string(r.Body); !strings.Contains(got, "my-lb") { + t.Fatalf("describe did not return the created load balancer: %s", got) + } + + if _, err := handleQuery(t, svc, url.Values{ + "Action": {"DeleteLoadBalancer"}, "LoadBalancerName": {"my-lb"}, + }); err != nil { + t.Fatalf("delete: %v", err) + } + r, _ = handleQuery(t, svc, url.Values{"Action": {"DescribeLoadBalancers"}}) + if got := string(r.Body); strings.Contains(got, "my-lb") { + t.Fatalf("resource survived delete: %s", got) + } +} + +// TestEngineQueryDropsProtocolFields keeps Action and Version out of the stored +// resource. They describe the request, not the thing being created, and echoing +// them back puts CreateLoadBalancer inside a result element +// where no SDK expects a member by that name. +func TestEngineQueryDropsProtocolFields(t *testing.T) { + const svc = "qfieldsvc" + Register(svc, map[string]OpMeta{ + "CreateThing": {Verb: "Create", Resource: "QFThing", OutputItemKey: "Thing"}, + }) + + r, err := handleQuery(t, svc, url.Values{ + "Action": {"CreateThing"}, "Version": {"2012-06-01"}, "QFThingName": {"t1"}, + }) + if err != nil { + t.Fatalf("create: %v", err) + } + body := string(r.Body) + if strings.Contains(body, "") || strings.Contains(body, "") { + t.Errorf("protocol envelope fields leaked into the resource: %s", body) + } + if !strings.Contains(body, "t1") { + t.Errorf("real parameter was dropped: %s", body) + } +} + +// TestEngineQueryDeclines covers every way a query request must fail rather +// than be answered from the generic store. +func TestEngineQueryDeclines(t *testing.T) { + const svc = "qmisssvc" + Register(svc, map[string]OpMeta{ + "CreateThing": {Verb: "Create", Resource: "QMThing"}, }) - _, err := Handle(Call{Service: svc, Protocol: "query", Method: "GET", URI: "/things"}) - if err != ErrUnclassified { - t.Errorf("query: want ErrUnclassified, got %v", err) + cases := []struct { + name string + form url.Values + }{ + // Not CRUD-shaped, so codegen registered nothing for it. + {"unknown_action", url.Values{"Action": {"ConfigureHealthCheck"}}}, + // A form body with no Action at all is not a query request the engine + // can classify; guessing an operation from the other fields would be + // exactly the fabrication the coverage claim forbids. + {"no_action", url.Values{"LoadBalancerName": {"x"}}}, + {"empty_action", url.Values{"Action": {""}}}, + } + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + if _, err := handleQuery(t, svc, c.form); err != ErrUnclassified { + t.Errorf("want ErrUnclassified, got %v", err) + } + }) + } + + if _, err := handleQuery(t, "unregistered", url.Values{"Action": {"CreateThing"}}); err != ErrUnclassified { + t.Errorf("unregistered service: want ErrUnclassified, got %v", err) + } +} + +// TestEngineQueryBodyIsNotJSON guards the branch that would otherwise reject +// every query request. Handle parses the body as JSON for the protocols that +// send JSON; a form-encoded body is not JSON, and treating a failure to parse +// it as a SerializationException would decline every query call with the wrong +// error. +func TestEngineQueryBodyIsNotJSON(t *testing.T) { + const svc = "qjsonsvc" + Register(svc, map[string]OpMeta{ + "ListThings": {Verb: "List", Resource: "QJThing", OutputListKey: "Things"}, + }) + + r, err := handleQuery(t, svc, url.Values{"Action": {"ListThings"}}) + if err != nil { + t.Fatalf("list: %v", err) + } + if r.Status != 200 { + t.Fatalf("form body was rejected as malformed JSON: %d %s", r.Status, r.Body) + } +} + +func TestEngineQueryContentType(t *testing.T) { + const svc = "qctsvc" + Register(svc, map[string]OpMeta{ + "ListThings": {Verb: "List", Resource: "QCThing", OutputListKey: "Things"}, + }) + + r, err := handleQuery(t, svc, url.Values{"Action": {"ListThings"}}) + if err != nil { + t.Fatalf("list: %v", err) + } + if r.ContentType != "application/xml" { + t.Errorf("ContentType = %q, want application/xml", r.ContentType) } } @@ -334,9 +475,9 @@ func TestServableAndNeedsBody(t *testing.T) { {"rest-json", true, true}, // The whole reason the predicates are separate. {"rest-xml", true, false}, - // Admitted in Task 4; its operation name is in the body, so it must be - // buffered before it can be read. - {"query", false, true}, + // The mirror image: servable, and its operation name is in the body, so + // it must be buffered before it can be read. + {"query", true, true}, {"ec2-query", false, false}, {"nonsense", false, false}, } From cee511fbec37e1014a439d4f2b9662a433924f4f Mon Sep 17 00:00:00 2001 From: Sung-Kyu Yoo Date: Sat, 5 Sep 2026 20:52:22 +0900 Subject: [PATCH 06/10] feat: serve query from the generic CRUD engine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GREEN: go test ./... fully green; make build clean; codegen idempotent. query is the last protocol and the odd one out. Its operation is neither a header nor a path but the Action field of a form body, which is why it outlived rest-json and rest-xml as a gap — and why it registers no route: a query operation has no method or URI at all. 18 operations move unimplemented -> auto-crud, all in elasticloadbalancing. Thirteen other query services gain registry entries and not one manifest change, including elbv2 sitting directly beside it, because EngineWired gates the label and none of their hand-written providers returns ErrUnhandledOp. Two traps closed by construction rather than by luck: Action and Version are dropped before storage, so a created resource does not echo back as a member; and the JSON body parse is now an else-branch, because reaching it with a form-encoded body would have declined every query call with a SerializationException. --- internal/codegen/gen_crud_meta.go | 11 +- internal/codegen/gen_crud_meta_test.go | 34 +- internal/gateway/router_test.go | 30 + .../generated/crudregistry/registry_gen.go | 823 ++++++++++++++++++ internal/generated/fidelity/manifest_gen.go | 36 +- internal/shared/crud/crud.go | 75 +- 6 files changed, 971 insertions(+), 38 deletions(-) diff --git a/internal/codegen/gen_crud_meta.go b/internal/codegen/gen_crud_meta.go index 658bdb77..d88e0799 100644 --- a/internal/codegen/gen_crud_meta.go +++ b/internal/codegen/gen_crud_meta.go @@ -139,9 +139,12 @@ func classifyOps(model *ir.Model) []crudOpData { // on the assumption that it had no modelled path; it has one, and all 97 of // s3-control's operations carry it. // -// query is what is left of PRD Milestone 5. Its operation is a field in the -// form body rather than a header or a path, so nothing here can match a request -// to it and admitting it would mean guessing. +// query has no modelled path at all, so it registers no route; the engine +// matches it by the Action field of the form body instead. It is admitted here +// because that is a place the operation name genuinely is, not a guess. +// +// ec2-query stays out. It is form-encoded like query but not interchangeable +// with it, and the only service that speaks it has a hand-written provider. // // This is deliberately the same question crud.Servable answers at runtime. The // two must agree: a protocol classified here but refused there registers @@ -149,7 +152,7 @@ func classifyOps(model *ir.Model) []crudOpData { // auto-crud. func engineServable(protocol string) bool { return strings.HasPrefix(protocol, "json") || - protocol == "rest-json" || protocol == "rest-xml" + protocol == "rest-json" || protocol == "rest-xml" || protocol == "query" } // ServiceCRUDData classifies an engine-servable model's CRUD operations. It diff --git a/internal/codegen/gen_crud_meta_test.go b/internal/codegen/gen_crud_meta_test.go index 28c6ed54..4a0fa436 100644 --- a/internal/codegen/gen_crud_meta_test.go +++ b/internal/codegen/gen_crud_meta_test.go @@ -115,17 +115,39 @@ func TestServiceCRUDDataAdmitsRESTXML(t *testing.T) { assert.Equal(t, "/v20180820/accesspoint", ops["ListAccessPoints"].URI) } -// TestServiceCRUDDataRejectsQuery holds what is left of the boundary Milestone 5 -// owns. query puts the operation neither in a header nor in a modelled path — -// it is a field in the form body — so until the engine reads that, admitting it -// would register operations no request can be matched to. -func TestServiceCRUDDataRejectsQuery(t *testing.T) { +// TestServiceCRUDDataAdmitsQuery closes the last protocol gap. query has no +// modelled path at all — its operations carry no http trait — so unlike the +// REST protocols it registers no route, and the engine matches it by the +// Action field of the form body instead. +func TestServiceCRUDDataAdmitsQuery(t *testing.T) { model := crudModel("query", ir.Operation{Name: "DescribeLoadBalancers", OutputName: "DescribeLoadBalancersOutput"}, ) + data, ok := ServiceCRUDData(model) + require.True(t, ok, "query service must be engine-servable") + + ops := map[string]crudOpData{} + for _, op := range data.Ops { + ops[op.Op] = op + } + // No route, and that is correct rather than a gap: a query operation has + // no method or URI to register, and Register skips an empty URI so the + // service contributes nothing to the route table. + assert.Empty(t, ops["DescribeLoadBalancers"].Method) + assert.Empty(t, ops["DescribeLoadBalancers"].URI) +} + +// TestServiceCRUDDataRejectsEC2Query holds the remaining boundary. ec2Query is +// form-encoded like query but not interchangeable with it, and the only service +// that speaks it has a hand-written provider that never reaches the engine. +func TestServiceCRUDDataRejectsEC2Query(t *testing.T) { + model := crudModel("ec2-query", + ir.Operation{Name: "DescribeInstances", OutputName: "DescribeInstancesOutput"}, + ) + _, ok := ServiceCRUDData(model) - assert.False(t, ok, "query must not be engine-servable yet") + assert.False(t, ok, "ec2-query must not be engine-servable") } // TestServiceCRUDDataSkipsUnclassifiableService is the rds-data case: a diff --git a/internal/gateway/router_test.go b/internal/gateway/router_test.go index b806c637..636dd2f6 100644 --- a/internal/gateway/router_test.go +++ b/internal/gateway/router_test.go @@ -219,6 +219,36 @@ func TestServiceRouter_RESTJSONUnmatchedPathDeclinesCleanly(t *testing.T) { assert.Contains(t, w.Body.String(), "InvalidAction") } +// TestServiceRouter_QueryReachesEngine is the gateway half of the query change. +// It is worth its own test because query is the only protocol where the gateway +// and the engine could disagree about which operation a request is for: the +// gateway reads Action from the URL, the engine reads it from the form body, +// and every real SDK puts it in the body. +func TestServiceRouter_QueryReachesEngine(t *testing.T) { + const svc = "gwquerysvc" + crud.Register(svc, map[string]crud.OpMeta{ + "CreateGizmo": {Verb: "Create", Resource: "GwGizmo", OutputItemKey: "Gizmo"}, + }) + router := NewServiceRouter(newDecliningRegistry(svc, plugin.ProtocolQuery), nil) + + form := "Action=CreateGizmo&Version=2012-06-01&GwGizmoName=g1" + req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(form)) + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + req.Header.Set("Authorization", + "AWS4-HMAC-SHA256 Credential=AKIA/20130524/us-east-1/"+svc+"/aws4_request, Signature=abc") + + w := httptest.NewRecorder() + router.ServeHTTP(w, req) + + require.Equal(t, http.StatusOK, w.Code, "body: %s", w.Body.String()) + body := w.Body.String() + assert.Contains(t, body, "", "not the query envelope") + assert.Contains(t, body, "") + assert.Contains(t, body, "g1", + "the form body did not reach the engine") + assert.NotContains(t, body, "", "protocol field leaked into the resource") +} + // TestServiceRouter_RESTXMLReachesEngineWithoutBuffering is the gateway half of // the rest-xml change, and it asserts two things that have to hold together. // diff --git a/internal/generated/crudregistry/registry_gen.go b/internal/generated/crudregistry/registry_gen.go index 75c40de0..f42bf517 100644 --- a/internal/generated/crudregistry/registry_gen.go +++ b/internal/generated/crudregistry/registry_gen.go @@ -567,6 +567,47 @@ func init() { "UpdatePreparedStatement": {Verb: "Update", Resource: "PreparedStatement", OutputListKey: "", OutputItemKey: ""}, "UpdateWorkGroup": {Verb: "Update", Resource: "WorkGroup", OutputListKey: "", OutputItemKey: ""}, }) + crud.Register("autoscaling", map[string]crud.OpMeta{ + "CreateAutoScalingGroup": {Verb: "Create", Resource: "AutoScalingGroup", OutputListKey: "", OutputItemKey: ""}, + "CreateLaunchConfiguration": {Verb: "Create", Resource: "LaunchConfiguration", OutputListKey: "", OutputItemKey: ""}, + "CreateOrUpdateTags": {Verb: "Create", Resource: "OrUpdateTag", OutputListKey: "", OutputItemKey: ""}, + "DeleteAutoScalingGroup": {Verb: "Delete", Resource: "AutoScalingGroup", OutputListKey: "", OutputItemKey: ""}, + "DeleteLaunchConfiguration": {Verb: "Delete", Resource: "LaunchConfiguration", OutputListKey: "", OutputItemKey: ""}, + "DeleteLifecycleHook": {Verb: "Delete", Resource: "LifecycleHook", OutputListKey: "", OutputItemKey: ""}, + "DeleteNotificationConfiguration": {Verb: "Delete", Resource: "NotificationConfiguration", OutputListKey: "", OutputItemKey: ""}, + "DeletePolicy": {Verb: "Delete", Resource: "Policy", OutputListKey: "", OutputItemKey: ""}, + "DeleteScheduledAction": {Verb: "Delete", Resource: "ScheduledAction", OutputListKey: "", OutputItemKey: ""}, + "DeleteTags": {Verb: "Delete", Resource: "Tag", OutputListKey: "", OutputItemKey: ""}, + "DeleteWarmPool": {Verb: "Delete", Resource: "WarmPool", OutputListKey: "", OutputItemKey: ""}, + "DescribeAccountLimits": {Verb: "Get", Resource: "AccountLimit", OutputListKey: "", OutputItemKey: ""}, + "DescribeAdjustmentTypes": {Verb: "Get", Resource: "AdjustmentType", OutputListKey: "AdjustmentTypes", OutputItemKey: ""}, + "DescribeAutoScalingGroups": {Verb: "Get", Resource: "AutoScalingGroup", OutputListKey: "AutoScalingGroups", OutputItemKey: ""}, + "DescribeAutoScalingInstances": {Verb: "Get", Resource: "AutoScalingInstance", OutputListKey: "AutoScalingInstances", OutputItemKey: ""}, + "DescribeAutoScalingNotificationTypes": {Verb: "Get", Resource: "AutoScalingNotificationType", OutputListKey: "AutoScalingNotificationTypes", OutputItemKey: ""}, + "DescribeInstanceRefreshes": {Verb: "Get", Resource: "InstanceRefreshe", OutputListKey: "InstanceRefreshes", OutputItemKey: ""}, + "DescribeLaunchConfigurations": {Verb: "Get", Resource: "LaunchConfiguration", OutputListKey: "LaunchConfigurations", OutputItemKey: ""}, + "DescribeLifecycleHookTypes": {Verb: "Get", Resource: "LifecycleHookType", OutputListKey: "LifecycleHookTypes", OutputItemKey: ""}, + "DescribeLifecycleHooks": {Verb: "Get", Resource: "LifecycleHook", OutputListKey: "LifecycleHooks", OutputItemKey: ""}, + "DescribeLoadBalancerTargetGroups": {Verb: "Get", Resource: "LoadBalancerTargetGroup", OutputListKey: "LoadBalancerTargetGroups", OutputItemKey: ""}, + "DescribeLoadBalancers": {Verb: "Get", Resource: "LoadBalancer", OutputListKey: "LoadBalancers", OutputItemKey: ""}, + "DescribeMetricCollectionTypes": {Verb: "Get", Resource: "MetricCollectionType", OutputListKey: "Granularities", OutputItemKey: ""}, + "DescribeNotificationConfigurations": {Verb: "Get", Resource: "NotificationConfiguration", OutputListKey: "NotificationConfigurations", OutputItemKey: ""}, + "DescribePolicies": {Verb: "Get", Resource: "Policy", OutputListKey: "ScalingPolicies", OutputItemKey: ""}, + "DescribeScalingActivities": {Verb: "Get", Resource: "ScalingActivity", OutputListKey: "Activities", OutputItemKey: ""}, + "DescribeScalingProcessTypes": {Verb: "Get", Resource: "ScalingProcessType", OutputListKey: "Processes", OutputItemKey: ""}, + "DescribeScheduledActions": {Verb: "Get", Resource: "ScheduledAction", OutputListKey: "ScheduledUpdateGroupActions", OutputItemKey: ""}, + "DescribeTags": {Verb: "Get", Resource: "Tag", OutputListKey: "Tags", OutputItemKey: ""}, + "DescribeTerminationPolicyTypes": {Verb: "Get", Resource: "TerminationPolicyType", OutputListKey: "TerminationPolicyTypes", OutputItemKey: ""}, + "DescribeTrafficSources": {Verb: "Get", Resource: "TrafficSource", OutputListKey: "TrafficSources", OutputItemKey: ""}, + "DescribeWarmPool": {Verb: "Get", Resource: "WarmPool", OutputListKey: "Instances", OutputItemKey: "WarmPoolConfiguration"}, + "GetPredictiveScalingForecast": {Verb: "Get", Resource: "PredictiveScalingForecast", OutputListKey: "LoadForecast", OutputItemKey: "CapacityForecast"}, + "PutLifecycleHook": {Verb: "Update", Resource: "LifecycleHook", OutputListKey: "", OutputItemKey: ""}, + "PutNotificationConfiguration": {Verb: "Update", Resource: "NotificationConfiguration", OutputListKey: "", OutputItemKey: ""}, + "PutScalingPolicy": {Verb: "Update", Resource: "ScalingPolicy", OutputListKey: "Alarms", OutputItemKey: ""}, + "PutScheduledUpdateGroupAction": {Verb: "Update", Resource: "ScheduledUpdateGroupAction", OutputListKey: "", OutputItemKey: ""}, + "PutWarmPool": {Verb: "Update", Resource: "WarmPool", OutputListKey: "", OutputItemKey: ""}, + "UpdateAutoScalingGroup": {Verb: "Update", Resource: "AutoScalingGroup", 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"}, @@ -1263,6 +1304,73 @@ func init() { "UpdateProtectedJob": {Verb: "Update", Resource: "ProtectedJob", OutputListKey: "", OutputItemKey: "protectedJob", Method: "PATCH", URI: "/memberships/{membershipIdentifier}/protectedJobs/{protectedJobIdentifier}"}, "UpdateProtectedQuery": {Verb: "Update", Resource: "ProtectedQuery", OutputListKey: "", OutputItemKey: "protectedQuery", Method: "PATCH", URI: "/memberships/{membershipIdentifier}/protectedQueries/{protectedQueryIdentifier}"}, }) + crud.Register("cloudformation", map[string]crud.OpMeta{ + "CreateChangeSet": {Verb: "Create", Resource: "ChangeSet", OutputListKey: "", OutputItemKey: ""}, + "CreateGeneratedTemplate": {Verb: "Create", Resource: "GeneratedTemplate", OutputListKey: "", OutputItemKey: ""}, + "CreateStack": {Verb: "Create", Resource: "Stack", OutputListKey: "", OutputItemKey: ""}, + "CreateStackInstances": {Verb: "Create", Resource: "StackInstance", OutputListKey: "", OutputItemKey: ""}, + "CreateStackRefactor": {Verb: "Create", Resource: "StackRefactor", OutputListKey: "", OutputItemKey: ""}, + "CreateStackSet": {Verb: "Create", Resource: "StackSet", OutputListKey: "", OutputItemKey: ""}, + "DeleteChangeSet": {Verb: "Delete", Resource: "ChangeSet", OutputListKey: "", OutputItemKey: ""}, + "DeleteGeneratedTemplate": {Verb: "Delete", Resource: "GeneratedTemplate", OutputListKey: "", OutputItemKey: ""}, + "DeleteStack": {Verb: "Delete", Resource: "Stack", OutputListKey: "", OutputItemKey: ""}, + "DeleteStackInstances": {Verb: "Delete", Resource: "StackInstance", OutputListKey: "", OutputItemKey: ""}, + "DeleteStackSet": {Verb: "Delete", Resource: "StackSet", OutputListKey: "", OutputItemKey: ""}, + "DeregisterType": {Verb: "Delete", Resource: "Type", OutputListKey: "", OutputItemKey: ""}, + "DescribeAccountLimits": {Verb: "Get", Resource: "AccountLimit", OutputListKey: "AccountLimits", OutputItemKey: ""}, + "DescribeChangeSet": {Verb: "Get", Resource: "ChangeSet", OutputListKey: "Capabilities", OutputItemKey: "RollbackConfiguration"}, + "DescribeChangeSetHooks": {Verb: "Get", Resource: "ChangeSetHook", OutputListKey: "Hooks", OutputItemKey: ""}, + "DescribeEvents": {Verb: "Get", Resource: "Event", OutputListKey: "OperationEvents", OutputItemKey: ""}, + "DescribeGeneratedTemplate": {Verb: "Get", Resource: "GeneratedTemplate", OutputListKey: "Resources", OutputItemKey: "Progress"}, + "DescribeOrganizationsAccess": {Verb: "Get", Resource: "OrganizationsAccess", OutputListKey: "", OutputItemKey: ""}, + "DescribePublisher": {Verb: "Get", Resource: "Publisher", OutputListKey: "", OutputItemKey: ""}, + "DescribeResourceScan": {Verb: "Get", Resource: "ResourceScan", OutputListKey: "ResourceTypes", OutputItemKey: ""}, + "DescribeStackDriftDetectionStatus": {Verb: "Get", Resource: "StackDriftDetectionStatu", OutputListKey: "", OutputItemKey: ""}, + "DescribeStackEvents": {Verb: "Get", Resource: "StackEvent", OutputListKey: "StackEvents", OutputItemKey: ""}, + "DescribeStackInstance": {Verb: "Get", Resource: "StackInstance", OutputListKey: "", OutputItemKey: "StackInstance"}, + "DescribeStackRefactor": {Verb: "Get", Resource: "StackRefactor", OutputListKey: "StackIds", OutputItemKey: ""}, + "DescribeStackResource": {Verb: "Get", Resource: "StackResource", OutputListKey: "", OutputItemKey: "StackResourceDetail"}, + "DescribeStackResourceDrifts": {Verb: "Get", Resource: "StackResourceDrift", OutputListKey: "StackResourceDrifts", OutputItemKey: ""}, + "DescribeStackResources": {Verb: "Get", Resource: "StackResource", OutputListKey: "StackResources", OutputItemKey: ""}, + "DescribeStackSet": {Verb: "Get", Resource: "StackSet", OutputListKey: "", OutputItemKey: "StackSet"}, + "DescribeStackSetOperation": {Verb: "Get", Resource: "StackSetOperation", OutputListKey: "", OutputItemKey: "StackSetOperation"}, + "DescribeStacks": {Verb: "Get", Resource: "Stack", OutputListKey: "Stacks", OutputItemKey: ""}, + "DescribeType": {Verb: "Get", Resource: "Type", OutputListKey: "RequiredActivatedTypes", OutputItemKey: "LoggingConfig"}, + "DescribeTypeRegistration": {Verb: "Get", Resource: "TypeRegistration", OutputListKey: "", OutputItemKey: ""}, + "GetGeneratedTemplate": {Verb: "Get", Resource: "GeneratedTemplate", OutputListKey: "", OutputItemKey: ""}, + "GetHookResult": {Verb: "Get", Resource: "HookResult", OutputListKey: "Annotations", OutputItemKey: "Target"}, + "GetStackPolicy": {Verb: "Get", Resource: "StackPolicy", OutputListKey: "", OutputItemKey: ""}, + "GetTemplate": {Verb: "Get", Resource: "Template", OutputListKey: "StagesAvailable", OutputItemKey: ""}, + "GetTemplateSummary": {Verb: "Get", Resource: "TemplateSummary", OutputListKey: "Capabilities", OutputItemKey: "Warnings"}, + "ListChangeSets": {Verb: "List", Resource: "ChangeSet", OutputListKey: "Summaries", OutputItemKey: ""}, + "ListExports": {Verb: "List", Resource: "Export", OutputListKey: "Exports", OutputItemKey: ""}, + "ListGeneratedTemplates": {Verb: "List", Resource: "GeneratedTemplate", OutputListKey: "Summaries", OutputItemKey: ""}, + "ListHookResults": {Verb: "List", Resource: "HookResult", OutputListKey: "HookResults", OutputItemKey: ""}, + "ListImports": {Verb: "List", Resource: "Import", OutputListKey: "Imports", OutputItemKey: ""}, + "ListResourceScanRelatedResources": {Verb: "List", Resource: "ResourceScanRelatedResource", OutputListKey: "RelatedResources", OutputItemKey: ""}, + "ListResourceScanResources": {Verb: "List", Resource: "ResourceScanResource", OutputListKey: "Resources", OutputItemKey: ""}, + "ListResourceScans": {Verb: "List", Resource: "ResourceScan", OutputListKey: "ResourceScanSummaries", OutputItemKey: ""}, + "ListStackInstanceResourceDrifts": {Verb: "List", Resource: "StackInstanceResourceDrift", OutputListKey: "Summaries", OutputItemKey: ""}, + "ListStackInstances": {Verb: "List", Resource: "StackInstance", OutputListKey: "Summaries", OutputItemKey: ""}, + "ListStackRefactorActions": {Verb: "List", Resource: "StackRefactorAction", OutputListKey: "StackRefactorActions", OutputItemKey: ""}, + "ListStackRefactors": {Verb: "List", Resource: "StackRefactor", OutputListKey: "StackRefactorSummaries", OutputItemKey: ""}, + "ListStackResources": {Verb: "List", Resource: "StackResource", OutputListKey: "StackResourceSummaries", OutputItemKey: ""}, + "ListStackSetAutoDeploymentTargets": {Verb: "List", Resource: "StackSetAutoDeploymentTarget", OutputListKey: "Summaries", OutputItemKey: ""}, + "ListStackSetOperationResults": {Verb: "List", Resource: "StackSetOperationResult", OutputListKey: "Summaries", OutputItemKey: ""}, + "ListStackSetOperations": {Verb: "List", Resource: "StackSetOperation", OutputListKey: "Summaries", OutputItemKey: ""}, + "ListStackSets": {Verb: "List", Resource: "StackSet", OutputListKey: "Summaries", OutputItemKey: ""}, + "ListStacks": {Verb: "List", Resource: "Stack", OutputListKey: "StackSummaries", OutputItemKey: ""}, + "ListTypeRegistrations": {Verb: "List", Resource: "TypeRegistration", OutputListKey: "RegistrationTokenList", OutputItemKey: ""}, + "ListTypeVersions": {Verb: "List", Resource: "TypeVersion", OutputListKey: "TypeVersionSummaries", OutputItemKey: ""}, + "ListTypes": {Verb: "List", Resource: "Type", OutputListKey: "TypeSummaries", OutputItemKey: ""}, + "RegisterPublisher": {Verb: "Create", Resource: "Publisher", OutputListKey: "", OutputItemKey: ""}, + "RegisterType": {Verb: "Create", Resource: "Type", OutputListKey: "", OutputItemKey: ""}, + "UpdateGeneratedTemplate": {Verb: "Update", Resource: "GeneratedTemplate", OutputListKey: "", OutputItemKey: ""}, + "UpdateStack": {Verb: "Update", Resource: "Stack", OutputListKey: "", OutputItemKey: ""}, + "UpdateStackInstances": {Verb: "Update", Resource: "StackInstance", OutputListKey: "", OutputItemKey: ""}, + "UpdateStackSet": {Verb: "Update", Resource: "StackSet", OutputListKey: "", OutputItemKey: ""}, + "UpdateTerminationProtection": {Verb: "Update", Resource: "TerminationProtection", OutputListKey: "", OutputItemKey: ""}, + }) crud.Register("cloudfront", map[string]crud.OpMeta{ "CreateAnycastIpList": {Verb: "Create", Resource: "AnycastIpList", OutputListKey: "", OutputItemKey: "AnycastIpList", Method: "POST", URI: "/2020-05-31/anycast-ip-list"}, "CreateCachePolicy": {Verb: "Create", Resource: "CachePolicy", OutputListKey: "", OutputItemKey: "CachePolicy", Method: "POST", URI: "/2020-05-31/cache-policy"}, @@ -1438,6 +1546,28 @@ func init() { "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: ""}, "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: ""}, }) + crud.Register("cloudsearch", map[string]crud.OpMeta{ + "CreateDomain": {Verb: "Create", Resource: "Domain", OutputListKey: "", OutputItemKey: "DomainStatus"}, + "DeleteAnalysisScheme": {Verb: "Delete", Resource: "AnalysisScheme", OutputListKey: "", OutputItemKey: "AnalysisScheme"}, + "DeleteDomain": {Verb: "Delete", Resource: "Domain", OutputListKey: "", OutputItemKey: "DomainStatus"}, + "DeleteExpression": {Verb: "Delete", Resource: "Expression", OutputListKey: "", OutputItemKey: "Expression"}, + "DeleteIndexField": {Verb: "Delete", Resource: "IndexField", OutputListKey: "", OutputItemKey: "IndexField"}, + "DeleteSuggester": {Verb: "Delete", Resource: "Suggester", OutputListKey: "", OutputItemKey: "Suggester"}, + "DescribeAnalysisSchemes": {Verb: "Get", Resource: "AnalysisScheme", OutputListKey: "AnalysisSchemes", OutputItemKey: ""}, + "DescribeAvailabilityOptions": {Verb: "Get", Resource: "AvailabilityOption", OutputListKey: "", OutputItemKey: "AvailabilityOptions"}, + "DescribeDomainEndpointOptions": {Verb: "Get", Resource: "DomainEndpointOption", OutputListKey: "", OutputItemKey: "DomainEndpointOptions"}, + "DescribeDomains": {Verb: "Get", Resource: "Domain", OutputListKey: "DomainStatusList", OutputItemKey: ""}, + "DescribeExpressions": {Verb: "Get", Resource: "Expression", OutputListKey: "Expressions", OutputItemKey: ""}, + "DescribeIndexFields": {Verb: "Get", Resource: "IndexField", OutputListKey: "IndexFields", OutputItemKey: ""}, + "DescribeScalingParameters": {Verb: "Get", Resource: "ScalingParameter", OutputListKey: "", OutputItemKey: "ScalingParameters"}, + "DescribeServiceAccessPolicies": {Verb: "Get", Resource: "ServiceAccessPolicy", OutputListKey: "", OutputItemKey: "AccessPolicies"}, + "DescribeSuggesters": {Verb: "Get", Resource: "Suggester", OutputListKey: "Suggesters", OutputItemKey: ""}, + "ListDomainNames": {Verb: "List", Resource: "DomainName", OutputListKey: "", OutputItemKey: ""}, + "UpdateAvailabilityOptions": {Verb: "Update", Resource: "AvailabilityOption", OutputListKey: "", OutputItemKey: "AvailabilityOptions"}, + "UpdateDomainEndpointOptions": {Verb: "Update", Resource: "DomainEndpointOption", OutputListKey: "", OutputItemKey: "DomainEndpointOptions"}, + "UpdateScalingParameters": {Verb: "Update", Resource: "ScalingParameter", OutputListKey: "", OutputItemKey: "ScalingParameters"}, + "UpdateServiceAccessPolicies": {Verb: "Update", Resource: "ServiceAccessPolicy", OutputListKey: "", OutputItemKey: "AccessPolicies"}, + }) crud.Register("cloudtrail", map[string]crud.OpMeta{ "CreateChannel": {Verb: "Create", Resource: "Channel", OutputListKey: "Destinations", OutputItemKey: ""}, "CreateDashboard": {Verb: "Create", Resource: "Dashboard", OutputListKey: "TagsList", OutputItemKey: "RefreshSchedule"}, @@ -2816,6 +2946,46 @@ func init() { "UpdateSettings": {Verb: "Update", Resource: "Setting", OutputListKey: "", OutputItemKey: ""}, "UpdateTrust": {Verb: "Update", Resource: "Trust", OutputListKey: "", OutputItemKey: ""}, }) + crud.Register("docdb", map[string]crud.OpMeta{ + "CreateDBCluster": {Verb: "Create", Resource: "DBCluster", OutputListKey: "", OutputItemKey: "DBCluster"}, + "CreateDBClusterParameterGroup": {Verb: "Create", Resource: "DBClusterParameterGroup", OutputListKey: "", OutputItemKey: "DBClusterParameterGroup"}, + "CreateDBClusterSnapshot": {Verb: "Create", Resource: "DBClusterSnapshot", OutputListKey: "", OutputItemKey: "DBClusterSnapshot"}, + "CreateDBInstance": {Verb: "Create", Resource: "DBInstance", OutputListKey: "", OutputItemKey: "DBInstance"}, + "CreateDBSubnetGroup": {Verb: "Create", Resource: "DBSubnetGroup", OutputListKey: "", OutputItemKey: "DBSubnetGroup"}, + "CreateEventSubscription": {Verb: "Create", Resource: "EventSubscription", OutputListKey: "", OutputItemKey: "EventSubscription"}, + "CreateGlobalCluster": {Verb: "Create", Resource: "GlobalCluster", OutputListKey: "", OutputItemKey: "GlobalCluster"}, + "DeleteDBCluster": {Verb: "Delete", Resource: "DBCluster", OutputListKey: "", OutputItemKey: "DBCluster"}, + "DeleteDBClusterParameterGroup": {Verb: "Delete", Resource: "DBClusterParameterGroup", OutputListKey: "", OutputItemKey: ""}, + "DeleteDBClusterSnapshot": {Verb: "Delete", Resource: "DBClusterSnapshot", OutputListKey: "", OutputItemKey: "DBClusterSnapshot"}, + "DeleteDBInstance": {Verb: "Delete", Resource: "DBInstance", OutputListKey: "", OutputItemKey: "DBInstance"}, + "DeleteDBSubnetGroup": {Verb: "Delete", Resource: "DBSubnetGroup", OutputListKey: "", OutputItemKey: ""}, + "DeleteEventSubscription": {Verb: "Delete", Resource: "EventSubscription", OutputListKey: "", OutputItemKey: "EventSubscription"}, + "DeleteGlobalCluster": {Verb: "Delete", Resource: "GlobalCluster", OutputListKey: "", OutputItemKey: "GlobalCluster"}, + "DescribeCertificates": {Verb: "Get", Resource: "Certificate", OutputListKey: "Certificates", OutputItemKey: ""}, + "DescribeDBClusterParameterGroups": {Verb: "Get", Resource: "DBClusterParameterGroup", OutputListKey: "DBClusterParameterGroups", OutputItemKey: ""}, + "DescribeDBClusterParameters": {Verb: "Get", Resource: "DBClusterParameter", OutputListKey: "Parameters", OutputItemKey: ""}, + "DescribeDBClusterSnapshotAttributes": {Verb: "Get", Resource: "DBClusterSnapshotAttribute", OutputListKey: "", OutputItemKey: "DBClusterSnapshotAttributesResult"}, + "DescribeDBClusterSnapshots": {Verb: "Get", Resource: "DBClusterSnapshot", OutputListKey: "DBClusterSnapshots", OutputItemKey: ""}, + "DescribeDBClusters": {Verb: "Get", Resource: "DBCluster", OutputListKey: "DBClusters", OutputItemKey: ""}, + "DescribeDBEngineVersions": {Verb: "Get", Resource: "DBEngineVersion", OutputListKey: "DBEngineVersions", OutputItemKey: ""}, + "DescribeDBInstances": {Verb: "Get", Resource: "DBInstance", OutputListKey: "DBInstances", OutputItemKey: ""}, + "DescribeDBSubnetGroups": {Verb: "Get", Resource: "DBSubnetGroup", OutputListKey: "DBSubnetGroups", OutputItemKey: ""}, + "DescribeEngineDefaultClusterParameters": {Verb: "Get", Resource: "EngineDefaultClusterParameter", OutputListKey: "", OutputItemKey: "EngineDefaults"}, + "DescribeEventCategories": {Verb: "Get", Resource: "EventCategory", OutputListKey: "EventCategoriesMapList", OutputItemKey: ""}, + "DescribeEventSubscriptions": {Verb: "Get", Resource: "EventSubscription", OutputListKey: "EventSubscriptionsList", OutputItemKey: ""}, + "DescribeEvents": {Verb: "Get", Resource: "Event", OutputListKey: "Events", OutputItemKey: ""}, + "DescribeGlobalClusters": {Verb: "Get", Resource: "GlobalCluster", OutputListKey: "GlobalClusters", OutputItemKey: ""}, + "DescribeOrderableDBInstanceOptions": {Verb: "Get", Resource: "OrderableDBInstanceOption", OutputListKey: "OrderableDBInstanceOptions", OutputItemKey: ""}, + "DescribePendingMaintenanceActions": {Verb: "Get", Resource: "PendingMaintenanceAction", OutputListKey: "PendingMaintenanceActions", OutputItemKey: ""}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "TagList", OutputItemKey: ""}, + "ModifyDBCluster": {Verb: "Update", Resource: "DBCluster", OutputListKey: "", OutputItemKey: "DBCluster"}, + "ModifyDBClusterParameterGroup": {Verb: "Update", Resource: "DBClusterParameterGroup", OutputListKey: "", OutputItemKey: ""}, + "ModifyDBClusterSnapshotAttribute": {Verb: "Update", Resource: "DBClusterSnapshotAttribute", OutputListKey: "", OutputItemKey: "DBClusterSnapshotAttributesResult"}, + "ModifyDBInstance": {Verb: "Update", Resource: "DBInstance", OutputListKey: "", OutputItemKey: "DBInstance"}, + "ModifyDBSubnetGroup": {Verb: "Update", Resource: "DBSubnetGroup", OutputListKey: "", OutputItemKey: "DBSubnetGroup"}, + "ModifyEventSubscription": {Verb: "Update", Resource: "EventSubscription", OutputListKey: "", OutputItemKey: "EventSubscription"}, + "ModifyGlobalCluster": {Verb: "Update", Resource: "GlobalCluster", OutputListKey: "", OutputItemKey: "GlobalCluster"}, + }) crud.Register("dsql", map[string]crud.OpMeta{ "CreateCluster": {Verb: "Create", Resource: "Cluster", OutputListKey: "", OutputItemKey: "encryptionDetails", Method: "POST", URI: "/cluster"}, "CreateStream": {Verb: "Create", Resource: "Stream", OutputListKey: "", OutputItemKey: "", Method: "POST", URI: "/stream/{clusterIdentifier}"}, @@ -3104,6 +3274,159 @@ func init() { "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("elasticache", map[string]crud.OpMeta{ + "CreateCacheCluster": {Verb: "Create", Resource: "CacheCluster", OutputListKey: "", OutputItemKey: "CacheCluster"}, + "CreateCacheParameterGroup": {Verb: "Create", Resource: "CacheParameterGroup", OutputListKey: "", OutputItemKey: "CacheParameterGroup"}, + "CreateCacheSecurityGroup": {Verb: "Create", Resource: "CacheSecurityGroup", OutputListKey: "", OutputItemKey: "CacheSecurityGroup"}, + "CreateCacheSubnetGroup": {Verb: "Create", Resource: "CacheSubnetGroup", OutputListKey: "", OutputItemKey: "CacheSubnetGroup"}, + "CreateGlobalReplicationGroup": {Verb: "Create", Resource: "GlobalReplicationGroup", OutputListKey: "", OutputItemKey: "GlobalReplicationGroup"}, + "CreateReplicationGroup": {Verb: "Create", Resource: "ReplicationGroup", OutputListKey: "", OutputItemKey: "ReplicationGroup"}, + "CreateServerlessCache": {Verb: "Create", Resource: "ServerlessCache", OutputListKey: "", OutputItemKey: "ServerlessCache"}, + "CreateServerlessCacheSnapshot": {Verb: "Create", Resource: "ServerlessCacheSnapshot", OutputListKey: "", OutputItemKey: "ServerlessCacheSnapshot"}, + "CreateSnapshot": {Verb: "Create", Resource: "Snapshot", OutputListKey: "", OutputItemKey: "Snapshot"}, + "CreateUser": {Verb: "Create", Resource: "User", OutputListKey: "UserGroupIds", OutputItemKey: "Authentication"}, + "CreateUserGroup": {Verb: "Create", Resource: "UserGroup", OutputListKey: "ReplicationGroups", OutputItemKey: "PendingChanges"}, + "DeleteCacheCluster": {Verb: "Delete", Resource: "CacheCluster", OutputListKey: "", OutputItemKey: "CacheCluster"}, + "DeleteCacheParameterGroup": {Verb: "Delete", Resource: "CacheParameterGroup", OutputListKey: "", OutputItemKey: ""}, + "DeleteCacheSecurityGroup": {Verb: "Delete", Resource: "CacheSecurityGroup", OutputListKey: "", OutputItemKey: ""}, + "DeleteCacheSubnetGroup": {Verb: "Delete", Resource: "CacheSubnetGroup", OutputListKey: "", OutputItemKey: ""}, + "DeleteGlobalReplicationGroup": {Verb: "Delete", Resource: "GlobalReplicationGroup", OutputListKey: "", OutputItemKey: "GlobalReplicationGroup"}, + "DeleteReplicationGroup": {Verb: "Delete", Resource: "ReplicationGroup", OutputListKey: "", OutputItemKey: "ReplicationGroup"}, + "DeleteServerlessCache": {Verb: "Delete", Resource: "ServerlessCache", OutputListKey: "", OutputItemKey: "ServerlessCache"}, + "DeleteServerlessCacheSnapshot": {Verb: "Delete", Resource: "ServerlessCacheSnapshot", OutputListKey: "", OutputItemKey: "ServerlessCacheSnapshot"}, + "DeleteSnapshot": {Verb: "Delete", Resource: "Snapshot", OutputListKey: "", OutputItemKey: "Snapshot"}, + "DeleteUser": {Verb: "Delete", Resource: "User", OutputListKey: "UserGroupIds", OutputItemKey: "Authentication"}, + "DeleteUserGroup": {Verb: "Delete", Resource: "UserGroup", OutputListKey: "ReplicationGroups", OutputItemKey: "PendingChanges"}, + "DescribeCacheClusters": {Verb: "Get", Resource: "CacheCluster", OutputListKey: "CacheClusters", OutputItemKey: ""}, + "DescribeCacheEngineVersions": {Verb: "Get", Resource: "CacheEngineVersion", OutputListKey: "CacheEngineVersions", OutputItemKey: ""}, + "DescribeCacheParameterGroups": {Verb: "Get", Resource: "CacheParameterGroup", OutputListKey: "CacheParameterGroups", OutputItemKey: ""}, + "DescribeCacheParameters": {Verb: "Get", Resource: "CacheParameter", OutputListKey: "CacheNodeTypeSpecificParameters", OutputItemKey: ""}, + "DescribeCacheSecurityGroups": {Verb: "Get", Resource: "CacheSecurityGroup", OutputListKey: "CacheSecurityGroups", OutputItemKey: ""}, + "DescribeCacheSubnetGroups": {Verb: "Get", Resource: "CacheSubnetGroup", OutputListKey: "CacheSubnetGroups", OutputItemKey: ""}, + "DescribeEngineDefaultParameters": {Verb: "Get", Resource: "EngineDefaultParameter", OutputListKey: "", OutputItemKey: "EngineDefaults"}, + "DescribeEvents": {Verb: "Get", Resource: "Event", OutputListKey: "Events", OutputItemKey: ""}, + "DescribeGlobalReplicationGroups": {Verb: "Get", Resource: "GlobalReplicationGroup", OutputListKey: "GlobalReplicationGroups", OutputItemKey: ""}, + "DescribeReplicationGroups": {Verb: "Get", Resource: "ReplicationGroup", OutputListKey: "ReplicationGroups", OutputItemKey: ""}, + "DescribeReservedCacheNodes": {Verb: "Get", Resource: "ReservedCacheNode", OutputListKey: "ReservedCacheNodes", OutputItemKey: ""}, + "DescribeReservedCacheNodesOfferings": {Verb: "Get", Resource: "ReservedCacheNodesOffering", OutputListKey: "ReservedCacheNodesOfferings", OutputItemKey: ""}, + "DescribeServerlessCacheSnapshots": {Verb: "Get", Resource: "ServerlessCacheSnapshot", OutputListKey: "ServerlessCacheSnapshots", OutputItemKey: ""}, + "DescribeServerlessCaches": {Verb: "Get", Resource: "ServerlessCache", OutputListKey: "ServerlessCaches", OutputItemKey: ""}, + "DescribeServiceUpdates": {Verb: "Get", Resource: "ServiceUpdate", OutputListKey: "ServiceUpdates", OutputItemKey: ""}, + "DescribeSnapshots": {Verb: "Get", Resource: "Snapshot", OutputListKey: "Snapshots", OutputItemKey: ""}, + "DescribeUpdateActions": {Verb: "Get", Resource: "UpdateAction", OutputListKey: "UpdateActions", OutputItemKey: ""}, + "DescribeUserGroups": {Verb: "Get", Resource: "UserGroup", OutputListKey: "UserGroups", OutputItemKey: ""}, + "DescribeUsers": {Verb: "Get", Resource: "User", OutputListKey: "Users", OutputItemKey: ""}, + "ListAllowedNodeTypeModifications": {Verb: "List", Resource: "AllowedNodeTypeModification", OutputListKey: "ScaleDownModifications", OutputItemKey: ""}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "TagList", OutputItemKey: ""}, + "ModifyCacheCluster": {Verb: "Update", Resource: "CacheCluster", OutputListKey: "", OutputItemKey: "CacheCluster"}, + "ModifyCacheParameterGroup": {Verb: "Update", Resource: "CacheParameterGroup", OutputListKey: "", OutputItemKey: ""}, + "ModifyCacheSubnetGroup": {Verb: "Update", Resource: "CacheSubnetGroup", OutputListKey: "", OutputItemKey: "CacheSubnetGroup"}, + "ModifyGlobalReplicationGroup": {Verb: "Update", Resource: "GlobalReplicationGroup", OutputListKey: "", OutputItemKey: "GlobalReplicationGroup"}, + "ModifyReplicationGroup": {Verb: "Update", Resource: "ReplicationGroup", OutputListKey: "", OutputItemKey: "ReplicationGroup"}, + "ModifyReplicationGroupShardConfiguration": {Verb: "Update", Resource: "ReplicationGroupShardConfiguration", OutputListKey: "", OutputItemKey: "ReplicationGroup"}, + "ModifyServerlessCache": {Verb: "Update", Resource: "ServerlessCache", OutputListKey: "", OutputItemKey: "ServerlessCache"}, + "ModifyUser": {Verb: "Update", Resource: "User", OutputListKey: "UserGroupIds", OutputItemKey: "Authentication"}, + "ModifyUserGroup": {Verb: "Update", Resource: "UserGroup", OutputListKey: "ReplicationGroups", OutputItemKey: "PendingChanges"}, + }) + crud.Register("elasticbeanstalk", map[string]crud.OpMeta{ + "CreateApplication": {Verb: "Create", Resource: "Application", OutputListKey: "", OutputItemKey: "Application"}, + "CreateApplicationVersion": {Verb: "Create", Resource: "ApplicationVersion", OutputListKey: "", OutputItemKey: "ApplicationVersion"}, + "CreateConfigurationTemplate": {Verb: "Create", Resource: "ConfigurationTemplate", OutputListKey: "OptionSettings", OutputItemKey: ""}, + "CreateEnvironment": {Verb: "Create", Resource: "Environment", OutputListKey: "EnvironmentLinks", OutputItemKey: "Resources"}, + "CreatePlatformVersion": {Verb: "Create", Resource: "PlatformVersion", OutputListKey: "", OutputItemKey: "Builder"}, + "CreateStorageLocation": {Verb: "Create", Resource: "StorageLocation", OutputListKey: "", OutputItemKey: ""}, + "DeleteApplication": {Verb: "Delete", Resource: "Application", OutputListKey: "", OutputItemKey: ""}, + "DeleteApplicationVersion": {Verb: "Delete", Resource: "ApplicationVersion", OutputListKey: "", OutputItemKey: ""}, + "DeleteConfigurationTemplate": {Verb: "Delete", Resource: "ConfigurationTemplate", OutputListKey: "", OutputItemKey: ""}, + "DeleteEnvironmentConfiguration": {Verb: "Delete", Resource: "EnvironmentConfiguration", OutputListKey: "", OutputItemKey: ""}, + "DeletePlatformVersion": {Verb: "Delete", Resource: "PlatformVersion", OutputListKey: "", OutputItemKey: "PlatformSummary"}, + "DescribeAccountAttributes": {Verb: "Get", Resource: "AccountAttribute", OutputListKey: "", OutputItemKey: "ResourceQuotas"}, + "DescribeApplicationVersions": {Verb: "Get", Resource: "ApplicationVersion", OutputListKey: "ApplicationVersions", OutputItemKey: ""}, + "DescribeApplications": {Verb: "Get", Resource: "Application", OutputListKey: "Applications", OutputItemKey: ""}, + "DescribeConfigurationOptions": {Verb: "Get", Resource: "ConfigurationOption", OutputListKey: "Options", OutputItemKey: ""}, + "DescribeConfigurationSettings": {Verb: "Get", Resource: "ConfigurationSetting", OutputListKey: "ConfigurationSettings", OutputItemKey: ""}, + "DescribeEnvironmentHealth": {Verb: "Get", Resource: "EnvironmentHealth", OutputListKey: "Causes", OutputItemKey: "ApplicationMetrics"}, + "DescribeEnvironmentManagedActionHistory": {Verb: "Get", Resource: "EnvironmentManagedActionHistory", OutputListKey: "ManagedActionHistoryItems", OutputItemKey: ""}, + "DescribeEnvironmentManagedActions": {Verb: "Get", Resource: "EnvironmentManagedAction", OutputListKey: "ManagedActions", OutputItemKey: ""}, + "DescribeEnvironmentResources": {Verb: "Get", Resource: "EnvironmentResource", OutputListKey: "", OutputItemKey: "EnvironmentResources"}, + "DescribeEnvironments": {Verb: "Get", Resource: "Environment", OutputListKey: "Environments", OutputItemKey: ""}, + "DescribeEvents": {Verb: "Get", Resource: "Event", OutputListKey: "Events", OutputItemKey: ""}, + "DescribeInstancesHealth": {Verb: "Get", Resource: "InstancesHealth", OutputListKey: "InstanceHealthList", OutputItemKey: ""}, + "DescribePlatformVersion": {Verb: "Get", Resource: "PlatformVersion", OutputListKey: "", OutputItemKey: "PlatformDescription"}, + "ListAvailableSolutionStacks": {Verb: "List", Resource: "AvailableSolutionStack", OutputListKey: "SolutionStackDetails", OutputItemKey: ""}, + "ListPlatformBranches": {Verb: "List", Resource: "PlatformBranche", OutputListKey: "PlatformBranchSummaryList", OutputItemKey: ""}, + "ListPlatformVersions": {Verb: "List", Resource: "PlatformVersion", OutputListKey: "PlatformSummaryList", OutputItemKey: ""}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "ResourceTags", OutputItemKey: ""}, + "UpdateApplication": {Verb: "Update", Resource: "Application", OutputListKey: "", OutputItemKey: "Application"}, + "UpdateApplicationResourceLifecycle": {Verb: "Update", Resource: "ApplicationResourceLifecycle", OutputListKey: "", OutputItemKey: "ResourceLifecycleConfig"}, + "UpdateApplicationVersion": {Verb: "Update", Resource: "ApplicationVersion", OutputListKey: "", OutputItemKey: "ApplicationVersion"}, + "UpdateConfigurationTemplate": {Verb: "Update", Resource: "ConfigurationTemplate", OutputListKey: "OptionSettings", OutputItemKey: ""}, + "UpdateEnvironment": {Verb: "Update", Resource: "Environment", OutputListKey: "EnvironmentLinks", OutputItemKey: "Resources"}, + "UpdateTagsForResource": {Verb: "Update", Resource: "TagsForResource", OutputListKey: "", OutputItemKey: ""}, + }) + crud.Register("elasticloadbalancing", map[string]crud.OpMeta{ + "CreateAppCookieStickinessPolicy": {Verb: "Create", Resource: "AppCookieStickinessPolicy", OutputListKey: "", OutputItemKey: ""}, + "CreateLBCookieStickinessPolicy": {Verb: "Create", Resource: "LBCookieStickinessPolicy", OutputListKey: "", OutputItemKey: ""}, + "CreateLoadBalancer": {Verb: "Create", Resource: "LoadBalancer", OutputListKey: "", OutputItemKey: ""}, + "CreateLoadBalancerListeners": {Verb: "Create", Resource: "LoadBalancerListener", OutputListKey: "", OutputItemKey: ""}, + "CreateLoadBalancerPolicy": {Verb: "Create", Resource: "LoadBalancerPolicy", OutputListKey: "", OutputItemKey: ""}, + "DeleteLoadBalancer": {Verb: "Delete", Resource: "LoadBalancer", OutputListKey: "", OutputItemKey: ""}, + "DeleteLoadBalancerListeners": {Verb: "Delete", Resource: "LoadBalancerListener", OutputListKey: "", OutputItemKey: ""}, + "DeleteLoadBalancerPolicy": {Verb: "Delete", Resource: "LoadBalancerPolicy", OutputListKey: "", OutputItemKey: ""}, + "DeregisterInstancesFromLoadBalancer": {Verb: "Delete", Resource: "InstancesFromLoadBalancer", OutputListKey: "Instances", OutputItemKey: ""}, + "DescribeAccountLimits": {Verb: "Get", Resource: "AccountLimit", OutputListKey: "Limits", OutputItemKey: ""}, + "DescribeInstanceHealth": {Verb: "Get", Resource: "InstanceHealth", OutputListKey: "InstanceStates", OutputItemKey: ""}, + "DescribeLoadBalancerAttributes": {Verb: "Get", Resource: "LoadBalancerAttribute", OutputListKey: "", OutputItemKey: "LoadBalancerAttributes"}, + "DescribeLoadBalancerPolicies": {Verb: "Get", Resource: "LoadBalancerPolicy", OutputListKey: "PolicyDescriptions", OutputItemKey: ""}, + "DescribeLoadBalancerPolicyTypes": {Verb: "Get", Resource: "LoadBalancerPolicyType", OutputListKey: "PolicyTypeDescriptions", OutputItemKey: ""}, + "DescribeLoadBalancers": {Verb: "Get", Resource: "LoadBalancer", OutputListKey: "LoadBalancerDescriptions", OutputItemKey: ""}, + "DescribeTags": {Verb: "Get", Resource: "Tag", OutputListKey: "TagDescriptions", OutputItemKey: ""}, + "ModifyLoadBalancerAttributes": {Verb: "Update", Resource: "LoadBalancerAttribute", OutputListKey: "", OutputItemKey: "LoadBalancerAttributes"}, + "RegisterInstancesWithLoadBalancer": {Verb: "Create", Resource: "InstancesWithLoadBalancer", OutputListKey: "Instances", OutputItemKey: ""}, + }) + crud.Register("elasticloadbalancingv2", map[string]crud.OpMeta{ + "CreateListener": {Verb: "Create", Resource: "Listener", OutputListKey: "Listeners", OutputItemKey: ""}, + "CreateLoadBalancer": {Verb: "Create", Resource: "LoadBalancer", OutputListKey: "LoadBalancers", OutputItemKey: ""}, + "CreateRule": {Verb: "Create", Resource: "Rule", OutputListKey: "Rules", OutputItemKey: ""}, + "CreateTargetGroup": {Verb: "Create", Resource: "TargetGroup", OutputListKey: "TargetGroups", OutputItemKey: ""}, + "CreateTrustStore": {Verb: "Create", Resource: "TrustStore", OutputListKey: "TrustStores", OutputItemKey: ""}, + "DeleteListener": {Verb: "Delete", Resource: "Listener", OutputListKey: "", OutputItemKey: ""}, + "DeleteLoadBalancer": {Verb: "Delete", Resource: "LoadBalancer", OutputListKey: "", OutputItemKey: ""}, + "DeleteRule": {Verb: "Delete", Resource: "Rule", OutputListKey: "", OutputItemKey: ""}, + "DeleteSharedTrustStoreAssociation": {Verb: "Delete", Resource: "SharedTrustStoreAssociation", OutputListKey: "", OutputItemKey: ""}, + "DeleteTargetGroup": {Verb: "Delete", Resource: "TargetGroup", OutputListKey: "", OutputItemKey: ""}, + "DeleteTrustStore": {Verb: "Delete", Resource: "TrustStore", OutputListKey: "", OutputItemKey: ""}, + "DeregisterTargets": {Verb: "Delete", Resource: "Target", OutputListKey: "", OutputItemKey: ""}, + "DescribeAccountLimits": {Verb: "Get", Resource: "AccountLimit", OutputListKey: "Limits", OutputItemKey: ""}, + "DescribeCapacityReservation": {Verb: "Get", Resource: "CapacityReservation", OutputListKey: "CapacityReservationState", OutputItemKey: "MinimumLoadBalancerCapacity"}, + "DescribeListenerAttributes": {Verb: "Get", Resource: "ListenerAttribute", OutputListKey: "Attributes", OutputItemKey: ""}, + "DescribeListenerCertificates": {Verb: "Get", Resource: "ListenerCertificate", OutputListKey: "Certificates", OutputItemKey: ""}, + "DescribeListeners": {Verb: "Get", Resource: "Listener", OutputListKey: "Listeners", OutputItemKey: ""}, + "DescribeLoadBalancerAttributes": {Verb: "Get", Resource: "LoadBalancerAttribute", OutputListKey: "Attributes", OutputItemKey: ""}, + "DescribeLoadBalancers": {Verb: "Get", Resource: "LoadBalancer", OutputListKey: "LoadBalancers", OutputItemKey: ""}, + "DescribeRules": {Verb: "Get", Resource: "Rule", OutputListKey: "Rules", OutputItemKey: ""}, + "DescribeSSLPolicies": {Verb: "Get", Resource: "SSLPolicy", OutputListKey: "SslPolicies", OutputItemKey: ""}, + "DescribeTags": {Verb: "Get", Resource: "Tag", OutputListKey: "TagDescriptions", OutputItemKey: ""}, + "DescribeTargetGroupAttributes": {Verb: "Get", Resource: "TargetGroupAttribute", OutputListKey: "Attributes", OutputItemKey: ""}, + "DescribeTargetGroups": {Verb: "Get", Resource: "TargetGroup", OutputListKey: "TargetGroups", OutputItemKey: ""}, + "DescribeTargetHealth": {Verb: "Get", Resource: "TargetHealth", OutputListKey: "TargetHealthDescriptions", OutputItemKey: ""}, + "DescribeTrustStoreAssociations": {Verb: "Get", Resource: "TrustStoreAssociation", OutputListKey: "TrustStoreAssociations", OutputItemKey: ""}, + "DescribeTrustStoreRevocations": {Verb: "Get", Resource: "TrustStoreRevocation", OutputListKey: "TrustStoreRevocations", OutputItemKey: ""}, + "DescribeTrustStores": {Verb: "Get", Resource: "TrustStore", OutputListKey: "TrustStores", OutputItemKey: ""}, + "GetResourcePolicy": {Verb: "Get", Resource: "ResourcePolicy", OutputListKey: "", OutputItemKey: ""}, + "GetTrustStoreCaCertificatesBundle": {Verb: "Get", Resource: "TrustStoreCaCertificatesBundle", OutputListKey: "", OutputItemKey: ""}, + "GetTrustStoreRevocationContent": {Verb: "Get", Resource: "TrustStoreRevocationContent", OutputListKey: "", OutputItemKey: ""}, + "ModifyCapacityReservation": {Verb: "Update", Resource: "CapacityReservation", OutputListKey: "CapacityReservationState", OutputItemKey: "MinimumLoadBalancerCapacity"}, + "ModifyIpPools": {Verb: "Update", Resource: "IpPool", OutputListKey: "", OutputItemKey: "IpamPools"}, + "ModifyListener": {Verb: "Update", Resource: "Listener", OutputListKey: "Listeners", OutputItemKey: ""}, + "ModifyListenerAttributes": {Verb: "Update", Resource: "ListenerAttribute", OutputListKey: "Attributes", OutputItemKey: ""}, + "ModifyLoadBalancerAttributes": {Verb: "Update", Resource: "LoadBalancerAttribute", OutputListKey: "Attributes", OutputItemKey: ""}, + "ModifyRule": {Verb: "Update", Resource: "Rule", OutputListKey: "Rules", OutputItemKey: ""}, + "ModifyTargetGroup": {Verb: "Update", Resource: "TargetGroup", OutputListKey: "TargetGroups", OutputItemKey: ""}, + "ModifyTargetGroupAttributes": {Verb: "Update", Resource: "TargetGroupAttribute", OutputListKey: "Attributes", OutputItemKey: ""}, + "ModifyTrustStore": {Verb: "Update", Resource: "TrustStore", OutputListKey: "TrustStores", OutputItemKey: ""}, + "RegisterTargets": {Verb: "Create", Resource: "Target", OutputListKey: "", OutputItemKey: ""}, + }) 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"}, @@ -3971,6 +4294,147 @@ func init() { "UpdateFHIRDatastore": {Verb: "Update", Resource: "FHIRDatastore", OutputListKey: "", OutputItemKey: "DatastoreProperties"}, "UpdateProfileWithAgent": {Verb: "Update", Resource: "ProfileWithAgent", OutputListKey: "", OutputItemKey: "AgentResponse", Method: "POST", URI: "/update-profile-with-agent"}, }) + crud.Register("iam", map[string]crud.OpMeta{ + "CreateAccessKey": {Verb: "Create", Resource: "AccessKey", OutputListKey: "", OutputItemKey: "AccessKey"}, + "CreateAccountAlias": {Verb: "Create", Resource: "AccountAlia", OutputListKey: "", OutputItemKey: ""}, + "CreateDelegationRequest": {Verb: "Create", Resource: "DelegationRequest", OutputListKey: "", OutputItemKey: ""}, + "CreateGroup": {Verb: "Create", Resource: "Group", OutputListKey: "", OutputItemKey: "Group"}, + "CreateInstanceProfile": {Verb: "Create", Resource: "InstanceProfile", OutputListKey: "", OutputItemKey: "InstanceProfile"}, + "CreateLoginProfile": {Verb: "Create", Resource: "LoginProfile", OutputListKey: "", OutputItemKey: "LoginProfile"}, + "CreateOpenIDConnectProvider": {Verb: "Create", Resource: "OpenIDConnectProvider", OutputListKey: "Tags", OutputItemKey: ""}, + "CreatePolicy": {Verb: "Create", Resource: "Policy", OutputListKey: "", OutputItemKey: "Policy"}, + "CreatePolicyVersion": {Verb: "Create", Resource: "PolicyVersion", OutputListKey: "", OutputItemKey: "PolicyVersion"}, + "CreateRole": {Verb: "Create", Resource: "Role", OutputListKey: "", OutputItemKey: "Role"}, + "CreateSAMLProvider": {Verb: "Create", Resource: "SAMLProvider", OutputListKey: "Tags", OutputItemKey: ""}, + "CreateServiceLinkedRole": {Verb: "Create", Resource: "ServiceLinkedRole", OutputListKey: "", OutputItemKey: "Role"}, + "CreateServiceSpecificCredential": {Verb: "Create", Resource: "ServiceSpecificCredential", OutputListKey: "", OutputItemKey: "ServiceSpecificCredential"}, + "CreateUser": {Verb: "Create", Resource: "User", OutputListKey: "", OutputItemKey: "User"}, + "CreateVirtualMFADevice": {Verb: "Create", Resource: "VirtualMFADevice", OutputListKey: "", OutputItemKey: "VirtualMFADevice"}, + "DeleteAccessKey": {Verb: "Delete", Resource: "AccessKey", OutputListKey: "", OutputItemKey: ""}, + "DeleteAccountAlias": {Verb: "Delete", Resource: "AccountAlia", OutputListKey: "", OutputItemKey: ""}, + "DeleteAccountPasswordPolicy": {Verb: "Delete", Resource: "AccountPasswordPolicy", OutputListKey: "", OutputItemKey: ""}, + "DeleteGroup": {Verb: "Delete", Resource: "Group", OutputListKey: "", OutputItemKey: ""}, + "DeleteGroupPolicy": {Verb: "Delete", Resource: "GroupPolicy", OutputListKey: "", OutputItemKey: ""}, + "DeleteInstanceProfile": {Verb: "Delete", Resource: "InstanceProfile", OutputListKey: "", OutputItemKey: ""}, + "DeleteLoginProfile": {Verb: "Delete", Resource: "LoginProfile", OutputListKey: "", OutputItemKey: ""}, + "DeleteOpenIDConnectProvider": {Verb: "Delete", Resource: "OpenIDConnectProvider", OutputListKey: "", OutputItemKey: ""}, + "DeletePolicy": {Verb: "Delete", Resource: "Policy", OutputListKey: "", OutputItemKey: ""}, + "DeletePolicyVersion": {Verb: "Delete", Resource: "PolicyVersion", OutputListKey: "", OutputItemKey: ""}, + "DeleteRole": {Verb: "Delete", Resource: "Role", OutputListKey: "", OutputItemKey: ""}, + "DeleteRolePermissionsBoundary": {Verb: "Delete", Resource: "RolePermissionsBoundary", OutputListKey: "", OutputItemKey: ""}, + "DeleteRolePolicy": {Verb: "Delete", Resource: "RolePolicy", OutputListKey: "", OutputItemKey: ""}, + "DeleteSAMLProvider": {Verb: "Delete", Resource: "SAMLProvider", OutputListKey: "", OutputItemKey: ""}, + "DeleteSSHPublicKey": {Verb: "Delete", Resource: "SSHPublicKey", OutputListKey: "", OutputItemKey: ""}, + "DeleteServerCertificate": {Verb: "Delete", Resource: "ServerCertificate", OutputListKey: "", OutputItemKey: ""}, + "DeleteServiceLinkedRole": {Verb: "Delete", Resource: "ServiceLinkedRole", OutputListKey: "", OutputItemKey: ""}, + "DeleteServiceSpecificCredential": {Verb: "Delete", Resource: "ServiceSpecificCredential", OutputListKey: "", OutputItemKey: ""}, + "DeleteSigningCertificate": {Verb: "Delete", Resource: "SigningCertificate", OutputListKey: "", OutputItemKey: ""}, + "DeleteUser": {Verb: "Delete", Resource: "User", OutputListKey: "", OutputItemKey: ""}, + "DeleteUserPermissionsBoundary": {Verb: "Delete", Resource: "UserPermissionsBoundary", OutputListKey: "", OutputItemKey: ""}, + "DeleteUserPolicy": {Verb: "Delete", Resource: "UserPolicy", OutputListKey: "", OutputItemKey: ""}, + "DeleteVirtualMFADevice": {Verb: "Delete", Resource: "VirtualMFADevice", OutputListKey: "", OutputItemKey: ""}, + "GetAccessKeyLastUsed": {Verb: "Get", Resource: "AccessKeyLastUsed", OutputListKey: "", OutputItemKey: "AccessKeyLastUsed"}, + "GetAccountAuthorizationDetails": {Verb: "Get", Resource: "AccountAuthorizationDetail", OutputListKey: "GroupDetailList", OutputItemKey: ""}, + "GetAccountPasswordPolicy": {Verb: "Get", Resource: "AccountPasswordPolicy", OutputListKey: "", OutputItemKey: "PasswordPolicy"}, + "GetAccountSummary": {Verb: "Get", Resource: "AccountSummary", OutputListKey: "", OutputItemKey: ""}, + "GetContextKeysForCustomPolicy": {Verb: "Get", Resource: "ContextKeysForCustomPolicy", OutputListKey: "ContextKeyNames", OutputItemKey: ""}, + "GetContextKeysForPrincipalPolicy": {Verb: "Get", Resource: "ContextKeysForPrincipalPolicy", OutputListKey: "ContextKeyNames", OutputItemKey: ""}, + "GetCredentialReport": {Verb: "Get", Resource: "CredentialReport", OutputListKey: "", OutputItemKey: ""}, + "GetDelegationRequest": {Verb: "Get", Resource: "DelegationRequest", OutputListKey: "", OutputItemKey: "DelegationRequest"}, + "GetGroup": {Verb: "Get", Resource: "Group", OutputListKey: "Users", OutputItemKey: "Group"}, + "GetGroupPolicy": {Verb: "Get", Resource: "GroupPolicy", OutputListKey: "", OutputItemKey: ""}, + "GetHumanReadableSummary": {Verb: "Get", Resource: "HumanReadableSummary", OutputListKey: "", OutputItemKey: ""}, + "GetInstanceProfile": {Verb: "Get", Resource: "InstanceProfile", OutputListKey: "", OutputItemKey: "InstanceProfile"}, + "GetLoginProfile": {Verb: "Get", Resource: "LoginProfile", OutputListKey: "", OutputItemKey: "LoginProfile"}, + "GetMFADevice": {Verb: "Get", Resource: "MFADevice", OutputListKey: "", OutputItemKey: ""}, + "GetOpenIDConnectProvider": {Verb: "Get", Resource: "OpenIDConnectProvider", OutputListKey: "ClientIDList", OutputItemKey: ""}, + "GetOrganizationsAccessReport": {Verb: "Get", Resource: "OrganizationsAccessReport", OutputListKey: "AccessDetails", OutputItemKey: "ErrorDetails"}, + "GetOutboundWebIdentityFederationInfo": {Verb: "Get", Resource: "OutboundWebIdentityFederationInfo", OutputListKey: "", OutputItemKey: ""}, + "GetPolicy": {Verb: "Get", Resource: "Policy", OutputListKey: "", OutputItemKey: "Policy"}, + "GetPolicyVersion": {Verb: "Get", Resource: "PolicyVersion", OutputListKey: "", OutputItemKey: "PolicyVersion"}, + "GetRole": {Verb: "Get", Resource: "Role", OutputListKey: "", OutputItemKey: "Role"}, + "GetRolePolicy": {Verb: "Get", Resource: "RolePolicy", OutputListKey: "", OutputItemKey: ""}, + "GetSAMLProvider": {Verb: "Get", Resource: "SAMLProvider", OutputListKey: "PrivateKeyList", OutputItemKey: ""}, + "GetSSHPublicKey": {Verb: "Get", Resource: "SSHPublicKey", OutputListKey: "", OutputItemKey: "SSHPublicKey"}, + "GetServerCertificate": {Verb: "Get", Resource: "ServerCertificate", OutputListKey: "", OutputItemKey: "ServerCertificate"}, + "GetServiceLastAccessedDetails": {Verb: "Get", Resource: "ServiceLastAccessedDetail", OutputListKey: "ServicesLastAccessed", OutputItemKey: "Error"}, + "GetServiceLastAccessedDetailsWithEntities": {Verb: "Get", Resource: "ServiceLastAccessedDetailsWithEntity", OutputListKey: "EntityDetailsList", OutputItemKey: "Error"}, + "GetServiceLinkedRoleDeletionStatus": {Verb: "Get", Resource: "ServiceLinkedRoleDeletionStatu", OutputListKey: "", OutputItemKey: "Reason"}, + "GetUser": {Verb: "Get", Resource: "User", OutputListKey: "", OutputItemKey: "User"}, + "GetUserPolicy": {Verb: "Get", Resource: "UserPolicy", OutputListKey: "", OutputItemKey: ""}, + "ListAccessKeys": {Verb: "List", Resource: "AccessKey", OutputListKey: "AccessKeyMetadata", OutputItemKey: ""}, + "ListAccountAliases": {Verb: "List", Resource: "AccountAliase", OutputListKey: "AccountAliases", OutputItemKey: ""}, + "ListAttachedGroupPolicies": {Verb: "List", Resource: "AttachedGroupPolicy", OutputListKey: "AttachedPolicies", OutputItemKey: ""}, + "ListAttachedRolePolicies": {Verb: "List", Resource: "AttachedRolePolicy", OutputListKey: "AttachedPolicies", OutputItemKey: ""}, + "ListAttachedUserPolicies": {Verb: "List", Resource: "AttachedUserPolicy", OutputListKey: "AttachedPolicies", OutputItemKey: ""}, + "ListDelegationRequests": {Verb: "List", Resource: "DelegationRequest", OutputListKey: "DelegationRequests", OutputItemKey: ""}, + "ListEntitiesForPolicy": {Verb: "List", Resource: "EntitiesForPolicy", OutputListKey: "PolicyGroups", OutputItemKey: ""}, + "ListGroupPolicies": {Verb: "List", Resource: "GroupPolicy", OutputListKey: "PolicyNames", OutputItemKey: ""}, + "ListGroups": {Verb: "List", Resource: "Group", OutputListKey: "Groups", OutputItemKey: ""}, + "ListGroupsForUser": {Verb: "List", Resource: "GroupsForUser", OutputListKey: "Groups", OutputItemKey: ""}, + "ListInstanceProfileTags": {Verb: "List", Resource: "InstanceProfileTag", OutputListKey: "Tags", OutputItemKey: ""}, + "ListInstanceProfiles": {Verb: "List", Resource: "InstanceProfile", OutputListKey: "InstanceProfiles", OutputItemKey: ""}, + "ListInstanceProfilesForRole": {Verb: "List", Resource: "InstanceProfilesForRole", OutputListKey: "InstanceProfiles", OutputItemKey: ""}, + "ListMFADeviceTags": {Verb: "List", Resource: "MFADeviceTag", OutputListKey: "Tags", OutputItemKey: ""}, + "ListMFADevices": {Verb: "List", Resource: "MFADevice", OutputListKey: "MFADevices", OutputItemKey: ""}, + "ListOpenIDConnectProviderTags": {Verb: "List", Resource: "OpenIDConnectProviderTag", OutputListKey: "Tags", OutputItemKey: ""}, + "ListOpenIDConnectProviders": {Verb: "List", Resource: "OpenIDConnectProvider", OutputListKey: "OpenIDConnectProviderList", OutputItemKey: ""}, + "ListOrganizationsFeatures": {Verb: "List", Resource: "OrganizationsFeature", OutputListKey: "EnabledFeatures", OutputItemKey: ""}, + "ListPolicies": {Verb: "List", Resource: "Policy", OutputListKey: "Policies", OutputItemKey: ""}, + "ListPoliciesGrantingServiceAccess": {Verb: "List", Resource: "PoliciesGrantingServiceAccess", OutputListKey: "PoliciesGrantingServiceAccess", OutputItemKey: ""}, + "ListPolicyTags": {Verb: "List", Resource: "PolicyTag", OutputListKey: "Tags", OutputItemKey: ""}, + "ListPolicyVersions": {Verb: "List", Resource: "PolicyVersion", OutputListKey: "Versions", OutputItemKey: ""}, + "ListRolePolicies": {Verb: "List", Resource: "RolePolicy", OutputListKey: "PolicyNames", OutputItemKey: ""}, + "ListRoleTags": {Verb: "List", Resource: "RoleTag", OutputListKey: "Tags", OutputItemKey: ""}, + "ListRoles": {Verb: "List", Resource: "Role", OutputListKey: "Roles", OutputItemKey: ""}, + "ListSAMLProviderTags": {Verb: "List", Resource: "SAMLProviderTag", OutputListKey: "Tags", OutputItemKey: ""}, + "ListSAMLProviders": {Verb: "List", Resource: "SAMLProvider", OutputListKey: "SAMLProviderList", OutputItemKey: ""}, + "ListSSHPublicKeys": {Verb: "List", Resource: "SSHPublicKey", OutputListKey: "SSHPublicKeys", OutputItemKey: ""}, + "ListServerCertificateTags": {Verb: "List", Resource: "ServerCertificateTag", OutputListKey: "Tags", OutputItemKey: ""}, + "ListServerCertificates": {Verb: "List", Resource: "ServerCertificate", OutputListKey: "ServerCertificateMetadataList", OutputItemKey: ""}, + "ListServiceSpecificCredentials": {Verb: "List", Resource: "ServiceSpecificCredential", OutputListKey: "ServiceSpecificCredentials", OutputItemKey: ""}, + "ListSigningCertificates": {Verb: "List", Resource: "SigningCertificate", OutputListKey: "Certificates", OutputItemKey: ""}, + "ListUserPolicies": {Verb: "List", Resource: "UserPolicy", OutputListKey: "PolicyNames", OutputItemKey: ""}, + "ListUserTags": {Verb: "List", Resource: "UserTag", OutputListKey: "Tags", OutputItemKey: ""}, + "ListUsers": {Verb: "List", Resource: "User", OutputListKey: "Users", OutputItemKey: ""}, + "ListVirtualMFADevices": {Verb: "List", Resource: "VirtualMFADevice", OutputListKey: "VirtualMFADevices", OutputItemKey: ""}, + "PutGroupPolicy": {Verb: "Update", Resource: "GroupPolicy", OutputListKey: "", OutputItemKey: ""}, + "PutRolePermissionsBoundary": {Verb: "Update", Resource: "RolePermissionsBoundary", OutputListKey: "", OutputItemKey: ""}, + "PutRolePolicy": {Verb: "Update", Resource: "RolePolicy", OutputListKey: "", OutputItemKey: ""}, + "PutUserPermissionsBoundary": {Verb: "Update", Resource: "UserPermissionsBoundary", OutputListKey: "", OutputItemKey: ""}, + "PutUserPolicy": {Verb: "Update", Resource: "UserPolicy", OutputListKey: "", OutputItemKey: ""}, + "TagInstanceProfile": {Verb: "Tag", Resource: "InstanceProfile", OutputListKey: "", OutputItemKey: ""}, + "TagMFADevice": {Verb: "Tag", Resource: "MFADevice", OutputListKey: "", OutputItemKey: ""}, + "TagOpenIDConnectProvider": {Verb: "Tag", Resource: "OpenIDConnectProvider", OutputListKey: "", OutputItemKey: ""}, + "TagPolicy": {Verb: "Tag", Resource: "Policy", OutputListKey: "", OutputItemKey: ""}, + "TagRole": {Verb: "Tag", Resource: "Role", OutputListKey: "", OutputItemKey: ""}, + "TagSAMLProvider": {Verb: "Tag", Resource: "SAMLProvider", OutputListKey: "", OutputItemKey: ""}, + "TagServerCertificate": {Verb: "Tag", Resource: "ServerCertificate", OutputListKey: "", OutputItemKey: ""}, + "TagUser": {Verb: "Tag", Resource: "User", OutputListKey: "", OutputItemKey: ""}, + "UntagInstanceProfile": {Verb: "Untag", Resource: "InstanceProfile", OutputListKey: "", OutputItemKey: ""}, + "UntagMFADevice": {Verb: "Untag", Resource: "MFADevice", OutputListKey: "", OutputItemKey: ""}, + "UntagOpenIDConnectProvider": {Verb: "Untag", Resource: "OpenIDConnectProvider", OutputListKey: "", OutputItemKey: ""}, + "UntagPolicy": {Verb: "Untag", Resource: "Policy", OutputListKey: "", OutputItemKey: ""}, + "UntagRole": {Verb: "Untag", Resource: "Role", OutputListKey: "", OutputItemKey: ""}, + "UntagSAMLProvider": {Verb: "Untag", Resource: "SAMLProvider", OutputListKey: "", OutputItemKey: ""}, + "UntagServerCertificate": {Verb: "Untag", Resource: "ServerCertificate", OutputListKey: "", OutputItemKey: ""}, + "UntagUser": {Verb: "Untag", Resource: "User", OutputListKey: "", OutputItemKey: ""}, + "UpdateAccessKey": {Verb: "Update", Resource: "AccessKey", OutputListKey: "", OutputItemKey: ""}, + "UpdateAccountPasswordPolicy": {Verb: "Update", Resource: "AccountPasswordPolicy", OutputListKey: "", OutputItemKey: ""}, + "UpdateAssumeRolePolicy": {Verb: "Update", Resource: "AssumeRolePolicy", OutputListKey: "", OutputItemKey: ""}, + "UpdateDelegationRequest": {Verb: "Update", Resource: "DelegationRequest", OutputListKey: "", OutputItemKey: ""}, + "UpdateGroup": {Verb: "Update", Resource: "Group", OutputListKey: "", OutputItemKey: ""}, + "UpdateLoginProfile": {Verb: "Update", Resource: "LoginProfile", OutputListKey: "", OutputItemKey: ""}, + "UpdateOpenIDConnectProviderThumbprint": {Verb: "Update", Resource: "OpenIDConnectProviderThumbprint", OutputListKey: "", OutputItemKey: ""}, + "UpdateRole": {Verb: "Update", Resource: "Role", OutputListKey: "", OutputItemKey: ""}, + "UpdateRoleDescription": {Verb: "Update", Resource: "RoleDescription", OutputListKey: "", OutputItemKey: "Role"}, + "UpdateSAMLProvider": {Verb: "Update", Resource: "SAMLProvider", OutputListKey: "", OutputItemKey: ""}, + "UpdateSSHPublicKey": {Verb: "Update", Resource: "SSHPublicKey", OutputListKey: "", OutputItemKey: ""}, + "UpdateServerCertificate": {Verb: "Update", Resource: "ServerCertificate", OutputListKey: "", OutputItemKey: ""}, + "UpdateServiceSpecificCredential": {Verb: "Update", Resource: "ServiceSpecificCredential", OutputListKey: "", OutputItemKey: ""}, + "UpdateSigningCertificate": {Verb: "Update", Resource: "SigningCertificate", OutputListKey: "", OutputItemKey: ""}, + "UpdateUser": {Verb: "Update", Resource: "User", OutputListKey: "", OutputItemKey: ""}, + }) crud.Register("inspector2", map[string]crud.OpMeta{ "BatchGetAccountStatus": {Verb: "List", Resource: "AccountStatu", OutputListKey: "accounts", OutputItemKey: "", Method: "POST", URI: "/status/batch/get"}, "BatchGetCodeSnippet": {Verb: "List", Resource: "CodeSnippet", OutputListKey: "codeSnippetResults", OutputItemKey: "", Method: "POST", URI: "/codesnippet/batchget"}, @@ -5381,6 +5845,56 @@ func init() { "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("neptune", map[string]crud.OpMeta{ + "CreateDBCluster": {Verb: "Create", Resource: "DBCluster", OutputListKey: "", OutputItemKey: "DBCluster"}, + "CreateDBClusterEndpoint": {Verb: "Create", Resource: "DBClusterEndpoint", OutputListKey: "ExcludedMembers", OutputItemKey: ""}, + "CreateDBClusterParameterGroup": {Verb: "Create", Resource: "DBClusterParameterGroup", OutputListKey: "", OutputItemKey: "DBClusterParameterGroup"}, + "CreateDBClusterSnapshot": {Verb: "Create", Resource: "DBClusterSnapshot", OutputListKey: "", OutputItemKey: "DBClusterSnapshot"}, + "CreateDBInstance": {Verb: "Create", Resource: "DBInstance", OutputListKey: "", OutputItemKey: "DBInstance"}, + "CreateDBParameterGroup": {Verb: "Create", Resource: "DBParameterGroup", OutputListKey: "", OutputItemKey: "DBParameterGroup"}, + "CreateDBSubnetGroup": {Verb: "Create", Resource: "DBSubnetGroup", OutputListKey: "", OutputItemKey: "DBSubnetGroup"}, + "CreateEventSubscription": {Verb: "Create", Resource: "EventSubscription", OutputListKey: "", OutputItemKey: "EventSubscription"}, + "CreateGlobalCluster": {Verb: "Create", Resource: "GlobalCluster", OutputListKey: "", OutputItemKey: "GlobalCluster"}, + "DeleteDBCluster": {Verb: "Delete", Resource: "DBCluster", OutputListKey: "", OutputItemKey: "DBCluster"}, + "DeleteDBClusterEndpoint": {Verb: "Delete", Resource: "DBClusterEndpoint", OutputListKey: "ExcludedMembers", OutputItemKey: ""}, + "DeleteDBClusterParameterGroup": {Verb: "Delete", Resource: "DBClusterParameterGroup", OutputListKey: "", OutputItemKey: ""}, + "DeleteDBClusterSnapshot": {Verb: "Delete", Resource: "DBClusterSnapshot", OutputListKey: "", OutputItemKey: "DBClusterSnapshot"}, + "DeleteDBInstance": {Verb: "Delete", Resource: "DBInstance", OutputListKey: "", OutputItemKey: "DBInstance"}, + "DeleteDBParameterGroup": {Verb: "Delete", Resource: "DBParameterGroup", OutputListKey: "", OutputItemKey: ""}, + "DeleteDBSubnetGroup": {Verb: "Delete", Resource: "DBSubnetGroup", OutputListKey: "", OutputItemKey: ""}, + "DeleteEventSubscription": {Verb: "Delete", Resource: "EventSubscription", OutputListKey: "", OutputItemKey: "EventSubscription"}, + "DeleteGlobalCluster": {Verb: "Delete", Resource: "GlobalCluster", OutputListKey: "", OutputItemKey: "GlobalCluster"}, + "DescribeDBClusterEndpoints": {Verb: "Get", Resource: "DBClusterEndpoint", OutputListKey: "DBClusterEndpoints", OutputItemKey: ""}, + "DescribeDBClusterParameterGroups": {Verb: "Get", Resource: "DBClusterParameterGroup", OutputListKey: "DBClusterParameterGroups", OutputItemKey: ""}, + "DescribeDBClusterParameters": {Verb: "Get", Resource: "DBClusterParameter", OutputListKey: "Parameters", OutputItemKey: ""}, + "DescribeDBClusterSnapshotAttributes": {Verb: "Get", Resource: "DBClusterSnapshotAttribute", OutputListKey: "", OutputItemKey: "DBClusterSnapshotAttributesResult"}, + "DescribeDBClusterSnapshots": {Verb: "Get", Resource: "DBClusterSnapshot", OutputListKey: "DBClusterSnapshots", OutputItemKey: ""}, + "DescribeDBClusters": {Verb: "Get", Resource: "DBCluster", OutputListKey: "DBClusters", OutputItemKey: ""}, + "DescribeDBEngineVersions": {Verb: "Get", Resource: "DBEngineVersion", OutputListKey: "DBEngineVersions", OutputItemKey: ""}, + "DescribeDBInstances": {Verb: "Get", Resource: "DBInstance", OutputListKey: "DBInstances", OutputItemKey: ""}, + "DescribeDBParameterGroups": {Verb: "Get", Resource: "DBParameterGroup", OutputListKey: "DBParameterGroups", OutputItemKey: ""}, + "DescribeDBParameters": {Verb: "Get", Resource: "DBParameter", OutputListKey: "Parameters", OutputItemKey: ""}, + "DescribeDBSubnetGroups": {Verb: "Get", Resource: "DBSubnetGroup", OutputListKey: "DBSubnetGroups", OutputItemKey: ""}, + "DescribeEngineDefaultClusterParameters": {Verb: "Get", Resource: "EngineDefaultClusterParameter", OutputListKey: "", OutputItemKey: "EngineDefaults"}, + "DescribeEngineDefaultParameters": {Verb: "Get", Resource: "EngineDefaultParameter", OutputListKey: "", OutputItemKey: "EngineDefaults"}, + "DescribeEventCategories": {Verb: "Get", Resource: "EventCategory", OutputListKey: "EventCategoriesMapList", OutputItemKey: ""}, + "DescribeEventSubscriptions": {Verb: "Get", Resource: "EventSubscription", OutputListKey: "EventSubscriptionsList", OutputItemKey: ""}, + "DescribeEvents": {Verb: "Get", Resource: "Event", OutputListKey: "Events", OutputItemKey: ""}, + "DescribeGlobalClusters": {Verb: "Get", Resource: "GlobalCluster", OutputListKey: "GlobalClusters", OutputItemKey: ""}, + "DescribeOrderableDBInstanceOptions": {Verb: "Get", Resource: "OrderableDBInstanceOption", OutputListKey: "OrderableDBInstanceOptions", OutputItemKey: ""}, + "DescribePendingMaintenanceActions": {Verb: "Get", Resource: "PendingMaintenanceAction", OutputListKey: "PendingMaintenanceActions", OutputItemKey: ""}, + "DescribeValidDBInstanceModifications": {Verb: "Get", Resource: "ValidDBInstanceModification", OutputListKey: "", OutputItemKey: "ValidDBInstanceModificationsMessage"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "TagList", OutputItemKey: ""}, + "ModifyDBCluster": {Verb: "Update", Resource: "DBCluster", OutputListKey: "", OutputItemKey: "DBCluster"}, + "ModifyDBClusterEndpoint": {Verb: "Update", Resource: "DBClusterEndpoint", OutputListKey: "ExcludedMembers", OutputItemKey: ""}, + "ModifyDBClusterParameterGroup": {Verb: "Update", Resource: "DBClusterParameterGroup", OutputListKey: "", OutputItemKey: ""}, + "ModifyDBClusterSnapshotAttribute": {Verb: "Update", Resource: "DBClusterSnapshotAttribute", OutputListKey: "", OutputItemKey: "DBClusterSnapshotAttributesResult"}, + "ModifyDBInstance": {Verb: "Update", Resource: "DBInstance", OutputListKey: "", OutputItemKey: "DBInstance"}, + "ModifyDBParameterGroup": {Verb: "Update", Resource: "DBParameterGroup", OutputListKey: "", OutputItemKey: ""}, + "ModifyDBSubnetGroup": {Verb: "Update", Resource: "DBSubnetGroup", OutputListKey: "", OutputItemKey: "DBSubnetGroup"}, + "ModifyEventSubscription": {Verb: "Update", Resource: "EventSubscription", OutputListKey: "", OutputItemKey: "EventSubscription"}, + "ModifyGlobalCluster": {Verb: "Update", Resource: "GlobalCluster", OutputListKey: "", OutputItemKey: "GlobalCluster"}, + }) crud.Register("networkfirewall", map[string]crud.OpMeta{ "CreateContainerAssociation": {Verb: "Create", Resource: "ContainerAssociation", OutputListKey: "ContainerMonitoringConfigurations", OutputItemKey: ""}, "CreateFirewall": {Verb: "Create", Resource: "Firewall", OutputListKey: "", OutputItemKey: "Firewall"}, @@ -6446,6 +6960,233 @@ func init() { "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("rds", map[string]crud.OpMeta{ + "CreateBlueGreenDeployment": {Verb: "Create", Resource: "BlueGreenDeployment", OutputListKey: "", OutputItemKey: "BlueGreenDeployment"}, + "CreateCustomDBEngineVersion": {Verb: "Create", Resource: "CustomDBEngineVersion", OutputListKey: "DatabaseInstallationFiles", OutputItemKey: "DefaultCharacterSet"}, + "CreateDBCluster": {Verb: "Create", Resource: "DBCluster", OutputListKey: "", OutputItemKey: "DBCluster"}, + "CreateDBClusterEndpoint": {Verb: "Create", Resource: "DBClusterEndpoint", OutputListKey: "ExcludedMembers", OutputItemKey: ""}, + "CreateDBClusterParameterGroup": {Verb: "Create", Resource: "DBClusterParameterGroup", OutputListKey: "", OutputItemKey: "DBClusterParameterGroup"}, + "CreateDBClusterSnapshot": {Verb: "Create", Resource: "DBClusterSnapshot", OutputListKey: "", OutputItemKey: "DBClusterSnapshot"}, + "CreateDBInstance": {Verb: "Create", Resource: "DBInstance", OutputListKey: "", OutputItemKey: "DBInstance"}, + "CreateDBInstanceReadReplica": {Verb: "Create", Resource: "DBInstanceReadReplica", OutputListKey: "", OutputItemKey: "DBInstance"}, + "CreateDBParameterGroup": {Verb: "Create", Resource: "DBParameterGroup", OutputListKey: "", OutputItemKey: "DBParameterGroup"}, + "CreateDBProxy": {Verb: "Create", Resource: "DBProxy", OutputListKey: "", OutputItemKey: "DBProxy"}, + "CreateDBProxyEndpoint": {Verb: "Create", Resource: "DBProxyEndpoint", OutputListKey: "", OutputItemKey: "DBProxyEndpoint"}, + "CreateDBSecurityGroup": {Verb: "Create", Resource: "DBSecurityGroup", OutputListKey: "", OutputItemKey: "DBSecurityGroup"}, + "CreateDBShardGroup": {Verb: "Create", Resource: "DBShardGroup", OutputListKey: "TagList", OutputItemKey: ""}, + "CreateDBSnapshot": {Verb: "Create", Resource: "DBSnapshot", OutputListKey: "", OutputItemKey: "DBSnapshot"}, + "CreateDBSubnetGroup": {Verb: "Create", Resource: "DBSubnetGroup", OutputListKey: "", OutputItemKey: "DBSubnetGroup"}, + "CreateEventSubscription": {Verb: "Create", Resource: "EventSubscription", OutputListKey: "", OutputItemKey: "EventSubscription"}, + "CreateGlobalCluster": {Verb: "Create", Resource: "GlobalCluster", OutputListKey: "", OutputItemKey: "GlobalCluster"}, + "CreateIntegration": {Verb: "Create", Resource: "Integration", OutputListKey: "Errors", OutputItemKey: ""}, + "CreateOptionGroup": {Verb: "Create", Resource: "OptionGroup", OutputListKey: "", OutputItemKey: "OptionGroup"}, + "CreateTenantDatabase": {Verb: "Create", Resource: "TenantDatabase", OutputListKey: "", OutputItemKey: "TenantDatabase"}, + "DeleteBlueGreenDeployment": {Verb: "Delete", Resource: "BlueGreenDeployment", OutputListKey: "", OutputItemKey: "BlueGreenDeployment"}, + "DeleteCustomDBEngineVersion": {Verb: "Delete", Resource: "CustomDBEngineVersion", OutputListKey: "DatabaseInstallationFiles", OutputItemKey: "DefaultCharacterSet"}, + "DeleteDBCluster": {Verb: "Delete", Resource: "DBCluster", OutputListKey: "", OutputItemKey: "DBCluster"}, + "DeleteDBClusterAutomatedBackup": {Verb: "Delete", Resource: "DBClusterAutomatedBackup", OutputListKey: "", OutputItemKey: "DBClusterAutomatedBackup"}, + "DeleteDBClusterEndpoint": {Verb: "Delete", Resource: "DBClusterEndpoint", OutputListKey: "ExcludedMembers", OutputItemKey: ""}, + "DeleteDBClusterParameterGroup": {Verb: "Delete", Resource: "DBClusterParameterGroup", OutputListKey: "", OutputItemKey: ""}, + "DeleteDBClusterSnapshot": {Verb: "Delete", Resource: "DBClusterSnapshot", OutputListKey: "", OutputItemKey: "DBClusterSnapshot"}, + "DeleteDBInstance": {Verb: "Delete", Resource: "DBInstance", OutputListKey: "", OutputItemKey: "DBInstance"}, + "DeleteDBInstanceAutomatedBackup": {Verb: "Delete", Resource: "DBInstanceAutomatedBackup", OutputListKey: "", OutputItemKey: "DBInstanceAutomatedBackup"}, + "DeleteDBParameterGroup": {Verb: "Delete", Resource: "DBParameterGroup", OutputListKey: "", OutputItemKey: ""}, + "DeleteDBProxy": {Verb: "Delete", Resource: "DBProxy", OutputListKey: "", OutputItemKey: "DBProxy"}, + "DeleteDBProxyEndpoint": {Verb: "Delete", Resource: "DBProxyEndpoint", OutputListKey: "", OutputItemKey: "DBProxyEndpoint"}, + "DeleteDBSecurityGroup": {Verb: "Delete", Resource: "DBSecurityGroup", OutputListKey: "", OutputItemKey: ""}, + "DeleteDBShardGroup": {Verb: "Delete", Resource: "DBShardGroup", OutputListKey: "TagList", OutputItemKey: ""}, + "DeleteDBSnapshot": {Verb: "Delete", Resource: "DBSnapshot", OutputListKey: "", OutputItemKey: "DBSnapshot"}, + "DeleteDBSubnetGroup": {Verb: "Delete", Resource: "DBSubnetGroup", OutputListKey: "", OutputItemKey: ""}, + "DeleteEventSubscription": {Verb: "Delete", Resource: "EventSubscription", OutputListKey: "", OutputItemKey: "EventSubscription"}, + "DeleteGlobalCluster": {Verb: "Delete", Resource: "GlobalCluster", OutputListKey: "", OutputItemKey: "GlobalCluster"}, + "DeleteIntegration": {Verb: "Delete", Resource: "Integration", OutputListKey: "Errors", OutputItemKey: ""}, + "DeleteOptionGroup": {Verb: "Delete", Resource: "OptionGroup", OutputListKey: "", OutputItemKey: ""}, + "DeleteTenantDatabase": {Verb: "Delete", Resource: "TenantDatabase", OutputListKey: "", OutputItemKey: "TenantDatabase"}, + "DeregisterDBProxyTargets": {Verb: "Delete", Resource: "DBProxyTarget", OutputListKey: "", OutputItemKey: ""}, + "DescribeAccountAttributes": {Verb: "Get", Resource: "AccountAttribute", OutputListKey: "AccountQuotas", OutputItemKey: ""}, + "DescribeBlueGreenDeployments": {Verb: "Get", Resource: "BlueGreenDeployment", OutputListKey: "BlueGreenDeployments", OutputItemKey: ""}, + "DescribeCertificates": {Verb: "Get", Resource: "Certificate", OutputListKey: "Certificates", OutputItemKey: ""}, + "DescribeDBClusterAutomatedBackups": {Verb: "Get", Resource: "DBClusterAutomatedBackup", OutputListKey: "DBClusterAutomatedBackups", OutputItemKey: ""}, + "DescribeDBClusterBacktracks": {Verb: "Get", Resource: "DBClusterBacktrack", OutputListKey: "DBClusterBacktracks", OutputItemKey: ""}, + "DescribeDBClusterEndpoints": {Verb: "Get", Resource: "DBClusterEndpoint", OutputListKey: "DBClusterEndpoints", OutputItemKey: ""}, + "DescribeDBClusterParameterGroups": {Verb: "Get", Resource: "DBClusterParameterGroup", OutputListKey: "DBClusterParameterGroups", OutputItemKey: ""}, + "DescribeDBClusterParameters": {Verb: "Get", Resource: "DBClusterParameter", OutputListKey: "Parameters", OutputItemKey: ""}, + "DescribeDBClusterSnapshotAttributes": {Verb: "Get", Resource: "DBClusterSnapshotAttribute", OutputListKey: "", OutputItemKey: "DBClusterSnapshotAttributesResult"}, + "DescribeDBClusterSnapshots": {Verb: "Get", Resource: "DBClusterSnapshot", OutputListKey: "DBClusterSnapshots", OutputItemKey: ""}, + "DescribeDBClusters": {Verb: "Get", Resource: "DBCluster", OutputListKey: "DBClusters", OutputItemKey: ""}, + "DescribeDBEngineVersions": {Verb: "Get", Resource: "DBEngineVersion", OutputListKey: "DBEngineVersions", OutputItemKey: ""}, + "DescribeDBInstanceAutomatedBackups": {Verb: "Get", Resource: "DBInstanceAutomatedBackup", OutputListKey: "DBInstanceAutomatedBackups", OutputItemKey: ""}, + "DescribeDBInstances": {Verb: "Get", Resource: "DBInstance", OutputListKey: "DBInstances", OutputItemKey: ""}, + "DescribeDBLogFiles": {Verb: "Get", Resource: "DBLogFile", OutputListKey: "DescribeDBLogFiles", OutputItemKey: ""}, + "DescribeDBMajorEngineVersions": {Verb: "Get", Resource: "DBMajorEngineVersion", OutputListKey: "DBMajorEngineVersions", OutputItemKey: ""}, + "DescribeDBParameterGroups": {Verb: "Get", Resource: "DBParameterGroup", OutputListKey: "DBParameterGroups", OutputItemKey: ""}, + "DescribeDBParameters": {Verb: "Get", Resource: "DBParameter", OutputListKey: "Parameters", OutputItemKey: ""}, + "DescribeDBProxies": {Verb: "Get", Resource: "DBProxy", OutputListKey: "DBProxies", OutputItemKey: ""}, + "DescribeDBProxyEndpoints": {Verb: "Get", Resource: "DBProxyEndpoint", OutputListKey: "DBProxyEndpoints", OutputItemKey: ""}, + "DescribeDBProxyTargetGroups": {Verb: "Get", Resource: "DBProxyTargetGroup", OutputListKey: "TargetGroups", OutputItemKey: ""}, + "DescribeDBProxyTargets": {Verb: "Get", Resource: "DBProxyTarget", OutputListKey: "Targets", OutputItemKey: ""}, + "DescribeDBRecommendations": {Verb: "Get", Resource: "DBRecommendation", OutputListKey: "DBRecommendations", OutputItemKey: ""}, + "DescribeDBSecurityGroups": {Verb: "Get", Resource: "DBSecurityGroup", OutputListKey: "DBSecurityGroups", OutputItemKey: ""}, + "DescribeDBShardGroups": {Verb: "Get", Resource: "DBShardGroup", OutputListKey: "DBShardGroups", OutputItemKey: ""}, + "DescribeDBSnapshotAttributes": {Verb: "Get", Resource: "DBSnapshotAttribute", OutputListKey: "", OutputItemKey: "DBSnapshotAttributesResult"}, + "DescribeDBSnapshotTenantDatabases": {Verb: "Get", Resource: "DBSnapshotTenantDatabase", OutputListKey: "DBSnapshotTenantDatabases", OutputItemKey: ""}, + "DescribeDBSnapshots": {Verb: "Get", Resource: "DBSnapshot", OutputListKey: "DBSnapshots", OutputItemKey: ""}, + "DescribeDBSubnetGroups": {Verb: "Get", Resource: "DBSubnetGroup", OutputListKey: "DBSubnetGroups", OutputItemKey: ""}, + "DescribeEngineDefaultClusterParameters": {Verb: "Get", Resource: "EngineDefaultClusterParameter", OutputListKey: "", OutputItemKey: "EngineDefaults"}, + "DescribeEngineDefaultParameters": {Verb: "Get", Resource: "EngineDefaultParameter", OutputListKey: "", OutputItemKey: "EngineDefaults"}, + "DescribeEventCategories": {Verb: "Get", Resource: "EventCategory", OutputListKey: "EventCategoriesMapList", OutputItemKey: ""}, + "DescribeEventSubscriptions": {Verb: "Get", Resource: "EventSubscription", OutputListKey: "EventSubscriptionsList", OutputItemKey: ""}, + "DescribeEvents": {Verb: "Get", Resource: "Event", OutputListKey: "Events", OutputItemKey: ""}, + "DescribeExportTasks": {Verb: "Get", Resource: "ExportTask", OutputListKey: "ExportTasks", OutputItemKey: ""}, + "DescribeGlobalClusters": {Verb: "Get", Resource: "GlobalCluster", OutputListKey: "GlobalClusters", OutputItemKey: ""}, + "DescribeIntegrations": {Verb: "Get", Resource: "Integration", OutputListKey: "Integrations", OutputItemKey: ""}, + "DescribeOptionGroupOptions": {Verb: "Get", Resource: "OptionGroupOption", OutputListKey: "OptionGroupOptions", OutputItemKey: ""}, + "DescribeOptionGroups": {Verb: "Get", Resource: "OptionGroup", OutputListKey: "OptionGroupsList", OutputItemKey: ""}, + "DescribeOrderableDBInstanceOptions": {Verb: "Get", Resource: "OrderableDBInstanceOption", OutputListKey: "OrderableDBInstanceOptions", OutputItemKey: ""}, + "DescribePendingMaintenanceActions": {Verb: "Get", Resource: "PendingMaintenanceAction", OutputListKey: "PendingMaintenanceActions", OutputItemKey: ""}, + "DescribeReservedDBInstances": {Verb: "Get", Resource: "ReservedDBInstance", OutputListKey: "ReservedDBInstances", OutputItemKey: ""}, + "DescribeReservedDBInstancesOfferings": {Verb: "Get", Resource: "ReservedDBInstancesOffering", OutputListKey: "ReservedDBInstancesOfferings", OutputItemKey: ""}, + "DescribeSourceRegions": {Verb: "Get", Resource: "SourceRegion", OutputListKey: "SourceRegions", OutputItemKey: ""}, + "DescribeTenantDatabases": {Verb: "Get", Resource: "TenantDatabase", OutputListKey: "TenantDatabases", OutputItemKey: ""}, + "DescribeValidDBInstanceModifications": {Verb: "Get", Resource: "ValidDBInstanceModification", OutputListKey: "", OutputItemKey: "ValidDBInstanceModificationsMessage"}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "TagList", OutputItemKey: ""}, + "ModifyActivityStream": {Verb: "Update", Resource: "ActivityStream", OutputListKey: "", OutputItemKey: ""}, + "ModifyCertificates": {Verb: "Update", Resource: "Certificate", OutputListKey: "", OutputItemKey: "Certificate"}, + "ModifyCurrentDBClusterCapacity": {Verb: "Update", Resource: "CurrentDBClusterCapacity", OutputListKey: "", OutputItemKey: ""}, + "ModifyCustomDBEngineVersion": {Verb: "Update", Resource: "CustomDBEngineVersion", OutputListKey: "DatabaseInstallationFiles", OutputItemKey: "DefaultCharacterSet"}, + "ModifyDBCluster": {Verb: "Update", Resource: "DBCluster", OutputListKey: "", OutputItemKey: "DBCluster"}, + "ModifyDBClusterEndpoint": {Verb: "Update", Resource: "DBClusterEndpoint", OutputListKey: "ExcludedMembers", OutputItemKey: ""}, + "ModifyDBClusterParameterGroup": {Verb: "Update", Resource: "DBClusterParameterGroup", OutputListKey: "", OutputItemKey: ""}, + "ModifyDBClusterSnapshotAttribute": {Verb: "Update", Resource: "DBClusterSnapshotAttribute", OutputListKey: "", OutputItemKey: "DBClusterSnapshotAttributesResult"}, + "ModifyDBInstance": {Verb: "Update", Resource: "DBInstance", OutputListKey: "", OutputItemKey: "DBInstance"}, + "ModifyDBParameterGroup": {Verb: "Update", Resource: "DBParameterGroup", OutputListKey: "", OutputItemKey: ""}, + "ModifyDBProxy": {Verb: "Update", Resource: "DBProxy", OutputListKey: "", OutputItemKey: "DBProxy"}, + "ModifyDBProxyEndpoint": {Verb: "Update", Resource: "DBProxyEndpoint", OutputListKey: "", OutputItemKey: "DBProxyEndpoint"}, + "ModifyDBProxyTargetGroup": {Verb: "Update", Resource: "DBProxyTargetGroup", OutputListKey: "", OutputItemKey: "DBProxyTargetGroup"}, + "ModifyDBRecommendation": {Verb: "Update", Resource: "DBRecommendation", OutputListKey: "", OutputItemKey: "DBRecommendation"}, + "ModifyDBShardGroup": {Verb: "Update", Resource: "DBShardGroup", OutputListKey: "TagList", OutputItemKey: ""}, + "ModifyDBSnapshot": {Verb: "Update", Resource: "DBSnapshot", OutputListKey: "", OutputItemKey: "DBSnapshot"}, + "ModifyDBSnapshotAttribute": {Verb: "Update", Resource: "DBSnapshotAttribute", OutputListKey: "", OutputItemKey: "DBSnapshotAttributesResult"}, + "ModifyDBSubnetGroup": {Verb: "Update", Resource: "DBSubnetGroup", OutputListKey: "", OutputItemKey: "DBSubnetGroup"}, + "ModifyEventSubscription": {Verb: "Update", Resource: "EventSubscription", OutputListKey: "", OutputItemKey: "EventSubscription"}, + "ModifyGlobalCluster": {Verb: "Update", Resource: "GlobalCluster", OutputListKey: "", OutputItemKey: "GlobalCluster"}, + "ModifyIntegration": {Verb: "Update", Resource: "Integration", OutputListKey: "Errors", OutputItemKey: ""}, + "ModifyOptionGroup": {Verb: "Update", Resource: "OptionGroup", OutputListKey: "", OutputItemKey: "OptionGroup"}, + "ModifyTenantDatabase": {Verb: "Update", Resource: "TenantDatabase", OutputListKey: "", OutputItemKey: "TenantDatabase"}, + "RegisterDBProxyTargets": {Verb: "Create", Resource: "DBProxyTarget", OutputListKey: "DBProxyTargets", OutputItemKey: ""}, + }) + crud.Register("redshift", map[string]crud.OpMeta{ + "CreateAuthenticationProfile": {Verb: "Create", Resource: "AuthenticationProfile", OutputListKey: "", OutputItemKey: ""}, + "CreateCluster": {Verb: "Create", Resource: "Cluster", OutputListKey: "", OutputItemKey: "Cluster"}, + "CreateClusterParameterGroup": {Verb: "Create", Resource: "ClusterParameterGroup", OutputListKey: "", OutputItemKey: "ClusterParameterGroup"}, + "CreateClusterSecurityGroup": {Verb: "Create", Resource: "ClusterSecurityGroup", OutputListKey: "", OutputItemKey: "ClusterSecurityGroup"}, + "CreateClusterSnapshot": {Verb: "Create", Resource: "ClusterSnapshot", OutputListKey: "", OutputItemKey: "Snapshot"}, + "CreateClusterSubnetGroup": {Verb: "Create", Resource: "ClusterSubnetGroup", OutputListKey: "", OutputItemKey: "ClusterSubnetGroup"}, + "CreateCustomDomainAssociation": {Verb: "Create", Resource: "CustomDomainAssociation", OutputListKey: "", OutputItemKey: ""}, + "CreateEndpointAccess": {Verb: "Create", Resource: "EndpointAccess", OutputListKey: "VpcSecurityGroups", OutputItemKey: "VpcEndpoint"}, + "CreateEventSubscription": {Verb: "Create", Resource: "EventSubscription", OutputListKey: "", OutputItemKey: "EventSubscription"}, + "CreateHsmClientCertificate": {Verb: "Create", Resource: "HsmClientCertificate", OutputListKey: "", OutputItemKey: "HsmClientCertificate"}, + "CreateHsmConfiguration": {Verb: "Create", Resource: "HsmConfiguration", OutputListKey: "", OutputItemKey: "HsmConfiguration"}, + "CreateIntegration": {Verb: "Create", Resource: "Integration", OutputListKey: "Errors", OutputItemKey: ""}, + "CreateRedshiftIdcApplication": {Verb: "Create", Resource: "RedshiftIdcApplication", OutputListKey: "", OutputItemKey: "RedshiftIdcApplication"}, + "CreateScheduledAction": {Verb: "Create", Resource: "ScheduledAction", OutputListKey: "NextInvocations", OutputItemKey: "TargetAction"}, + "CreateSnapshotCopyGrant": {Verb: "Create", Resource: "SnapshotCopyGrant", OutputListKey: "", OutputItemKey: "SnapshotCopyGrant"}, + "CreateSnapshotSchedule": {Verb: "Create", Resource: "SnapshotSchedule", OutputListKey: "AssociatedClusters", OutputItemKey: ""}, + "CreateTags": {Verb: "Create", Resource: "Tag", OutputListKey: "", OutputItemKey: ""}, + "CreateUsageLimit": {Verb: "Create", Resource: "UsageLimit", OutputListKey: "Tags", OutputItemKey: ""}, + "DeleteAuthenticationProfile": {Verb: "Delete", Resource: "AuthenticationProfile", OutputListKey: "", OutputItemKey: ""}, + "DeleteCluster": {Verb: "Delete", Resource: "Cluster", OutputListKey: "", OutputItemKey: "Cluster"}, + "DeleteClusterParameterGroup": {Verb: "Delete", Resource: "ClusterParameterGroup", OutputListKey: "", OutputItemKey: ""}, + "DeleteClusterSecurityGroup": {Verb: "Delete", Resource: "ClusterSecurityGroup", OutputListKey: "", OutputItemKey: ""}, + "DeleteClusterSnapshot": {Verb: "Delete", Resource: "ClusterSnapshot", OutputListKey: "", OutputItemKey: "Snapshot"}, + "DeleteClusterSubnetGroup": {Verb: "Delete", Resource: "ClusterSubnetGroup", OutputListKey: "", OutputItemKey: ""}, + "DeleteCustomDomainAssociation": {Verb: "Delete", Resource: "CustomDomainAssociation", OutputListKey: "", OutputItemKey: ""}, + "DeleteEndpointAccess": {Verb: "Delete", Resource: "EndpointAccess", OutputListKey: "VpcSecurityGroups", OutputItemKey: "VpcEndpoint"}, + "DeleteEventSubscription": {Verb: "Delete", Resource: "EventSubscription", OutputListKey: "", OutputItemKey: ""}, + "DeleteHsmClientCertificate": {Verb: "Delete", Resource: "HsmClientCertificate", OutputListKey: "", OutputItemKey: ""}, + "DeleteHsmConfiguration": {Verb: "Delete", Resource: "HsmConfiguration", OutputListKey: "", OutputItemKey: ""}, + "DeleteIntegration": {Verb: "Delete", Resource: "Integration", OutputListKey: "Errors", OutputItemKey: ""}, + "DeletePartner": {Verb: "Delete", Resource: "Partner", OutputListKey: "", OutputItemKey: ""}, + "DeleteRedshiftIdcApplication": {Verb: "Delete", Resource: "RedshiftIdcApplication", OutputListKey: "", OutputItemKey: ""}, + "DeleteResourcePolicy": {Verb: "Delete", Resource: "ResourcePolicy", OutputListKey: "", OutputItemKey: ""}, + "DeleteScheduledAction": {Verb: "Delete", Resource: "ScheduledAction", OutputListKey: "", OutputItemKey: ""}, + "DeleteSnapshotCopyGrant": {Verb: "Delete", Resource: "SnapshotCopyGrant", OutputListKey: "", OutputItemKey: ""}, + "DeleteSnapshotSchedule": {Verb: "Delete", Resource: "SnapshotSchedule", OutputListKey: "", OutputItemKey: ""}, + "DeleteTags": {Verb: "Delete", Resource: "Tag", OutputListKey: "", OutputItemKey: ""}, + "DeleteUsageLimit": {Verb: "Delete", Resource: "UsageLimit", OutputListKey: "", OutputItemKey: ""}, + "DeregisterNamespace": {Verb: "Delete", Resource: "Namespace", OutputListKey: "", OutputItemKey: ""}, + "DescribeAccountAttributes": {Verb: "Get", Resource: "AccountAttribute", OutputListKey: "AccountAttributes", OutputItemKey: ""}, + "DescribeAuthenticationProfiles": {Verb: "Get", Resource: "AuthenticationProfile", OutputListKey: "AuthenticationProfiles", OutputItemKey: ""}, + "DescribeClusterDbRevisions": {Verb: "Get", Resource: "ClusterDbRevision", OutputListKey: "ClusterDbRevisions", OutputItemKey: ""}, + "DescribeClusterParameterGroups": {Verb: "Get", Resource: "ClusterParameterGroup", OutputListKey: "ParameterGroups", OutputItemKey: ""}, + "DescribeClusterParameters": {Verb: "Get", Resource: "ClusterParameter", OutputListKey: "Parameters", OutputItemKey: ""}, + "DescribeClusterSecurityGroups": {Verb: "Get", Resource: "ClusterSecurityGroup", OutputListKey: "ClusterSecurityGroups", OutputItemKey: ""}, + "DescribeClusterSnapshots": {Verb: "Get", Resource: "ClusterSnapshot", OutputListKey: "Snapshots", OutputItemKey: ""}, + "DescribeClusterSubnetGroups": {Verb: "Get", Resource: "ClusterSubnetGroup", OutputListKey: "ClusterSubnetGroups", OutputItemKey: ""}, + "DescribeClusterTracks": {Verb: "Get", Resource: "ClusterTrack", OutputListKey: "MaintenanceTracks", OutputItemKey: ""}, + "DescribeClusterVersions": {Verb: "Get", Resource: "ClusterVersion", OutputListKey: "ClusterVersions", OutputItemKey: ""}, + "DescribeClusters": {Verb: "Get", Resource: "Cluster", OutputListKey: "Clusters", OutputItemKey: ""}, + "DescribeCustomDomainAssociations": {Verb: "Get", Resource: "CustomDomainAssociation", OutputListKey: "Associations", OutputItemKey: ""}, + "DescribeDataShares": {Verb: "Get", Resource: "DataShare", OutputListKey: "DataShares", OutputItemKey: ""}, + "DescribeDataSharesForConsumer": {Verb: "Get", Resource: "DataSharesForConsumer", OutputListKey: "DataShares", OutputItemKey: ""}, + "DescribeDataSharesForProducer": {Verb: "Get", Resource: "DataSharesForProducer", OutputListKey: "DataShares", OutputItemKey: ""}, + "DescribeDefaultClusterParameters": {Verb: "Get", Resource: "DefaultClusterParameter", OutputListKey: "", OutputItemKey: "DefaultClusterParameters"}, + "DescribeEndpointAccess": {Verb: "Get", Resource: "EndpointAccess", OutputListKey: "EndpointAccessList", OutputItemKey: ""}, + "DescribeEndpointAuthorization": {Verb: "Get", Resource: "EndpointAuthorization", OutputListKey: "EndpointAuthorizationList", OutputItemKey: ""}, + "DescribeEventCategories": {Verb: "Get", Resource: "EventCategory", OutputListKey: "EventCategoriesMapList", OutputItemKey: ""}, + "DescribeEventSubscriptions": {Verb: "Get", Resource: "EventSubscription", OutputListKey: "EventSubscriptionsList", OutputItemKey: ""}, + "DescribeEvents": {Verb: "Get", Resource: "Event", OutputListKey: "Events", OutputItemKey: ""}, + "DescribeHsmClientCertificates": {Verb: "Get", Resource: "HsmClientCertificate", OutputListKey: "HsmClientCertificates", OutputItemKey: ""}, + "DescribeHsmConfigurations": {Verb: "Get", Resource: "HsmConfiguration", OutputListKey: "HsmConfigurations", OutputItemKey: ""}, + "DescribeInboundIntegrations": {Verb: "Get", Resource: "InboundIntegration", OutputListKey: "InboundIntegrations", OutputItemKey: ""}, + "DescribeIntegrations": {Verb: "Get", Resource: "Integration", OutputListKey: "Integrations", OutputItemKey: ""}, + "DescribeLoggingStatus": {Verb: "Get", Resource: "LoggingStatu", OutputListKey: "LogExports", OutputItemKey: ""}, + "DescribeNodeConfigurationOptions": {Verb: "Get", Resource: "NodeConfigurationOption", OutputListKey: "NodeConfigurationOptionList", OutputItemKey: ""}, + "DescribeOrderableClusterOptions": {Verb: "Get", Resource: "OrderableClusterOption", OutputListKey: "OrderableClusterOptions", OutputItemKey: ""}, + "DescribePartners": {Verb: "Get", Resource: "Partner", OutputListKey: "PartnerIntegrationInfoList", OutputItemKey: ""}, + "DescribeRedshiftIdcApplications": {Verb: "Get", Resource: "RedshiftIdcApplication", OutputListKey: "RedshiftIdcApplications", OutputItemKey: ""}, + "DescribeReservedNodeExchangeStatus": {Verb: "Get", Resource: "ReservedNodeExchangeStatu", OutputListKey: "ReservedNodeExchangeStatusDetails", OutputItemKey: ""}, + "DescribeReservedNodeOfferings": {Verb: "Get", Resource: "ReservedNodeOffering", OutputListKey: "ReservedNodeOfferings", OutputItemKey: ""}, + "DescribeReservedNodes": {Verb: "Get", Resource: "ReservedNode", OutputListKey: "ReservedNodes", OutputItemKey: ""}, + "DescribeResize": {Verb: "Get", Resource: "Resize", OutputListKey: "ImportTablesCompleted", OutputItemKey: ""}, + "DescribeScheduledActions": {Verb: "Get", Resource: "ScheduledAction", OutputListKey: "ScheduledActions", OutputItemKey: ""}, + "DescribeSnapshotCopyGrants": {Verb: "Get", Resource: "SnapshotCopyGrant", OutputListKey: "SnapshotCopyGrants", OutputItemKey: ""}, + "DescribeSnapshotSchedules": {Verb: "Get", Resource: "SnapshotSchedule", OutputListKey: "SnapshotSchedules", OutputItemKey: ""}, + "DescribeStorage": {Verb: "Get", Resource: "Storage", OutputListKey: "", OutputItemKey: ""}, + "DescribeTableRestoreStatus": {Verb: "Get", Resource: "TableRestoreStatu", OutputListKey: "TableRestoreStatusDetails", OutputItemKey: ""}, + "DescribeTags": {Verb: "Get", Resource: "Tag", OutputListKey: "TaggedResources", OutputItemKey: ""}, + "DescribeUsageLimits": {Verb: "Get", Resource: "UsageLimit", OutputListKey: "UsageLimits", OutputItemKey: ""}, + "GetClusterCredentials": {Verb: "Get", Resource: "ClusterCredential", OutputListKey: "", OutputItemKey: ""}, + "GetClusterCredentialsWithIAM": {Verb: "Get", Resource: "ClusterCredentialsWithIAM", OutputListKey: "", OutputItemKey: ""}, + "GetIdentityCenterAuthToken": {Verb: "Get", Resource: "IdentityCenterAuthToken", OutputListKey: "", OutputItemKey: ""}, + "GetReservedNodeExchangeConfigurationOptions": {Verb: "Get", Resource: "ReservedNodeExchangeConfigurationOption", OutputListKey: "ReservedNodeConfigurationOptionList", OutputItemKey: ""}, + "GetReservedNodeExchangeOfferings": {Verb: "Get", Resource: "ReservedNodeExchangeOffering", OutputListKey: "ReservedNodeOfferings", OutputItemKey: ""}, + "GetResourcePolicy": {Verb: "Get", Resource: "ResourcePolicy", OutputListKey: "", OutputItemKey: "ResourcePolicy"}, + "ListRecommendations": {Verb: "List", Resource: "Recommendation", OutputListKey: "Recommendations", OutputItemKey: ""}, + "ModifyAquaConfiguration": {Verb: "Update", Resource: "AquaConfiguration", OutputListKey: "", OutputItemKey: "AquaConfiguration"}, + "ModifyAuthenticationProfile": {Verb: "Update", Resource: "AuthenticationProfile", OutputListKey: "", OutputItemKey: ""}, + "ModifyCluster": {Verb: "Update", Resource: "Cluster", OutputListKey: "", OutputItemKey: "Cluster"}, + "ModifyClusterDbRevision": {Verb: "Update", Resource: "ClusterDbRevision", OutputListKey: "", OutputItemKey: "Cluster"}, + "ModifyClusterIamRoles": {Verb: "Update", Resource: "ClusterIamRole", OutputListKey: "", OutputItemKey: "Cluster"}, + "ModifyClusterMaintenance": {Verb: "Update", Resource: "ClusterMaintenance", OutputListKey: "", OutputItemKey: "Cluster"}, + "ModifyClusterParameterGroup": {Verb: "Update", Resource: "ClusterParameterGroup", OutputListKey: "", OutputItemKey: ""}, + "ModifyClusterSnapshot": {Verb: "Update", Resource: "ClusterSnapshot", OutputListKey: "", OutputItemKey: "Snapshot"}, + "ModifyClusterSnapshotSchedule": {Verb: "Update", Resource: "ClusterSnapshotSchedule", OutputListKey: "", OutputItemKey: ""}, + "ModifyClusterSubnetGroup": {Verb: "Update", Resource: "ClusterSubnetGroup", OutputListKey: "", OutputItemKey: "ClusterSubnetGroup"}, + "ModifyCustomDomainAssociation": {Verb: "Update", Resource: "CustomDomainAssociation", OutputListKey: "", OutputItemKey: ""}, + "ModifyEndpointAccess": {Verb: "Update", Resource: "EndpointAccess", OutputListKey: "VpcSecurityGroups", OutputItemKey: "VpcEndpoint"}, + "ModifyEventSubscription": {Verb: "Update", Resource: "EventSubscription", OutputListKey: "", OutputItemKey: "EventSubscription"}, + "ModifyIntegration": {Verb: "Update", Resource: "Integration", OutputListKey: "Errors", OutputItemKey: ""}, + "ModifyLakehouseConfiguration": {Verb: "Update", Resource: "LakehouseConfiguration", OutputListKey: "", OutputItemKey: ""}, + "ModifyRedshiftIdcApplication": {Verb: "Update", Resource: "RedshiftIdcApplication", OutputListKey: "", OutputItemKey: "RedshiftIdcApplication"}, + "ModifyScheduledAction": {Verb: "Update", Resource: "ScheduledAction", OutputListKey: "NextInvocations", OutputItemKey: "TargetAction"}, + "ModifySnapshotCopyRetentionPeriod": {Verb: "Update", Resource: "SnapshotCopyRetentionPeriod", OutputListKey: "", OutputItemKey: "Cluster"}, + "ModifySnapshotSchedule": {Verb: "Update", Resource: "SnapshotSchedule", OutputListKey: "AssociatedClusters", OutputItemKey: ""}, + "ModifyUsageLimit": {Verb: "Update", Resource: "UsageLimit", OutputListKey: "Tags", OutputItemKey: ""}, + "PutResourcePolicy": {Verb: "Update", Resource: "ResourcePolicy", OutputListKey: "", OutputItemKey: "ResourcePolicy"}, + "RegisterNamespace": {Verb: "Create", Resource: "Namespace", OutputListKey: "", OutputItemKey: ""}, + "UpdatePartnerStatus": {Verb: "Update", Resource: "PartnerStatu", OutputListKey: "", OutputItemKey: ""}, + }) crud.Register("redshiftdata", map[string]crud.OpMeta{ "DescribeStatement": {Verb: "Get", Resource: "Statement", OutputListKey: "QueryParameters", OutputItemKey: ""}, "DescribeTable": {Verb: "Get", Resource: "Table", OutputListKey: "ColumnList", OutputItemKey: ""}, @@ -7561,6 +8302,59 @@ func init() { "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: ""}, "UpdateAutoManagement": {Verb: "Update", Resource: "AutoManagement", OutputListKey: "", OutputItemKey: ""}, }) + crud.Register("ses", map[string]crud.OpMeta{ + "CreateConfigurationSet": {Verb: "Create", Resource: "ConfigurationSet", OutputListKey: "", OutputItemKey: ""}, + "CreateConfigurationSetEventDestination": {Verb: "Create", Resource: "ConfigurationSetEventDestination", OutputListKey: "", OutputItemKey: ""}, + "CreateConfigurationSetTrackingOptions": {Verb: "Create", Resource: "ConfigurationSetTrackingOption", OutputListKey: "", OutputItemKey: ""}, + "CreateCustomVerificationEmailTemplate": {Verb: "Create", Resource: "CustomVerificationEmailTemplate", OutputListKey: "", OutputItemKey: ""}, + "CreateReceiptFilter": {Verb: "Create", Resource: "ReceiptFilter", OutputListKey: "", OutputItemKey: ""}, + "CreateReceiptRule": {Verb: "Create", Resource: "ReceiptRule", OutputListKey: "", OutputItemKey: ""}, + "CreateReceiptRuleSet": {Verb: "Create", Resource: "ReceiptRuleSet", OutputListKey: "", OutputItemKey: ""}, + "CreateTemplate": {Verb: "Create", Resource: "Template", OutputListKey: "", OutputItemKey: ""}, + "DeleteConfigurationSet": {Verb: "Delete", Resource: "ConfigurationSet", OutputListKey: "", OutputItemKey: ""}, + "DeleteConfigurationSetEventDestination": {Verb: "Delete", Resource: "ConfigurationSetEventDestination", OutputListKey: "", OutputItemKey: ""}, + "DeleteConfigurationSetTrackingOptions": {Verb: "Delete", Resource: "ConfigurationSetTrackingOption", OutputListKey: "", OutputItemKey: ""}, + "DeleteCustomVerificationEmailTemplate": {Verb: "Delete", Resource: "CustomVerificationEmailTemplate", OutputListKey: "", OutputItemKey: ""}, + "DeleteIdentity": {Verb: "Delete", Resource: "Identity", OutputListKey: "", OutputItemKey: ""}, + "DeleteIdentityPolicy": {Verb: "Delete", Resource: "IdentityPolicy", OutputListKey: "", OutputItemKey: ""}, + "DeleteReceiptFilter": {Verb: "Delete", Resource: "ReceiptFilter", OutputListKey: "", OutputItemKey: ""}, + "DeleteReceiptRule": {Verb: "Delete", Resource: "ReceiptRule", OutputListKey: "", OutputItemKey: ""}, + "DeleteReceiptRuleSet": {Verb: "Delete", Resource: "ReceiptRuleSet", OutputListKey: "", OutputItemKey: ""}, + "DeleteTemplate": {Verb: "Delete", Resource: "Template", OutputListKey: "", OutputItemKey: ""}, + "DeleteVerifiedEmailAddress": {Verb: "Delete", Resource: "VerifiedEmailAddress", OutputListKey: "", OutputItemKey: ""}, + "DescribeActiveReceiptRuleSet": {Verb: "Get", Resource: "ActiveReceiptRuleSet", OutputListKey: "Rules", OutputItemKey: "Metadata"}, + "DescribeConfigurationSet": {Verb: "Get", Resource: "ConfigurationSet", OutputListKey: "EventDestinations", OutputItemKey: "ConfigurationSet"}, + "DescribeReceiptRule": {Verb: "Get", Resource: "ReceiptRule", OutputListKey: "", OutputItemKey: "Rule"}, + "DescribeReceiptRuleSet": {Verb: "Get", Resource: "ReceiptRuleSet", OutputListKey: "Rules", OutputItemKey: "Metadata"}, + "GetAccountSendingEnabled": {Verb: "Get", Resource: "AccountSendingEnabled", OutputListKey: "", OutputItemKey: ""}, + "GetCustomVerificationEmailTemplate": {Verb: "Get", Resource: "CustomVerificationEmailTemplate", OutputListKey: "", OutputItemKey: ""}, + "GetIdentityDkimAttributes": {Verb: "Get", Resource: "IdentityDkimAttribute", OutputListKey: "", OutputItemKey: ""}, + "GetIdentityMailFromDomainAttributes": {Verb: "Get", Resource: "IdentityMailFromDomainAttribute", OutputListKey: "", OutputItemKey: ""}, + "GetIdentityNotificationAttributes": {Verb: "Get", Resource: "IdentityNotificationAttribute", OutputListKey: "", OutputItemKey: ""}, + "GetIdentityPolicies": {Verb: "Get", Resource: "IdentityPolicy", OutputListKey: "", OutputItemKey: ""}, + "GetIdentityVerificationAttributes": {Verb: "Get", Resource: "IdentityVerificationAttribute", OutputListKey: "", OutputItemKey: ""}, + "GetSendQuota": {Verb: "Get", Resource: "SendQuota", OutputListKey: "", OutputItemKey: ""}, + "GetSendStatistics": {Verb: "Get", Resource: "SendStatistic", OutputListKey: "SendDataPoints", OutputItemKey: ""}, + "GetTemplate": {Verb: "Get", Resource: "Template", OutputListKey: "", OutputItemKey: "Template"}, + "ListConfigurationSets": {Verb: "List", Resource: "ConfigurationSet", OutputListKey: "ConfigurationSets", OutputItemKey: ""}, + "ListCustomVerificationEmailTemplates": {Verb: "List", Resource: "CustomVerificationEmailTemplate", OutputListKey: "CustomVerificationEmailTemplates", OutputItemKey: ""}, + "ListIdentities": {Verb: "List", Resource: "Identity", OutputListKey: "Identities", OutputItemKey: ""}, + "ListIdentityPolicies": {Verb: "List", Resource: "IdentityPolicy", OutputListKey: "PolicyNames", OutputItemKey: ""}, + "ListReceiptFilters": {Verb: "List", Resource: "ReceiptFilter", OutputListKey: "Filters", OutputItemKey: ""}, + "ListReceiptRuleSets": {Verb: "List", Resource: "ReceiptRuleSet", OutputListKey: "RuleSets", OutputItemKey: ""}, + "ListTemplates": {Verb: "List", Resource: "Template", OutputListKey: "TemplatesMetadata", OutputItemKey: ""}, + "ListVerifiedEmailAddresses": {Verb: "List", Resource: "VerifiedEmailAddress", OutputListKey: "VerifiedEmailAddresses", OutputItemKey: ""}, + "PutConfigurationSetDeliveryOptions": {Verb: "Update", Resource: "ConfigurationSetDeliveryOption", OutputListKey: "", OutputItemKey: ""}, + "PutIdentityPolicy": {Verb: "Update", Resource: "IdentityPolicy", OutputListKey: "", OutputItemKey: ""}, + "UpdateAccountSendingEnabled": {Verb: "Update", Resource: "AccountSendingEnabled", OutputListKey: "", OutputItemKey: ""}, + "UpdateConfigurationSetEventDestination": {Verb: "Update", Resource: "ConfigurationSetEventDestination", OutputListKey: "", OutputItemKey: ""}, + "UpdateConfigurationSetReputationMetricsEnabled": {Verb: "Update", Resource: "ConfigurationSetReputationMetricsEnabled", OutputListKey: "", OutputItemKey: ""}, + "UpdateConfigurationSetSendingEnabled": {Verb: "Update", Resource: "ConfigurationSetSendingEnabled", OutputListKey: "", OutputItemKey: ""}, + "UpdateConfigurationSetTrackingOptions": {Verb: "Update", Resource: "ConfigurationSetTrackingOption", OutputListKey: "", OutputItemKey: ""}, + "UpdateCustomVerificationEmailTemplate": {Verb: "Update", Resource: "CustomVerificationEmailTemplate", OutputListKey: "", OutputItemKey: ""}, + "UpdateReceiptRule": {Verb: "Update", Resource: "ReceiptRule", OutputListKey: "", OutputItemKey: ""}, + "UpdateTemplate": {Verb: "Update", Resource: "Template", 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"}, @@ -7738,6 +8532,35 @@ func init() { "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("sns", map[string]crud.OpMeta{ + "CreatePlatformApplication": {Verb: "Create", Resource: "PlatformApplication", OutputListKey: "", OutputItemKey: ""}, + "CreatePlatformEndpoint": {Verb: "Create", Resource: "PlatformEndpoint", OutputListKey: "", OutputItemKey: ""}, + "CreateSMSSandboxPhoneNumber": {Verb: "Create", Resource: "SMSSandboxPhoneNumber", OutputListKey: "", OutputItemKey: ""}, + "CreateTopic": {Verb: "Create", Resource: "Topic", OutputListKey: "", OutputItemKey: ""}, + "DeleteEndpoint": {Verb: "Delete", Resource: "Endpoint", OutputListKey: "", OutputItemKey: ""}, + "DeletePlatformApplication": {Verb: "Delete", Resource: "PlatformApplication", OutputListKey: "", OutputItemKey: ""}, + "DeleteSMSSandboxPhoneNumber": {Verb: "Delete", Resource: "SMSSandboxPhoneNumber", OutputListKey: "", OutputItemKey: ""}, + "DeleteTopic": {Verb: "Delete", Resource: "Topic", OutputListKey: "", OutputItemKey: ""}, + "GetDataProtectionPolicy": {Verb: "Get", Resource: "DataProtectionPolicy", OutputListKey: "", OutputItemKey: ""}, + "GetEndpointAttributes": {Verb: "Get", Resource: "EndpointAttribute", OutputListKey: "", OutputItemKey: ""}, + "GetPlatformApplicationAttributes": {Verb: "Get", Resource: "PlatformApplicationAttribute", OutputListKey: "", OutputItemKey: ""}, + "GetSMSAttributes": {Verb: "Get", Resource: "SMSAttribute", OutputListKey: "", OutputItemKey: ""}, + "GetSMSSandboxAccountStatus": {Verb: "Get", Resource: "SMSSandboxAccountStatu", OutputListKey: "", OutputItemKey: ""}, + "GetSubscriptionAttributes": {Verb: "Get", Resource: "SubscriptionAttribute", OutputListKey: "", OutputItemKey: ""}, + "GetTopicAttributes": {Verb: "Get", Resource: "TopicAttribute", OutputListKey: "", OutputItemKey: ""}, + "ListEndpointsByPlatformApplication": {Verb: "List", Resource: "EndpointsByPlatformApplication", OutputListKey: "Endpoints", OutputItemKey: ""}, + "ListOriginationNumbers": {Verb: "List", Resource: "OriginationNumber", OutputListKey: "PhoneNumbers", OutputItemKey: ""}, + "ListPhoneNumbersOptedOut": {Verb: "List", Resource: "PhoneNumbersOptedOut", OutputListKey: "phoneNumbers", OutputItemKey: ""}, + "ListPlatformApplications": {Verb: "List", Resource: "PlatformApplication", OutputListKey: "PlatformApplications", OutputItemKey: ""}, + "ListSMSSandboxPhoneNumbers": {Verb: "List", Resource: "SMSSandboxPhoneNumber", OutputListKey: "PhoneNumbers", OutputItemKey: ""}, + "ListSubscriptions": {Verb: "List", Resource: "Subscription", OutputListKey: "Subscriptions", OutputItemKey: ""}, + "ListSubscriptionsByTopic": {Verb: "List", Resource: "SubscriptionsByTopic", OutputListKey: "Subscriptions", OutputItemKey: ""}, + "ListTagsForResource": {Verb: "List", Resource: "TagsForResource", OutputListKey: "Tags", OutputItemKey: ""}, + "ListTopics": {Verb: "List", Resource: "Topic", OutputListKey: "Topics", OutputItemKey: ""}, + "PutDataProtectionPolicy": {Verb: "Update", Resource: "DataProtectionPolicy", OutputListKey: "", OutputItemKey: ""}, + "TagResource": {Verb: "Tag", Resource: "Resource", OutputListKey: "", OutputItemKey: ""}, + "UntagResource": {Verb: "Untag", Resource: "Resource", OutputListKey: "", OutputItemKey: ""}, + }) crud.Register("sqs", map[string]crud.OpMeta{ "CreateQueue": {Verb: "Create", Resource: "Queue", OutputListKey: "", OutputItemKey: ""}, "DeleteMessage": {Verb: "Delete", Resource: "Message", OutputListKey: "", OutputItemKey: ""}, diff --git a/internal/generated/fidelity/manifest_gen.go b/internal/generated/fidelity/manifest_gen.go index 9dd4a8d6..2321eaf0 100644 --- a/internal/generated/fidelity/manifest_gen.go +++ b/internal/generated/fidelity/manifest_gen.go @@ -5129,27 +5129,27 @@ var Services = map[string]Service{ "ApplySecurityGroupsToLoadBalancer": TierUnimplemented, "AttachLoadBalancerToSubnets": TierUnimplemented, "ConfigureHealthCheck": TierUnimplemented, - "CreateAppCookieStickinessPolicy": TierUnimplemented, - "CreateLBCookieStickinessPolicy": TierUnimplemented, - "CreateLoadBalancer": TierUnimplemented, - "CreateLoadBalancerListeners": TierUnimplemented, - "CreateLoadBalancerPolicy": TierUnimplemented, - "DeleteLoadBalancer": TierUnimplemented, - "DeleteLoadBalancerListeners": TierUnimplemented, - "DeleteLoadBalancerPolicy": TierUnimplemented, - "DeregisterInstancesFromLoadBalancer": TierUnimplemented, - "DescribeAccountLimits": TierUnimplemented, - "DescribeInstanceHealth": TierUnimplemented, - "DescribeLoadBalancerAttributes": TierUnimplemented, - "DescribeLoadBalancerPolicies": TierUnimplemented, - "DescribeLoadBalancerPolicyTypes": TierUnimplemented, - "DescribeLoadBalancers": TierUnimplemented, - "DescribeTags": TierUnimplemented, + "CreateAppCookieStickinessPolicy": TierAutoCRUD, + "CreateLBCookieStickinessPolicy": TierAutoCRUD, + "CreateLoadBalancer": TierAutoCRUD, + "CreateLoadBalancerListeners": TierAutoCRUD, + "CreateLoadBalancerPolicy": TierAutoCRUD, + "DeleteLoadBalancer": TierAutoCRUD, + "DeleteLoadBalancerListeners": TierAutoCRUD, + "DeleteLoadBalancerPolicy": TierAutoCRUD, + "DeregisterInstancesFromLoadBalancer": TierAutoCRUD, + "DescribeAccountLimits": TierAutoCRUD, + "DescribeInstanceHealth": TierAutoCRUD, + "DescribeLoadBalancerAttributes": TierAutoCRUD, + "DescribeLoadBalancerPolicies": TierAutoCRUD, + "DescribeLoadBalancerPolicyTypes": TierAutoCRUD, + "DescribeLoadBalancers": TierAutoCRUD, + "DescribeTags": TierAutoCRUD, "DetachLoadBalancerFromSubnets": TierUnimplemented, "DisableAvailabilityZonesForLoadBalancer": TierUnimplemented, "EnableAvailabilityZonesForLoadBalancer": TierUnimplemented, - "ModifyLoadBalancerAttributes": TierUnimplemented, - "RegisterInstancesWithLoadBalancer": TierUnimplemented, + "ModifyLoadBalancerAttributes": TierAutoCRUD, + "RegisterInstancesWithLoadBalancer": TierAutoCRUD, "RemoveTags": TierUnimplemented, "SetLoadBalancerListenerSSLCertificate": TierUnimplemented, "SetLoadBalancerPoliciesForBackendServer": TierUnimplemented, diff --git a/internal/shared/crud/crud.go b/internal/shared/crud/crud.go index 04f1c858..beaca3f3 100644 --- a/internal/shared/crud/crud.go +++ b/internal/shared/crud/crud.go @@ -133,19 +133,23 @@ func JSONProtocol(protocol string) bool { // Servable reports whether the engine can serve requests for a protocol. // -// The JSON protocols carry the operation name in a header. rest-json and -// rest-xml do not, but their models bind every operation to a method and URI -// template, which the route table turns back into an operation name. query has -// neither a target header nor a modelled path — its operation is a form field — -// so a query request cannot be classified here and is declined rather than -// guessed at. +// Each protocol says which operation it means in a different place, and the +// engine now reads all three: the JSON protocols put it in an X-Amz-Target +// header; rest-json and rest-xml bind every operation to a method and URI +// template, which the route table turns back into a name; query puts it in the +// Action field of a form body. +// +// ec2-query is the one left out. It is form-encoded like query but not +// interchangeable with it, and no registered service speaks it except EC2, +// whose provider is hand-written and never reaches the engine. // // This is deliberately the same question codegen's engineServable answers. The // two must agree: a protocol admitted there but refused here registers // operations nothing can reach, and the fidelity manifest would call them // auto-crud. func Servable(protocol string) bool { - return JSONProtocol(protocol) || protocol == protocolRESTJSON || protocol == protocolRESTXML + return JSONProtocol(protocol) || protocol == protocolRESTJSON || + protocol == protocolRESTXML || protocol == protocolQuery } // NeedsBody reports whether the gateway must buffer the request body before @@ -159,8 +163,8 @@ func Servable(protocol string) bool { // CRUD-shaped S3 Control operation addresses its resource with a path label or // a query term, so the engine has what it needs without the body. // -// query is the mirror image — not servable yet, but its operation name is a -// field in the form body, so it cannot be read without buffering. +// query is the mirror image: servable, and unservable without the body, because +// the operation name itself is a field in it. func NeedsBody(protocol string) bool { return JSONProtocol(protocol) || protocol == protocolRESTJSON || protocol == protocolQuery } @@ -171,11 +175,22 @@ func NeedsBody(protocol string) bool { func Handle(c Call) (*Result, error) { op := c.Op var labels httproute.Params + var form map[string]any rest := false switch { case JSONProtocol(c.Protocol): // The operation name arrived in X-Amz-Target; nothing to resolve. + case c.Protocol == protocolQuery: + // query names its operation in neither a header nor a path: Action is + // a field of the form body, which is why it outlived the two REST + // protocols as a gap. An absent or empty Action is not a request this + // engine can classify — the other fields describe a resource, not an + // operation, and picking one from them would be a guess. + op, form = parseQueryForm(c.Body) + if op == "" { + return nil, ErrUnclassified + } case c.Protocol == protocolRESTJSON, c.Protocol == protocolRESTXML: rest = true mu.RLock() @@ -212,7 +227,14 @@ func Handle(c Call) (*Result, error) { if rest { maps.Copy(params, queryParams(c.URI)) } - if len(c.Body) > 0 { + switch { + case c.Protocol == protocolQuery: + // Already decoded above. A query body is form-encoded, not JSON, so it + // must not reach the branch below — parsing it as JSON fails, and + // reporting that as a SerializationException would decline every query + // request with an error about a format it never claimed to send. + maps.Copy(params, form) + case 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 @@ -229,6 +251,39 @@ func Handle(c Call) (*Result, error) { return withContentType(res, c.Protocol), err } +// parseQueryForm reads a Query-protocol form body, returning the operation name +// from Action and the remaining fields as engine parameters. +// +// Action and Version are dropped from the parameters. They describe the +// request, not the resource, and the engine echoes what it stores — leaving +// them in would put CreateLoadBalancer inside a result element +// where no SDK expects a member by that name, and would make Version part of +// the stored document forever. +// +// Structured members arrive flattened, as "Listeners.member.1.Protocol". They +// are kept here and dropped at the serializer (see sortedKeys), so that a +// dotted key can still be a resource identifier if some model ever binds one, +// without being emitted as a bogus element. +func parseQueryForm(body []byte) (action string, 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(string(body)) + params = make(map[string]any, len(values)) + for k, vs := range values { + if len(vs) == 0 { + continue + } + switch k { + case "Action": + action = vs[0] + case "Version": + default: + params[k] = vs[0] + } + } + return action, params +} + // 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. From bf8704ce266ec4fd7aa21f01b8b6912064dfce60 Mon Sep 17 00:00:00 2001 From: Sung-Kyu Yoo Date: Sat, 5 Sep 2026 20:55:41 +0900 Subject: [PATCH 07/10] test: prove the floor for elb and s3control through botocore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GREEN: 854 passed, 2 skipped (was 846/3); go test ./... green. Both leave REGISTERED_ONLY_SERVICES. elb joins the generic smoke list; s3control cannot, and that is a finding rather than a test to loosen — all 97 of its operations take a required AccountId, so the harness has no parameterless read to pick. It is proved in test_s3control.py instead, the budgets precedent. These tests assert on parsed members, not status codes, because the failure mode they exist to catch is silent: botocore's query parser given the wrong envelope returns a result with nothing in it rather than an error, so a 200 whose body it discards is indistinguishable from a working service on the Go side of the wire. Both files also pin the edge of the claim. ConfigureHealthCheck is one of ELB's 11 unclassifiable operations and a Terraform aws_elb resource calls it; it must decline with a parseable code, not an empty success. --- tests/compatibility/test_elb.py | 90 +++++++++++++++++++++++ tests/compatibility/test_s3control.py | 47 ++++++++++++ tests/compatibility/test_service_smoke.py | 45 ++++++++---- 3 files changed, 168 insertions(+), 14 deletions(-) create mode 100644 tests/compatibility/test_elb.py diff --git a/tests/compatibility/test_elb.py b/tests/compatibility/test_elb.py new file mode 100644 index 00000000..20e4c4a4 --- /dev/null +++ b/tests/compatibility/test_elb.py @@ -0,0 +1,90 @@ +"""Elastic Load Balancing v1, served by the generic CRUD engine over Query. + +query was the last protocol the engine could not read. Its operation is neither +an X-Amz-Target header nor a modelled path but the Action field of a form body, +and its responses are XML in a dialect of their own: botocore's query parser +looks for nested inside and, given +anything else, returns a result with nothing in it rather than an error. + +That failure mode is why these tests assert on parsed members instead of on +status codes. A 200 whose body botocore silently discards looks identical to a +working service from Go's side of the wire. +""" + +import pytest +from botocore.exceptions import ClientError + +from conftest import _make_client + + +@pytest.fixture +def elb_client(devcloud_server): + return _make_client("elb") + + +def test_describe_on_empty_store(elb_client): + """The parameterless read, and the first thing that would break if the + query envelope were wrong: an empty collection must parse as an empty list, + not as a missing key.""" + got = elb_client.describe_load_balancers() + assert got["LoadBalancerDescriptions"] == [] + + +def test_create_then_describe_round_trips(elb_client): + """The name the caller sent in a form field comes back through the XML. + + This is the whole query path end to end: Action picks the operation, + LoadBalancerName is stored as the identifier, and the response is re-parsed + by botocore into a modelled member. + """ + elb_client.create_load_balancer( + LoadBalancerName="my-lb", + Listeners=[{"Protocol": "HTTP", "LoadBalancerPort": 80, "InstancePort": 8080}], + ) + + got = elb_client.describe_load_balancers() + names = [lb["LoadBalancerName"] for lb in got["LoadBalancerDescriptions"]] + assert "my-lb" in names + + +def test_delete_removes_it(elb_client): + elb_client.create_load_balancer(LoadBalancerName="doomed-lb", Listeners=[]) + elb_client.delete_load_balancer(LoadBalancerName="doomed-lb") + + got = elb_client.describe_load_balancers() + names = [lb["LoadBalancerName"] for lb in got["LoadBalancerDescriptions"]] + assert "doomed-lb" not in names + + +def test_unclassifiable_operation_declines(elb_client): + """The floor is a floor. Eleven of ELB's 29 operations are not CRUD-shaped, + so codegen registers nothing for them and they must return a clean AWS error + rather than an empty success. + + ConfigureHealthCheck is the one worth naming: a Terraform aws_elb resource + calls it, so this is the honest edge of what "elb is covered" means. + """ + with pytest.raises(ClientError) as exc: + elb_client.configure_health_check( + LoadBalancerName="my-lb", + HealthCheck={ + "Target": "HTTP:80/", + "Interval": 30, + "Timeout": 5, + "UnhealthyThreshold": 2, + "HealthyThreshold": 2, + }, + ) + # The code has to survive botocore's query parser. A bare envelope + # here would produce a ClientError with no Code at all, which tells the + # caller nothing about why the call failed. + assert exc.value.response["Error"]["Code"], "botocore parsed no error code" + + +def test_elbv2_is_unaffected(devcloud_server): + """ELB v1 and v2 share the signing name "elasticloadbalancing" and both + speak query, so only the API version in the request body separates them. + v2 has a hand-written provider and must keep reaching it.""" + v2 = _make_client("elbv2") + got = v2.describe_load_balancers() + assert "LoadBalancers" in got diff --git a/tests/compatibility/test_s3control.py b/tests/compatibility/test_s3control.py index 026ee459..169ba527 100644 --- a/tests/compatibility/test_s3control.py +++ b/tests/compatibility/test_s3control.py @@ -70,6 +70,53 @@ def test_s3control_answers_as_itself_not_as_s3(s3control_client): ) +def test_s3control_is_engine_served(s3control_client): + """s3control's floor, proved here rather than in test_service_smoke.py. + + It cannot go in that harness's ENGINE_SERVED_SERVICES list: the list picks a + parameterless List*/Describe* from the model, and all 97 of s3control's + operations take a required AccountId. This is the budgets precedent — the + service is served, and the proof needs one fixture instead of none. + + rest-xml is why it was the last protocol but one: botocore's RestXMLParser + maps the response root's children onto the output shape, so this asserts the + engine's generic XML is something a real parser accepts, not merely that Go + produced a 200. + """ + got = s3control_client.list_access_points(AccountId=ACCOUNT_ID) + assert "AccessPointList" in got, f"no modelled member came back: {got}" + + +def test_s3control_round_trips_a_resource(s3control_client): + """Create then read, through botocore both ways. + + The identifier arrives only as a path label — PUT /v20180820/accesspoint/ + {Name} — with no request body at all, because the gateway deliberately does + not buffer rest-xml bodies. If the label were not read, the resource would + be stored under a generated id and this read would come back empty. + """ + name = "round-trip-ap" + s3control_client.create_access_point( + AccountId=ACCOUNT_ID, Name=name, Bucket="some-bucket" + ) + + listed = s3control_client.list_access_points(AccountId=ACCOUNT_ID) + names = [ap.get("Name") for ap in listed.get("AccessPointList", [])] + assert name in names, f"created access point is not in the list: {listed}" + + +def test_s3control_unclassifiable_operation_declines(s3control_client): + """The floor is a floor. AssociateAccessGrantsIdentityCenter is one of the + three s3control operations that is not CRUD-shaped, so codegen registers + nothing for it and it must decline rather than answer from the store.""" + code = _error_code( + s3control_client.associate_access_grants_identity_center, + AccountId=ACCOUNT_ID, + IdentityCenterArn="arn:aws:sso:::instance/ssoins-000000000000", + ) + assert code is not None, "an unclassifiable operation returned a success" + + def test_s3_is_unaffected_by_the_split(s3_client): """The split must cost S3 nothing for any normal bucket or key.""" s3_client.create_bucket(Bucket="split-guard-bucket") diff --git a/tests/compatibility/test_service_smoke.py b/tests/compatibility/test_service_smoke.py index daa4613b..bd52cb5f 100644 --- a/tests/compatibility/test_service_smoke.py +++ b/tests/compatibility/test_service_smoke.py @@ -19,10 +19,10 @@ # 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 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. +# hand-written provider. The engine reads every protocol DevCloud registers, +# each naming its operation somewhere different: awsJson1_0 / awsJson1_1 in the +# X-Amz-Target header, rest-json and rest-xml in the request method and path via +# the model's route table, query in the Action field of the form body. ENGINE_SERVED_SERVICES = [ "comprehend", # rest-json, and the proof the engine reaches that protocol at all. All @@ -111,19 +111,37 @@ "vpc-lattice", "workspaces", "workspaces-web", + # --- the non-JSON surface (Milestone 5) --- + # The last two of the 57, and the reason they were last. Neither protocol + # names its operation the way the engine originally required: elb is query, + # so the operation is the Action field of a form body, and s3control is + # rest-xml, so it comes from the method and path. Both are read now, and + # this entry is what proves it against a real botocore parser rather than + # against Go's idea of the wire format. + # + # s3control is served too — 94 auto-crud operations in the manifest — but + # is absent here on purpose: every one of its 97 operations takes a required + # AccountId, so this harness has no parameterless read to prove it with. The + # budgets precedent, and tests/compatibility/test_s3control.py is where it + # is proved instead. + "elb", # Served, but not provable here: apigateway and apigatewaymanagementapi # read with Get* rather than List*/Describe*, and budgets requires an # account id on every operation. The fidelity manifest is their record, # as for bedrock-data-automation-runtime. ] -# Services registered so the gateway routes them, but served by nothing: their -# protocol carries no operation name for the CRUD engine to classify, and no -# provider implements them by hand. They must answer with a clean AWS error — -# never a fabricated success, and never an unrouted UnknownService, which would +# Services registered so the gateway routes them, but served by nothing: no +# operation in their whole API is CRUD-shaped, and no provider implements them +# by hand. They must answer with a clean AWS error — 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. # +# The protocol reason for being on this list is gone. The engine reads all five +# protocols now — X-Amz-Target for the JSON family, method and path for the two +# REST ones, the Action form field for query — so what is left here is only the +# services whose operations are not CRUD-shaped at all. +# # 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 @@ -137,15 +155,14 @@ # no route to match. Same case as forecastquery. "sagemaker-runtime", # --- the demand set (Milestone 4) --- - # The three of 57 that do not meet the floor, and why each is different: - # elb query protocol — the engine cannot read it; Milestone 5 - # s3control rest-xml protocol — same; Milestone 5 + # One of the 57 does not meet the floor. elb and s3control were here too, + # for the protocol reason Milestone 5 removed: the engine now reads query + # from the Action form field and rest-xml from the method and path. # rds-data rest-json and readable, but its whole API is # ExecuteStatement / BeginTransaction / Commit / Rollback, - # none of which is CRUD-shaped. No protocol change helps it. - "elb", + # none of which is CRUD-shaped. No protocol change helps it, + # which is why it is the one that stays. "rds-data", - "s3control", ] From e1ca03ce94f26dcb9cca6a9f0d9a60222e05ef02 Mon Sep 17 00:00:00 2001 From: Sung-Kyu Yoo Date: Sat, 5 Sep 2026 20:58:21 +0900 Subject: [PATCH 08/10] docs: publish the coverage figure with the non-JSON surface closed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 205 registered / 201 serving >=1 / 4 registered-only, and 4,496 hand-verified / 4,970 auto-crud / 2,941 unimplemented. Every number is read out of internal/generated/fidelity/manifest_gen.go, not out of the plan; go test ./cmd/devcloud/ asserts the manifest against the live registry. The interesting edit is a deletion. coverage.md listed two reasons a registered service can serve nothing; one of them is gone. Protocol is no longer a reason, so the four that remain are all the same case — no CRUD-shaped operation anywhere in their API — and the page says so rather than leaving a category with nothing in it. crud-engine.md documents the limits each new protocol brings, because they are real: rest-xml request bodies are never read, query keeps flat form keys only and drops Action and Version, lists are always -wrapped, no xmlns is emitted. The PRD retires the non-JSON risk as closed rather than as excluded. --- changes/unreleased/Added-20260905-201000.yaml | 5 ++ .../unreleased/Changed-20260905-201001.yaml | 5 ++ docs/coverage.md | 64 +++++++++------- docs/crud-engine.md | 74 ++++++++++++++----- 4 files changed, 102 insertions(+), 46 deletions(-) create mode 100644 changes/unreleased/Added-20260905-201000.yaml create mode 100644 changes/unreleased/Changed-20260905-201001.yaml diff --git a/changes/unreleased/Added-20260905-201000.yaml b/changes/unreleased/Added-20260905-201000.yaml new file mode 100644 index 00000000..7886beb8 --- /dev/null +++ b/changes/unreleased/Added-20260905-201000.yaml @@ -0,0 +1,5 @@ +kind: Added +body: 'The generic CRUD engine now serves every protocol DevCloud registers. `rest-xml` and `query` were the last two: `rest-xml` recovers its operation from the request method and path against the model''s URI templates, like `rest-json`, and `query` reads it from the `Action` field of the form body. 112 operations move from `unimplemented` to `auto-crud` — 94 in `s3-control` and 18 in `elastic-load-balancing` — and protocol is no longer a reason any registered service serves nothing' +time: 2026-09-05T20:10:00.000000+09:00 +custom: + Issue: "142" diff --git a/changes/unreleased/Changed-20260905-201001.yaml b/changes/unreleased/Changed-20260905-201001.yaml new file mode 100644 index 00000000..5ce6fab8 --- /dev/null +++ b/changes/unreleased/Changed-20260905-201001.yaml @@ -0,0 +1,5 @@ +kind: Changed +body: '`rest-xml` request bodies are still not buffered by the gateway, now by an explicit rule rather than as a side effect of the protocol being unservable. The engine serves `rest-xml` from the path and query alone, so S3''s large binary uploads keep streaming; `crud.NeedsBody` is the predicate and a test fails if the body is read' +time: 2026-09-05T20:10:01.000000+09:00 +custom: + Issue: "142" diff --git a/docs/coverage.md b/docs/coverage.md index 278f4c87..08435ffc 100644 --- a/docs/coverage.md +++ b/docs/coverage.md @@ -10,36 +10,35 @@ things: | Number | What it means | Today | |---|---|---| | **Registered** | The gateway routes the service. A call reaches DevCloud instead of falling through to real AWS. | **205** | -| **Serving ≥1 operation** | At least one operation returns a real, store-backed answer — hand-written or served by the generic CRUD engine. | **199** | -| **Registered-only** | Routed, but every operation declines with a clean AWS error. Nothing is served. | **6** | +| **Serving ≥1 operation** | At least one operation returns a real, store-backed answer — hand-written or served by the generic CRUD engine. | **201** | +| **Registered-only** | Routed, but every operation declines with a clean AWS error. Nothing is served. | **4** | Per operation, from the [fidelity manifest](fidelity-manifest.md): | Tier | Operations | |---|---| | `hand-verified` | 4,496 | -| `auto-crud` | 4,858 | -| `unimplemented` | 3,053 | +| `auto-crud` | 4,970 | +| `unimplemented` | 2,941 | | **total known** | **12,407** | ## Why a registered service can serve nothing 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. +to recognise that operation as CRUD-shaped. Only the second one still stops 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 protocol always says which operation.** Each one says it somewhere +different, and the engine reads all of them: the `X-Amz-Target` JSON protocols +put it in a header; `rest-json` and `rest-xml` bind every operation to an HTTP +method and a URI template, which `internal/shared/httproute` matches a request +back to; `query` puts it in the `Action` field of the form body. This used to be +the main reason a service served nothing. It no longer is. **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. +protocol. This is now the *only* reason. Registered services by protocol: @@ -48,19 +47,21 @@ Registered services by protocol: | `json-1.1` | 64 | yes — operation from `X-Amz-Target` | | `json-1.0` | 17 | yes — operation from `X-Amz-Target` | | `rest-json` | 93 | yes — operation from method + path | -| `query` | 15 | no | -| `rest-xml` | 4 | no | +| `query` | 15 | yes — operation from the `Action` form field | +| `rest-xml` | 4 | yes — operation from method + path | | no in-tree model | 12 | n/a — hand-written providers | -Six services are registered and serve nothing. Four are the second case — no -CRUD-shaped operation anywhere in their API: `forecastquery` (`QueryForecast`, +Four services are registered and serve nothing, and all four are the same case — +no CRUD-shaped operation anywhere in their API: `forecastquery` (`QueryForecast`, `QueryWhatIfForecast`), the two SageMaker Runtime variants (`InvokeEndpoint*`), and `rds-data` (`ExecuteStatement`, `BeginTransaction`, `CommitTransaction`, `RollbackTransaction`). No protocol change reaches them. -The other two are the first case, and they are the whole of what is left: -`elastic-load-balancing` (`query`) and `s3-control` (`rest-xml`). Both are in -the demand set, and both are what PRD Milestone 5 now covers. +Being engine-servable is not the same as being served. Thirteen of the fifteen +`query` services and three of the four `rest-xml` ones have hand-written +providers that answer their own unknown operations, so they never enter the +engine and their manifest did not move when the protocols were admitted — the +`EngineWired` flag records that per service. A registered operation is not automatically a reachable one. The engine is entered only when a provider returns `plugin.ErrUnhandledOp`, so a hand-written @@ -103,8 +104,8 @@ stopped on the best surface available. | | Count | |---|---| | Registered | 57 | -| Serving ≥1 operation | 54 | -| Registered-only | 3 | +| Serving ≥1 operation | 56 | +| Registered-only | 1 | The 57 split by protocol as 34 `rest-json`, 15 `json-1.1`, 6 `json-1.0`, 1 `query`, 1 `rest-xml`. Two thirds of the set is `rest-json`, which is why the @@ -112,12 +113,19 @@ engine gaining that protocol is what made this milestone possible rather than a matter of arithmetic: without it, 34 of the 57 would have registered and served nothing. -The three that do not meet the floor are named above, each for a different -reason. `rds-data` is the one worth calling out: it is supported by all three -projects in the demand survey — the strongest signal in the whole set — and it -still cannot be served generically, because not one of its six operations is -CRUD-shaped. Breadth does not reach every service, and saying so is cheaper than -a fabricated success. +The one that does not meet the floor is `rds-data`, and it is the one worth +calling out: it is supported by all three projects in the demand survey — the +strongest signal in the whole set — and it still cannot be served generically, +because not one of its six operations is CRUD-shaped. Breadth does not reach +every service, and saying so is cheaper than a fabricated success. + +`elastic-load-balancing` and `s3-control` were the other two. They were the last +of the demand set because of their protocols, not their APIs, and both are +served now: 18 of ELB's 29 operations and 94 of S3 Control's 97. The eleven and +the three that remain are the not-CRUD-shaped case again — `ConfigureHealthCheck` +and `ApplySecurityGroupsToLoadBalancer` among them, which a Terraform `aws_elb` +resource does call. Breadth is what this milestone bought; depth is still not +claimed. ## What counts as a service diff --git a/docs/crud-engine.md b/docs/crud-engine.md index aa737f01..18a445ab 100644 --- a/docs/crud-engine.md +++ b/docs/crud-engine.md @@ -35,24 +35,62 @@ it. Where that name lives depends on the protocol: |---|---|---| | `json-1.0`, `json-1.1` | the `X-Amz-Target` header | yes | | `rest-json` | the request method and path, matched against the model's URI templates (`internal/shared/httproute`) | yes | -| `query` | — | no | -| `rest-xml` | — | no | - -For `rest-json` the engine reads parameters from three places, least -authoritative first: values the model binds with `httpQuery`, then the JSON -body, then the path labels. The URI is what addresses the resource, so a path -label wins. A `restJson1` model never binds one member to two of these, so real -SDK traffic never exercises the precedence. - -It does **not** read `httpHeader` members, `httpPayload` blobs, or streaming -bodies. An operation whose identifier arrives only in a header is therefore -served with a generated id rather than the caller's — plausible, not faithful, -which is the engine's stated contract. - -A request whose method and path match no route in the service's table is -**declined** with `InvalidAction`, never served from the store. That is what -keeps a registered `rest-json` service from answering for paths it does not -model. +| `rest-xml` | the same — every `restXml` operation is bound to a method and URI too | yes | +| `query` | the `Action` field of the form body | yes | +| `ec2-query` | — | no | + +Every protocol DevCloud registers is now readable, so a service that serves +nothing does so because none of its operations is CRUD-shaped, not because of +how it talks. `ec2-query` is the one exception and it is not a gap in practice: +the only service that speaks it is EC2, whose provider is hand-written and never +reaches the engine. + +### Where parameters come from + +For the two REST protocols, three places, least authoritative first: values the +model binds with `httpQuery`, then the request body, then the path labels. The +URI is what addresses the resource, so a path label wins. A REST model never +binds one member to two of these, so real SDK traffic never exercises the +precedence; it is defined so a hand-rolled request cannot redirect a lookup. + +For `query`, the form body, flat keys only. `Action` and `Version` are dropped: +they describe the request rather than the resource, and storing them would echo +`CreateLoadBalancer` back inside a result element. A structured +member arrives flattened as `Listeners.member.1.Protocol`; the engine has no +nested shape to put it in, so it is not emitted in the response. + +**`rest-xml` request bodies are never read at all.** The gateway does not buffer +them — S3 speaks `rest-xml` and its bodies are multi-gigabyte uploads that must +keep streaming — so a `rest-xml` operation is served from its path and query +alone. Every CRUD-shaped S3 Control operation addresses its resource that way, +so nothing is lost; an operation that carried its identifier only in a body +would get a generated id. + +The engine does **not** read `httpHeader` members, `httpPayload` blobs, or +streaming bodies. An operation whose identifier arrives only in a header is +therefore served with a generated id rather than the caller's — plausible, not +faithful, which is the engine's stated contract. + +### Responses + +The JSON protocols get a JSON body. `query` and `rest-xml` get XML, and they do +not share an envelope: botocore's query parser looks for `` +nested inside `` and, given anything else, returns a result +with nothing in it rather than an error, while its `rest-xml` parser maps the +root element's children straight onto the output shape. List entries are wrapped +in ``, which is AWS's default for both dialects; a model that flattens a +list gets the unflattened form, because the engine has no flattening +information. No `xmlns` is emitted — botocore strips namespaces before matching +element names. + +### Declining + +A request whose method and path match no route in the service's table, or whose +`Action` names an operation the service did not register, is **declined** with +`InvalidAction` and never served from the store. That is what keeps a registered +service from answering for operations it does not model — and it matters most +for `rest-xml`, because `DetectProtocol` routes anything it cannot classify to +S3. ## Fidelity tiers From 564bc2f2181ecf2dbb9d6fa18dae62589835f55e Mon Sep 17 00:00:00 2001 From: Sung-Kyu Yoo Date: Sun, 6 Sep 2026 02:02:32 +0900 Subject: [PATCH 09/10] chore: point the changelog fragments at the real PR number --- changes/unreleased/Added-20260905-201000.yaml | 2 +- changes/unreleased/Changed-20260905-201001.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/changes/unreleased/Added-20260905-201000.yaml b/changes/unreleased/Added-20260905-201000.yaml index 7886beb8..2e4809ae 100644 --- a/changes/unreleased/Added-20260905-201000.yaml +++ b/changes/unreleased/Added-20260905-201000.yaml @@ -2,4 +2,4 @@ kind: Added body: 'The generic CRUD engine now serves every protocol DevCloud registers. `rest-xml` and `query` were the last two: `rest-xml` recovers its operation from the request method and path against the model''s URI templates, like `rest-json`, and `query` reads it from the `Action` field of the form body. 112 operations move from `unimplemented` to `auto-crud` — 94 in `s3-control` and 18 in `elastic-load-balancing` — and protocol is no longer a reason any registered service serves nothing' time: 2026-09-05T20:10:00.000000+09:00 custom: - Issue: "142" + Issue: "143" diff --git a/changes/unreleased/Changed-20260905-201001.yaml b/changes/unreleased/Changed-20260905-201001.yaml index 5ce6fab8..ee0438d2 100644 --- a/changes/unreleased/Changed-20260905-201001.yaml +++ b/changes/unreleased/Changed-20260905-201001.yaml @@ -2,4 +2,4 @@ kind: Changed body: '`rest-xml` request bodies are still not buffered by the gateway, now by an explicit rule rather than as a side effect of the protocol being unservable. The engine serves `rest-xml` from the path and query alone, so S3''s large binary uploads keep streaming; `crud.NeedsBody` is the predicate and a test fails if the body is read' time: 2026-09-05T20:10:01.000000+09:00 custom: - Issue: "142" + Issue: "143" From 9804d7ba6d3b98490e0bf9adbc0a01ed10772d45 Mon Sep 17 00:00:00 2001 From: Sung-Kyu Yoo Date: Sun, 6 Sep 2026 02:07:08 +0900 Subject: [PATCH 10/10] fix: check the error golangci-lint asks about in the XML encoder errcheck flagged both xml.EscapeText calls. The error is the Writer's and a strings.Builder never fails a write, so the discard is explicit with the reason attached rather than implicit. Found by running golangci-lint locally: every CI workflow in this repo is gated on `pull_request: branches: [main]`, so a PR stacked on another branch gets no CI at all beyond the labeler. --- internal/shared/crud/xml.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/internal/shared/crud/xml.go b/internal/shared/crud/xml.go index 333ab48a..91f9dd0a 100644 --- a/internal/shared/crud/xml.go +++ b/internal/shared/crud/xml.go @@ -85,13 +85,14 @@ func writeValue(b *strings.Builder, value any) { } case string: - xml.EscapeText(b, []byte(val)) + // The error is the Writer's, and a strings.Builder never fails a write. + _ = xml.EscapeText(b, []byte(val)) default: // Numbers and bools. fmt renders these the way AWS does, and escaping // is applied anyway because the branch is reachable from a caller's // arbitrary JSON body, not only from the two types named. - xml.EscapeText(b, []byte(fmt.Sprint(val))) + _ = xml.EscapeText(b, []byte(fmt.Sprint(val))) } }