diff --git a/internal/tfprotov5tov6/tfprotov5tov6.go b/internal/tfprotov5tov6/tfprotov5tov6.go index 040d69d..4f6ac79 100644 --- a/internal/tfprotov5tov6/tfprotov5tov6.go +++ b/internal/tfprotov5tov6/tfprotov5tov6.go @@ -304,7 +304,7 @@ func GetMetadataResponse(in *tfprotov5.GetMetadataResponse) *tfprotov6.GetMetada DataSources: make([]tfprotov6.DataSourceMetadata, 0, len(in.DataSources)), Diagnostics: Diagnostics(in.Diagnostics), EphemeralResources: make([]tfprotov6.EphemeralResourceMetadata, 0, len(in.Resources)), - ListResources: make([]tfprotov6.ListResourceMetadata, 0, len(in.Resources)), + ListResources: make([]tfprotov6.ListResourceMetadata, 0, len(in.ListResources)), Functions: make([]tfprotov6.FunctionMetadata, 0, len(in.Functions)), Resources: make([]tfprotov6.ResourceMetadata, 0, len(in.Resources)), ServerCapabilities: ServerCapabilities(in.ServerCapabilities), diff --git a/internal/tfprotov6tov5/tfprotov6tov5.go b/internal/tfprotov6tov5/tfprotov6tov5.go index 96b6ff5..6d35376 100644 --- a/internal/tfprotov6tov5/tfprotov6tov5.go +++ b/internal/tfprotov6tov5/tfprotov6tov5.go @@ -309,7 +309,7 @@ func GetMetadataResponse(in *tfprotov6.GetMetadataResponse) *tfprotov5.GetMetada DataSources: make([]tfprotov5.DataSourceMetadata, 0, len(in.DataSources)), Diagnostics: Diagnostics(in.Diagnostics), EphemeralResources: make([]tfprotov5.EphemeralResourceMetadata, 0, len(in.Resources)), - ListResources: make([]tfprotov5.ListResourceMetadata, 0, len(in.Resources)), + ListResources: make([]tfprotov5.ListResourceMetadata, 0, len(in.ListResources)), Functions: make([]tfprotov5.FunctionMetadata, 0, len(in.Functions)), Resources: make([]tfprotov5.ResourceMetadata, 0, len(in.Resources)), ServerCapabilities: ServerCapabilities(in.ServerCapabilities), diff --git a/tf5muxserver/mux_server_GetMetadata_test.go b/tf5muxserver/mux_server_GetMetadata_test.go index 604b628..ba4dfd3 100644 --- a/tf5muxserver/mux_server_GetMetadata_test.go +++ b/tf5muxserver/mux_server_GetMetadata_test.go @@ -22,6 +22,7 @@ func TestMuxServerGetMetadata(t *testing.T) { expectedDataSources []tfprotov5.DataSourceMetadata expectedDiagnostics []*tfprotov5.Diagnostic expectedEphemeralResources []tfprotov5.EphemeralResourceMetadata + expectedListResources []tfprotov5.ListResourceMetadata expectedFunctions []tfprotov5.FunctionMetadata expectedResources []tfprotov5.ResourceMetadata expectedServerCapabilities *tfprotov5.ServerCapabilities @@ -56,6 +57,14 @@ func TestMuxServerGetMetadata(t *testing.T) { TypeName: "test_bar", }, }, + ListResources: []tfprotov5.ListResourceMetadata{ + { + TypeName: "test_foo", + }, + { + TypeName: "test_bar", + }, + }, }, }).ProviderServer, (&tf5testserver.TestServer{ @@ -86,6 +95,11 @@ func TestMuxServerGetMetadata(t *testing.T) { TypeName: "test_quux", }, }, + ListResources: []tfprotov5.ListResourceMetadata{ + { + TypeName: "test_quux", + }, + }, }, }).ProviderServer, }, @@ -133,6 +147,17 @@ func TestMuxServerGetMetadata(t *testing.T) { TypeName: "test_quux", }, }, + expectedListResources: []tfprotov5.ListResourceMetadata{ + { + TypeName: "test_foo", + }, + { + TypeName: "test_bar", + }, + { + TypeName: "test_quux", + }, + }, expectedServerCapabilities: &tfprotov5.ServerCapabilities{ GetProviderSchemaOptional: true, MoveResourceState: true, @@ -176,6 +201,7 @@ func TestMuxServerGetMetadata(t *testing.T) { }, }, expectedEphemeralResources: []tfprotov5.EphemeralResourceMetadata{}, + expectedListResources: []tfprotov5.ListResourceMetadata{}, expectedFunctions: []tfprotov5.FunctionMetadata{}, expectedResources: []tfprotov5.ResourceMetadata{}, expectedServerCapabilities: &tfprotov5.ServerCapabilities{ @@ -221,6 +247,53 @@ func TestMuxServerGetMetadata(t *testing.T) { TypeName: "test_foo", }, }, + expectedListResources: []tfprotov5.ListResourceMetadata{}, + expectedFunctions: []tfprotov5.FunctionMetadata{}, + expectedResources: []tfprotov5.ResourceMetadata{}, + expectedServerCapabilities: &tfprotov5.ServerCapabilities{ + GetProviderSchemaOptional: true, + MoveResourceState: true, + PlanDestroy: true, + }, + }, + "duplicate-list-resource-type": { + servers: []func() tfprotov5.ProviderServer{ + (&tf5testserver.TestServer{ + GetMetadataResponse: &tfprotov5.GetMetadataResponse{ + ListResources: []tfprotov5.ListResourceMetadata{ + { + TypeName: "test_foo", + }, + }, + }, + }).ProviderServer, + (&tf5testserver.TestServer{ + GetMetadataResponse: &tfprotov5.GetMetadataResponse{ + ListResources: []tfprotov5.ListResourceMetadata{ + { + TypeName: "test_foo", + }, + }, + }, + }).ProviderServer, + }, + expectedDataSources: []tfprotov5.DataSourceMetadata{}, + expectedDiagnostics: []*tfprotov5.Diagnostic{ + { + Severity: tfprotov5.DiagnosticSeverityError, + Summary: "Invalid Provider Server Combination", + Detail: "The combined provider has multiple implementations of the same list resource type across underlying providers. " + + "List resource types must be implemented by only one underlying provider. " + + "This is always an issue in the provider implementation and should be reported to the provider developers.\n\n" + + "Duplicate list resource type: test_foo", + }, + }, + expectedEphemeralResources: []tfprotov5.EphemeralResourceMetadata{}, + expectedListResources: []tfprotov5.ListResourceMetadata{ + { + TypeName: "test_foo", + }, + }, expectedFunctions: []tfprotov5.FunctionMetadata{}, expectedResources: []tfprotov5.ResourceMetadata{}, expectedServerCapabilities: &tfprotov5.ServerCapabilities{ @@ -262,6 +335,7 @@ func TestMuxServerGetMetadata(t *testing.T) { }, }, expectedEphemeralResources: []tfprotov5.EphemeralResourceMetadata{}, + expectedListResources: []tfprotov5.ListResourceMetadata{}, expectedFunctions: []tfprotov5.FunctionMetadata{ { Name: "test_function", @@ -307,6 +381,7 @@ func TestMuxServerGetMetadata(t *testing.T) { }, }, expectedEphemeralResources: []tfprotov5.EphemeralResourceMetadata{}, + expectedListResources: []tfprotov5.ListResourceMetadata{}, expectedFunctions: []tfprotov5.FunctionMetadata{}, expectedResources: []tfprotov5.ResourceMetadata{ { @@ -347,6 +422,7 @@ func TestMuxServerGetMetadata(t *testing.T) { }, expectedDataSources: []tfprotov5.DataSourceMetadata{}, expectedEphemeralResources: []tfprotov5.EphemeralResourceMetadata{}, + expectedListResources: []tfprotov5.ListResourceMetadata{}, expectedFunctions: []tfprotov5.FunctionMetadata{}, expectedResources: []tfprotov5.ResourceMetadata{ { @@ -387,6 +463,7 @@ func TestMuxServerGetMetadata(t *testing.T) { }, }, expectedEphemeralResources: []tfprotov5.EphemeralResourceMetadata{}, + expectedListResources: []tfprotov5.ListResourceMetadata{}, expectedFunctions: []tfprotov5.FunctionMetadata{}, expectedResources: []tfprotov5.ResourceMetadata{}, expectedServerCapabilities: &tfprotov5.ServerCapabilities{ @@ -435,6 +512,7 @@ func TestMuxServerGetMetadata(t *testing.T) { }, }, expectedEphemeralResources: []tfprotov5.EphemeralResourceMetadata{}, + expectedListResources: []tfprotov5.ListResourceMetadata{}, expectedFunctions: []tfprotov5.FunctionMetadata{}, expectedResources: []tfprotov5.ResourceMetadata{}, expectedServerCapabilities: &tfprotov5.ServerCapabilities{ @@ -468,6 +546,7 @@ func TestMuxServerGetMetadata(t *testing.T) { }, }, expectedEphemeralResources: []tfprotov5.EphemeralResourceMetadata{}, + expectedListResources: []tfprotov5.ListResourceMetadata{}, expectedFunctions: []tfprotov5.FunctionMetadata{}, expectedResources: []tfprotov5.ResourceMetadata{}, expectedServerCapabilities: &tfprotov5.ServerCapabilities{ @@ -516,6 +595,7 @@ func TestMuxServerGetMetadata(t *testing.T) { }, }, expectedEphemeralResources: []tfprotov5.EphemeralResourceMetadata{}, + expectedListResources: []tfprotov5.ListResourceMetadata{}, expectedFunctions: []tfprotov5.FunctionMetadata{}, expectedResources: []tfprotov5.ResourceMetadata{}, expectedServerCapabilities: &tfprotov5.ServerCapabilities{ @@ -564,6 +644,7 @@ func TestMuxServerGetMetadata(t *testing.T) { }, }, expectedEphemeralResources: []tfprotov5.EphemeralResourceMetadata{}, + expectedListResources: []tfprotov5.ListResourceMetadata{}, expectedFunctions: []tfprotov5.FunctionMetadata{}, expectedResources: []tfprotov5.ResourceMetadata{}, expectedServerCapabilities: &tfprotov5.ServerCapabilities{ @@ -603,6 +684,10 @@ func TestMuxServerGetMetadata(t *testing.T) { t.Errorf("ephemeral resources didn't match expectations: %s", diff) } + if diff := cmp.Diff(resp.ListResources, testCase.expectedListResources); diff != "" { + t.Errorf("list resources didn't match expectations: %s", diff) + } + if diff := cmp.Diff(resp.Functions, testCase.expectedFunctions); diff != "" { t.Errorf("functions didn't match expectations: %s", diff) } diff --git a/tf5muxserver/mux_server_GetProviderSchema_test.go b/tf5muxserver/mux_server_GetProviderSchema_test.go index 52eb6bc..5faea90 100644 --- a/tf5muxserver/mux_server_GetProviderSchema_test.go +++ b/tf5muxserver/mux_server_GetProviderSchema_test.go @@ -23,6 +23,7 @@ func TestMuxServerGetProviderSchema(t *testing.T) { expectedDataSourceSchemas map[string]*tfprotov5.Schema expectedDiagnostics []*tfprotov5.Diagnostic expectedEphemeralResourcesSchemas map[string]*tfprotov5.Schema + expectedListResourcesSchemas map[string]*tfprotov5.Schema expectedFunctions map[string]*tfprotov5.Function expectedProviderSchema *tfprotov5.Schema expectedProviderMetaSchema *tfprotov5.Schema @@ -192,6 +193,45 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, }, }, + ListResourceSchemas: map[string]*tfprotov5.Schema{ + "test_list_foo": { + Version: 1, + Block: &tfprotov5.SchemaBlock{ + Version: 1, + Attributes: []*tfprotov5.SchemaAttribute{ + { + Name: "query_name", + Type: tftypes.String, + Required: true, + Description: "input the query name", + DescriptionKind: tfprotov5.StringKindPlain, + }, + }, + }, + }, + "test_list_bar": { + Version: 1, + Block: &tfprotov5.SchemaBlock{ + Version: 1, + Attributes: []*tfprotov5.SchemaAttribute{ + { + Name: "filter", + Type: tftypes.String, + Optional: true, + Description: "search filter", + DescriptionKind: tfprotov5.StringKindPlain, + }, + { + Name: "prefix", + Type: tftypes.String, + Optional: true, + Description: "name prefix", + DescriptionKind: tfprotov5.StringKindPlain, + }, + }, + }, + }, + }, }, }).ProviderServer, (&tf5testserver.TestServer{ @@ -336,6 +376,23 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, }, }, + ListResourceSchemas: map[string]*tfprotov5.Schema{ + "test_list_foobar": { + Version: 1, + Block: &tfprotov5.SchemaBlock{ + Version: 1, + Attributes: []*tfprotov5.SchemaAttribute{ + { + Name: "query_name", + Type: tftypes.String, + Computed: true, + Description: "A generated query name", + DescriptionKind: tfprotov5.StringKindPlain, + }, + }, + }, + }, + }, }, }).ProviderServer, }, @@ -573,6 +630,60 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, }, }, + expectedListResourcesSchemas: map[string]*tfprotov5.Schema{ + "test_list_foo": { + Version: 1, + Block: &tfprotov5.SchemaBlock{ + Version: 1, + Attributes: []*tfprotov5.SchemaAttribute{ + { + Name: "query_name", + Type: tftypes.String, + Required: true, + Description: "input the query name", + DescriptionKind: tfprotov5.StringKindPlain, + }, + }, + }, + }, + "test_list_bar": { + Version: 1, + Block: &tfprotov5.SchemaBlock{ + Version: 1, + Attributes: []*tfprotov5.SchemaAttribute{ + { + Name: "filter", + Type: tftypes.String, + Optional: true, + Description: "search filter", + DescriptionKind: tfprotov5.StringKindPlain, + }, + { + Name: "prefix", + Type: tftypes.String, + Optional: true, + Description: "name prefix", + DescriptionKind: tfprotov5.StringKindPlain, + }, + }, + }, + }, + "test_list_foobar": { + Version: 1, + Block: &tfprotov5.SchemaBlock{ + Version: 1, + Attributes: []*tfprotov5.SchemaAttribute{ + { + Name: "query_name", + Type: tftypes.String, + Computed: true, + Description: "A generated query name", + DescriptionKind: tfprotov5.StringKindPlain, + }, + }, + }, + }, + }, expectedServerCapabilities: &tfprotov5.ServerCapabilities{ GetProviderSchemaOptional: true, MoveResourceState: true, @@ -610,6 +721,7 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, }, expectedEphemeralResourcesSchemas: map[string]*tfprotov5.Schema{}, + expectedListResourcesSchemas: map[string]*tfprotov5.Schema{}, expectedFunctions: map[string]*tfprotov5.Function{}, expectedResourceSchemas: map[string]*tfprotov5.Schema{}, expectedServerCapabilities: &tfprotov5.ServerCapabilities{ @@ -649,6 +761,47 @@ func TestMuxServerGetProviderSchema(t *testing.T) { expectedEphemeralResourcesSchemas: map[string]*tfprotov5.Schema{ "test_foo": {}, }, + expectedListResourcesSchemas: map[string]*tfprotov5.Schema{}, + expectedFunctions: map[string]*tfprotov5.Function{}, + expectedResourceSchemas: map[string]*tfprotov5.Schema{}, + expectedServerCapabilities: &tfprotov5.ServerCapabilities{ + GetProviderSchemaOptional: true, + MoveResourceState: true, + PlanDestroy: true, + }, + }, + "duplicate-list-resource-type": { + servers: []func() tfprotov5.ProviderServer{ + (&tf5testserver.TestServer{ + GetProviderSchemaResponse: &tfprotov5.GetProviderSchemaResponse{ + ListResourceSchemas: map[string]*tfprotov5.Schema{ + "test_foo": {}, + }, + }, + }).ProviderServer, + (&tf5testserver.TestServer{ + GetProviderSchemaResponse: &tfprotov5.GetProviderSchemaResponse{ + ListResourceSchemas: map[string]*tfprotov5.Schema{ + "test_foo": {}, + }, + }, + }).ProviderServer, + }, + expectedDataSourceSchemas: map[string]*tfprotov5.Schema{}, + expectedDiagnostics: []*tfprotov5.Diagnostic{ + { + Severity: tfprotov5.DiagnosticSeverityError, + Summary: "Invalid Provider Server Combination", + Detail: "The combined provider has multiple implementations of the same list resource type across underlying providers. " + + "List resource types must be implemented by only one underlying provider. " + + "This is always an issue in the provider implementation and should be reported to the provider developers.\n\n" + + "Duplicate list resource type: test_foo", + }, + }, + expectedEphemeralResourcesSchemas: map[string]*tfprotov5.Schema{}, + expectedListResourcesSchemas: map[string]*tfprotov5.Schema{ + "test_foo": {}, + }, expectedFunctions: map[string]*tfprotov5.Function{}, expectedResourceSchemas: map[string]*tfprotov5.Schema{}, expectedServerCapabilities: &tfprotov5.ServerCapabilities{ @@ -686,6 +839,7 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, }, expectedEphemeralResourcesSchemas: map[string]*tfprotov5.Schema{}, + expectedListResourcesSchemas: map[string]*tfprotov5.Schema{}, expectedFunctions: map[string]*tfprotov5.Function{ "test_function": {}, }, @@ -725,6 +879,7 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, }, expectedEphemeralResourcesSchemas: map[string]*tfprotov5.Schema{}, + expectedListResourcesSchemas: map[string]*tfprotov5.Schema{}, expectedFunctions: map[string]*tfprotov5.Function{}, expectedResourceSchemas: map[string]*tfprotov5.Schema{ "test_foo": {}, @@ -803,6 +958,7 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, }, expectedEphemeralResourcesSchemas: map[string]*tfprotov5.Schema{}, + expectedListResourcesSchemas: map[string]*tfprotov5.Schema{}, expectedFunctions: map[string]*tfprotov5.Function{}, expectedProviderSchema: &tfprotov5.Schema{ Block: &tfprotov5.SchemaBlock{ @@ -890,6 +1046,7 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, }, expectedEphemeralResourcesSchemas: map[string]*tfprotov5.Schema{}, + expectedListResourcesSchemas: map[string]*tfprotov5.Schema{}, expectedFunctions: map[string]*tfprotov5.Function{}, expectedProviderMetaSchema: &tfprotov5.Schema{ Block: &tfprotov5.SchemaBlock{ @@ -933,6 +1090,7 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, expectedDataSourceSchemas: map[string]*tfprotov5.Schema{}, expectedEphemeralResourcesSchemas: map[string]*tfprotov5.Schema{}, + expectedListResourcesSchemas: map[string]*tfprotov5.Schema{}, expectedFunctions: map[string]*tfprotov5.Function{}, expectedResourceSchemas: map[string]*tfprotov5.Schema{ "test_with_server_capabilities": {}, @@ -969,6 +1127,7 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, }, expectedEphemeralResourcesSchemas: map[string]*tfprotov5.Schema{}, + expectedListResourcesSchemas: map[string]*tfprotov5.Schema{}, expectedFunctions: map[string]*tfprotov5.Function{}, expectedResourceSchemas: map[string]*tfprotov5.Schema{}, expectedServerCapabilities: &tfprotov5.ServerCapabilities{ @@ -1017,6 +1176,7 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, }, expectedEphemeralResourcesSchemas: map[string]*tfprotov5.Schema{}, + expectedListResourcesSchemas: map[string]*tfprotov5.Schema{}, expectedFunctions: map[string]*tfprotov5.Function{}, expectedResourceSchemas: map[string]*tfprotov5.Schema{}, expectedServerCapabilities: &tfprotov5.ServerCapabilities{ @@ -1050,6 +1210,7 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, }, expectedEphemeralResourcesSchemas: map[string]*tfprotov5.Schema{}, + expectedListResourcesSchemas: map[string]*tfprotov5.Schema{}, expectedFunctions: map[string]*tfprotov5.Function{}, expectedResourceSchemas: map[string]*tfprotov5.Schema{}, expectedServerCapabilities: &tfprotov5.ServerCapabilities{ @@ -1098,6 +1259,7 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, }, expectedEphemeralResourcesSchemas: map[string]*tfprotov5.Schema{}, + expectedListResourcesSchemas: map[string]*tfprotov5.Schema{}, expectedFunctions: map[string]*tfprotov5.Function{}, expectedResourceSchemas: map[string]*tfprotov5.Schema{}, expectedServerCapabilities: &tfprotov5.ServerCapabilities{ @@ -1146,6 +1308,7 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, }, expectedEphemeralResourcesSchemas: map[string]*tfprotov5.Schema{}, + expectedListResourcesSchemas: map[string]*tfprotov5.Schema{}, expectedFunctions: map[string]*tfprotov5.Function{}, expectedResourceSchemas: map[string]*tfprotov5.Schema{}, expectedServerCapabilities: &tfprotov5.ServerCapabilities{ @@ -1185,6 +1348,10 @@ func TestMuxServerGetProviderSchema(t *testing.T) { t.Errorf("ephemeral resources schemas didn't match expectations: %s", diff) } + if diff := cmp.Diff(resp.ListResourceSchemas, testCase.expectedListResourcesSchemas); diff != "" { + t.Errorf("list resources schemas didn't match expectations: %s", diff) + } + if diff := cmp.Diff(resp.Functions, testCase.expectedFunctions); diff != "" { t.Errorf("functions didn't match expectations: %s", diff) } diff --git a/tf5muxserver/mux_server_ValidateListResourceConfig.go b/tf5muxserver/mux_server_ValidateListResourceConfig.go index e392f16..d50b4dc 100644 --- a/tf5muxserver/mux_server_ValidateListResourceConfig.go +++ b/tf5muxserver/mux_server_ValidateListResourceConfig.go @@ -12,7 +12,7 @@ import ( ) func (s *muxServer) ValidateListResourceConfig(ctx context.Context, req *tfprotov5.ValidateListResourceConfigRequest) (*tfprotov5.ValidateListResourceConfigResponse, error) { - rpc := "ValidateListResourceTypeConfig" + rpc := "ValidateListResourceConfig" ctx = logging.InitContext(ctx) ctx = logging.RpcContext(ctx, rpc) diff --git a/tf5to6server/tf5to6server_test.go b/tf5to6server/tf5to6server_test.go index f65e73a..ce4b331 100644 --- a/tf5to6server/tf5to6server_test.go +++ b/tf5to6server/tf5to6server_test.go @@ -812,13 +812,13 @@ func TestV6ToV5ServerValidateListResourceConfig(t *testing.T) { v6server, err := tf5to6server.UpgradeServer(context.Background(), v5server.ProviderServer) if err != nil { - t.Fatalf("unexpected error downgrading server: %s", err) + t.Fatalf("unexpected error upgrading server: %s", err) } //nolint:staticcheck // Intentionally verifying interface implementation listResourceServer, ok := v6server.(tfprotov6.ProviderServerWithListResource) if !ok { - t.Fatal("v6server should implement tfprotov6.ProviderServerWithResourceIdentity") + t.Fatal("v6server should implement tfprotov6.ProviderServerWithListResource") } _, err = listResourceServer.ValidateListResourceConfig(ctx, &tfprotov6.ValidateListResourceConfigRequest{ diff --git a/tf6muxserver/mux_server_GetMetadata.go b/tf6muxserver/mux_server_GetMetadata.go index 8a2f1e5..92c4c4f 100644 --- a/tf6muxserver/mux_server_GetMetadata.go +++ b/tf6muxserver/mux_server_GetMetadata.go @@ -27,6 +27,7 @@ func (s *muxServer) GetMetadata(ctx context.Context, req *tfprotov6.GetMetadataR resp := &tfprotov6.GetMetadataResponse{ DataSources: make([]tfprotov6.DataSourceMetadata, 0), EphemeralResources: make([]tfprotov6.EphemeralResourceMetadata, 0), + ListResources: make([]tfprotov6.ListResourceMetadata, 0), Functions: make([]tfprotov6.FunctionMetadata, 0), Resources: make([]tfprotov6.ResourceMetadata, 0), ServerCapabilities: serverCapabilities, @@ -66,6 +67,17 @@ func (s *muxServer) GetMetadata(ctx context.Context, req *tfprotov6.GetMetadataR resp.EphemeralResources = append(resp.EphemeralResources, ephemeralResource) } + for _, listResource := range serverResp.ListResources { + if listResourceMetadataContainsTypeName(resp.ListResources, listResource.TypeName) { + resp.Diagnostics = append(resp.Diagnostics, listResourceDuplicateError(listResource.TypeName)) + + continue + } + + s.listResources[listResource.TypeName] = server + resp.ListResources = append(resp.ListResources, listResource) + } + for _, function := range serverResp.Functions { if functionMetadataContainsName(resp.Functions, function.Name) { resp.Diagnostics = append(resp.Diagnostics, functionDuplicateError(function.Name)) @@ -113,6 +125,16 @@ func ephemeralResourceMetadataContainsTypeName(metadatas []tfprotov6.EphemeralRe return false } +func listResourceMetadataContainsTypeName(metadatas []tfprotov6.ListResourceMetadata, typeName string) bool { + for _, metadata := range metadatas { + if typeName == metadata.TypeName { + return true + } + } + + return false +} + func functionMetadataContainsName(metadatas []tfprotov6.FunctionMetadata, name string) bool { for _, metadata := range metadatas { if name == metadata.Name { diff --git a/tf6muxserver/mux_server_GetMetadata_test.go b/tf6muxserver/mux_server_GetMetadata_test.go index 6449e63..dae8138 100644 --- a/tf6muxserver/mux_server_GetMetadata_test.go +++ b/tf6muxserver/mux_server_GetMetadata_test.go @@ -22,6 +22,7 @@ func TestMuxServerGetMetadata(t *testing.T) { expectedDataSources []tfprotov6.DataSourceMetadata expectedDiagnostics []*tfprotov6.Diagnostic expectedEphemeralResources []tfprotov6.EphemeralResourceMetadata + expectedListResources []tfprotov6.ListResourceMetadata expectedFunctions []tfprotov6.FunctionMetadata expectedResources []tfprotov6.ResourceMetadata expectedServerCapabilities *tfprotov6.ServerCapabilities @@ -56,6 +57,14 @@ func TestMuxServerGetMetadata(t *testing.T) { TypeName: "test_bar", }, }, + ListResources: []tfprotov6.ListResourceMetadata{ + { + TypeName: "test_foo", + }, + { + TypeName: "test_bar", + }, + }, }, }).ProviderServer, (&tf6testserver.TestServer{ @@ -86,6 +95,11 @@ func TestMuxServerGetMetadata(t *testing.T) { TypeName: "test_quux", }, }, + ListResources: []tfprotov6.ListResourceMetadata{ + { + TypeName: "test_quux", + }, + }, }, }).ProviderServer, }, @@ -133,6 +147,17 @@ func TestMuxServerGetMetadata(t *testing.T) { TypeName: "test_quux", }, }, + expectedListResources: []tfprotov6.ListResourceMetadata{ + { + TypeName: "test_foo", + }, + { + TypeName: "test_bar", + }, + { + TypeName: "test_quux", + }, + }, expectedServerCapabilities: &tfprotov6.ServerCapabilities{ GetProviderSchemaOptional: true, MoveResourceState: true, @@ -176,6 +201,7 @@ func TestMuxServerGetMetadata(t *testing.T) { }, }, expectedEphemeralResources: []tfprotov6.EphemeralResourceMetadata{}, + expectedListResources: []tfprotov6.ListResourceMetadata{}, expectedFunctions: []tfprotov6.FunctionMetadata{}, expectedResources: []tfprotov6.ResourceMetadata{}, expectedServerCapabilities: &tfprotov6.ServerCapabilities{ @@ -221,8 +247,55 @@ func TestMuxServerGetMetadata(t *testing.T) { TypeName: "test_foo", }, }, - expectedFunctions: []tfprotov6.FunctionMetadata{}, - expectedResources: []tfprotov6.ResourceMetadata{}, + expectedListResources: []tfprotov6.ListResourceMetadata{}, + expectedFunctions: []tfprotov6.FunctionMetadata{}, + expectedResources: []tfprotov6.ResourceMetadata{}, + expectedServerCapabilities: &tfprotov6.ServerCapabilities{ + GetProviderSchemaOptional: true, + MoveResourceState: true, + PlanDestroy: true, + }, + }, + "duplicate-list-resource-type": { + servers: []func() tfprotov6.ProviderServer{ + (&tf6testserver.TestServer{ + GetMetadataResponse: &tfprotov6.GetMetadataResponse{ + ListResources: []tfprotov6.ListResourceMetadata{ + { + TypeName: "test_foo", + }, + }, + }, + }).ProviderServer, + (&tf6testserver.TestServer{ + GetMetadataResponse: &tfprotov6.GetMetadataResponse{ + ListResources: []tfprotov6.ListResourceMetadata{ + { + TypeName: "test_foo", + }, + }, + }, + }).ProviderServer, + }, + expectedDataSources: []tfprotov6.DataSourceMetadata{}, + expectedDiagnostics: []*tfprotov6.Diagnostic{ + { + Severity: tfprotov6.DiagnosticSeverityError, + Summary: "Invalid Provider Server Combination", + Detail: "The combined provider has multiple implementations of the same list resource type across underlying providers. " + + "List resource types must be implemented by only one underlying provider. " + + "This is always an issue in the provider implementation and should be reported to the provider developers.\n\n" + + "Duplicate list resource type: test_foo", + }, + }, + expectedListResources: []tfprotov6.ListResourceMetadata{ + { + TypeName: "test_foo", + }, + }, + expectedEphemeralResources: []tfprotov6.EphemeralResourceMetadata{}, + expectedFunctions: []tfprotov6.FunctionMetadata{}, + expectedResources: []tfprotov6.ResourceMetadata{}, expectedServerCapabilities: &tfprotov6.ServerCapabilities{ GetProviderSchemaOptional: true, MoveResourceState: true, @@ -262,6 +335,7 @@ func TestMuxServerGetMetadata(t *testing.T) { }, }, expectedEphemeralResources: []tfprotov6.EphemeralResourceMetadata{}, + expectedListResources: []tfprotov6.ListResourceMetadata{}, expectedFunctions: []tfprotov6.FunctionMetadata{ { Name: "test_function", @@ -307,6 +381,7 @@ func TestMuxServerGetMetadata(t *testing.T) { }, }, expectedEphemeralResources: []tfprotov6.EphemeralResourceMetadata{}, + expectedListResources: []tfprotov6.ListResourceMetadata{}, expectedFunctions: []tfprotov6.FunctionMetadata{}, expectedResources: []tfprotov6.ResourceMetadata{ { @@ -347,6 +422,7 @@ func TestMuxServerGetMetadata(t *testing.T) { }, expectedDataSources: []tfprotov6.DataSourceMetadata{}, expectedEphemeralResources: []tfprotov6.EphemeralResourceMetadata{}, + expectedListResources: []tfprotov6.ListResourceMetadata{}, expectedFunctions: []tfprotov6.FunctionMetadata{}, expectedResources: []tfprotov6.ResourceMetadata{ { @@ -387,6 +463,7 @@ func TestMuxServerGetMetadata(t *testing.T) { }, }, expectedEphemeralResources: []tfprotov6.EphemeralResourceMetadata{}, + expectedListResources: []tfprotov6.ListResourceMetadata{}, expectedFunctions: []tfprotov6.FunctionMetadata{}, expectedResources: []tfprotov6.ResourceMetadata{}, expectedServerCapabilities: &tfprotov6.ServerCapabilities{ @@ -435,6 +512,7 @@ func TestMuxServerGetMetadata(t *testing.T) { }, }, expectedEphemeralResources: []tfprotov6.EphemeralResourceMetadata{}, + expectedListResources: []tfprotov6.ListResourceMetadata{}, expectedFunctions: []tfprotov6.FunctionMetadata{}, expectedResources: []tfprotov6.ResourceMetadata{}, expectedServerCapabilities: &tfprotov6.ServerCapabilities{ @@ -468,6 +546,7 @@ func TestMuxServerGetMetadata(t *testing.T) { }, }, expectedEphemeralResources: []tfprotov6.EphemeralResourceMetadata{}, + expectedListResources: []tfprotov6.ListResourceMetadata{}, expectedFunctions: []tfprotov6.FunctionMetadata{}, expectedResources: []tfprotov6.ResourceMetadata{}, expectedServerCapabilities: &tfprotov6.ServerCapabilities{ @@ -516,6 +595,7 @@ func TestMuxServerGetMetadata(t *testing.T) { }, }, expectedEphemeralResources: []tfprotov6.EphemeralResourceMetadata{}, + expectedListResources: []tfprotov6.ListResourceMetadata{}, expectedFunctions: []tfprotov6.FunctionMetadata{}, expectedResources: []tfprotov6.ResourceMetadata{}, expectedServerCapabilities: &tfprotov6.ServerCapabilities{ @@ -564,6 +644,7 @@ func TestMuxServerGetMetadata(t *testing.T) { }, }, expectedEphemeralResources: []tfprotov6.EphemeralResourceMetadata{}, + expectedListResources: []tfprotov6.ListResourceMetadata{}, expectedFunctions: []tfprotov6.FunctionMetadata{}, expectedResources: []tfprotov6.ResourceMetadata{}, expectedServerCapabilities: &tfprotov6.ServerCapabilities{ @@ -607,6 +688,10 @@ func TestMuxServerGetMetadata(t *testing.T) { t.Errorf("ephemeral resources didn't match expectations: %s", diff) } + if diff := cmp.Diff(resp.ListResources, testCase.expectedListResources); diff != "" { + t.Errorf("list resources didn't match expectations: %s", diff) + } + if diff := cmp.Diff(resp.Resources, testCase.expectedResources); diff != "" { t.Errorf("resources didn't match expectations: %s", diff) } diff --git a/tf6muxserver/mux_server_GetProviderSchema.go b/tf6muxserver/mux_server_GetProviderSchema.go index 4d0db7d..571bf00 100644 --- a/tf6muxserver/mux_server_GetProviderSchema.go +++ b/tf6muxserver/mux_server_GetProviderSchema.go @@ -26,6 +26,7 @@ func (s *muxServer) GetProviderSchema(ctx context.Context, req *tfprotov6.GetPro resp := &tfprotov6.GetProviderSchemaResponse{ DataSourceSchemas: make(map[string]*tfprotov6.Schema), + ListResourceSchemas: make(map[string]*tfprotov6.Schema), EphemeralResourceSchemas: make(map[string]*tfprotov6.Schema), Functions: make(map[string]*tfprotov6.Function), ResourceSchemas: make(map[string]*tfprotov6.Schema), @@ -118,6 +119,17 @@ func (s *muxServer) GetProviderSchema(ctx context.Context, req *tfprotov6.GetPro s.ephemeralResources[ephemeralResourceType] = server resp.EphemeralResourceSchemas[ephemeralResourceType] = schema } + + for listResourceType, schema := range serverResp.ListResourceSchemas { + if _, ok := resp.ListResourceSchemas[listResourceType]; ok { + resp.Diagnostics = append(resp.Diagnostics, listResourceDuplicateError(listResourceType)) + + continue + } + + s.listResources[listResourceType] = server + resp.ListResourceSchemas[listResourceType] = schema + } } s.serverDiscoveryComplete = true diff --git a/tf6muxserver/mux_server_GetProviderSchema_test.go b/tf6muxserver/mux_server_GetProviderSchema_test.go index 2e83699..bd939f9 100644 --- a/tf6muxserver/mux_server_GetProviderSchema_test.go +++ b/tf6muxserver/mux_server_GetProviderSchema_test.go @@ -23,6 +23,7 @@ func TestMuxServerGetProviderSchema(t *testing.T) { expectedDataSourceSchemas map[string]*tfprotov6.Schema expectedDiagnostics []*tfprotov6.Diagnostic expectedEphemeralResourcesSchemas map[string]*tfprotov6.Schema + expectedListResourcesSchemas map[string]*tfprotov6.Schema expectedFunctions map[string]*tfprotov6.Function expectedProviderSchema *tfprotov6.Schema expectedProviderMetaSchema *tfprotov6.Schema @@ -192,6 +193,45 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, }, }, + ListResourceSchemas: map[string]*tfprotov6.Schema{ + "test_list_foo": { + Version: 1, + Block: &tfprotov6.SchemaBlock{ + Version: 1, + Attributes: []*tfprotov6.SchemaAttribute{ + { + Name: "query_name", + Type: tftypes.String, + Required: true, + Description: "input the query name", + DescriptionKind: tfprotov6.StringKindPlain, + }, + }, + }, + }, + "test_list_bar": { + Version: 1, + Block: &tfprotov6.SchemaBlock{ + Version: 1, + Attributes: []*tfprotov6.SchemaAttribute{ + { + Name: "filter", + Type: tftypes.String, + Optional: true, + Description: "search filter", + DescriptionKind: tfprotov6.StringKindPlain, + }, + { + Name: "prefix", + Type: tftypes.String, + Optional: true, + Description: "name prefix", + DescriptionKind: tfprotov6.StringKindPlain, + }, + }, + }, + }, + }, }, }).ProviderServer, (&tf6testserver.TestServer{ @@ -336,6 +376,23 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, }, }, + ListResourceSchemas: map[string]*tfprotov6.Schema{ + "test_list_foobar": { + Version: 1, + Block: &tfprotov6.SchemaBlock{ + Version: 1, + Attributes: []*tfprotov6.SchemaAttribute{ + { + Name: "query_name", + Type: tftypes.String, + Computed: true, + Description: "A generated query name", + DescriptionKind: tfprotov6.StringKindPlain, + }, + }, + }, + }, + }, }, }).ProviderServer, }, @@ -573,6 +630,60 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, }, }, + expectedListResourcesSchemas: map[string]*tfprotov6.Schema{ + "test_list_foo": { + Version: 1, + Block: &tfprotov6.SchemaBlock{ + Version: 1, + Attributes: []*tfprotov6.SchemaAttribute{ + { + Name: "query_name", + Type: tftypes.String, + Required: true, + Description: "input the query name", + DescriptionKind: tfprotov6.StringKindPlain, + }, + }, + }, + }, + "test_list_bar": { + Version: 1, + Block: &tfprotov6.SchemaBlock{ + Version: 1, + Attributes: []*tfprotov6.SchemaAttribute{ + { + Name: "filter", + Type: tftypes.String, + Optional: true, + Description: "search filter", + DescriptionKind: tfprotov6.StringKindPlain, + }, + { + Name: "prefix", + Type: tftypes.String, + Optional: true, + Description: "name prefix", + DescriptionKind: tfprotov6.StringKindPlain, + }, + }, + }, + }, + "test_list_foobar": { + Version: 1, + Block: &tfprotov6.SchemaBlock{ + Version: 1, + Attributes: []*tfprotov6.SchemaAttribute{ + { + Name: "query_name", + Type: tftypes.String, + Computed: true, + Description: "A generated query name", + DescriptionKind: tfprotov6.StringKindPlain, + }, + }, + }, + }, + }, expectedServerCapabilities: &tfprotov6.ServerCapabilities{ GetProviderSchemaOptional: true, MoveResourceState: true, @@ -610,6 +721,7 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, }, expectedEphemeralResourcesSchemas: map[string]*tfprotov6.Schema{}, + expectedListResourcesSchemas: map[string]*tfprotov6.Schema{}, expectedFunctions: map[string]*tfprotov6.Function{}, expectedResourceSchemas: map[string]*tfprotov6.Schema{}, expectedServerCapabilities: &tfprotov6.ServerCapabilities{ @@ -649,8 +761,49 @@ func TestMuxServerGetProviderSchema(t *testing.T) { expectedEphemeralResourcesSchemas: map[string]*tfprotov6.Schema{ "test_foo": {}, }, - expectedFunctions: map[string]*tfprotov6.Function{}, - expectedResourceSchemas: map[string]*tfprotov6.Schema{}, + expectedListResourcesSchemas: map[string]*tfprotov6.Schema{}, + expectedFunctions: map[string]*tfprotov6.Function{}, + expectedResourceSchemas: map[string]*tfprotov6.Schema{}, + expectedServerCapabilities: &tfprotov6.ServerCapabilities{ + GetProviderSchemaOptional: true, + MoveResourceState: true, + PlanDestroy: true, + }, + }, + "duplicate-list-resource-type": { + servers: []func() tfprotov6.ProviderServer{ + (&tf6testserver.TestServer{ + GetProviderSchemaResponse: &tfprotov6.GetProviderSchemaResponse{ + ListResourceSchemas: map[string]*tfprotov6.Schema{ + "test_foo": {}, + }, + }, + }).ProviderServer, + (&tf6testserver.TestServer{ + GetProviderSchemaResponse: &tfprotov6.GetProviderSchemaResponse{ + ListResourceSchemas: map[string]*tfprotov6.Schema{ + "test_foo": {}, + }, + }, + }).ProviderServer, + }, + expectedDataSourceSchemas: map[string]*tfprotov6.Schema{}, + expectedDiagnostics: []*tfprotov6.Diagnostic{ + { + Severity: tfprotov6.DiagnosticSeverityError, + Summary: "Invalid Provider Server Combination", + Detail: "The combined provider has multiple implementations of the same list resource type across underlying providers. " + + "List resource types must be implemented by only one underlying provider. " + + "This is always an issue in the provider implementation and should be reported to the provider developers.\n\n" + + "Duplicate list resource type: test_foo", + }, + }, + expectedListResourcesSchemas: map[string]*tfprotov6.Schema{ + "test_foo": {}, + }, + expectedEphemeralResourcesSchemas: map[string]*tfprotov6.Schema{}, + expectedFunctions: map[string]*tfprotov6.Function{}, + expectedResourceSchemas: map[string]*tfprotov6.Schema{}, expectedServerCapabilities: &tfprotov6.ServerCapabilities{ GetProviderSchemaOptional: true, MoveResourceState: true, @@ -686,6 +839,7 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, }, expectedEphemeralResourcesSchemas: map[string]*tfprotov6.Schema{}, + expectedListResourcesSchemas: map[string]*tfprotov6.Schema{}, expectedFunctions: map[string]*tfprotov6.Function{ "test_function": {}, }, @@ -725,6 +879,7 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, }, expectedEphemeralResourcesSchemas: map[string]*tfprotov6.Schema{}, + expectedListResourcesSchemas: map[string]*tfprotov6.Schema{}, expectedFunctions: map[string]*tfprotov6.Function{}, expectedResourceSchemas: map[string]*tfprotov6.Schema{ "test_foo": {}, @@ -803,6 +958,7 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, }, expectedEphemeralResourcesSchemas: map[string]*tfprotov6.Schema{}, + expectedListResourcesSchemas: map[string]*tfprotov6.Schema{}, expectedFunctions: map[string]*tfprotov6.Function{}, expectedProviderSchema: &tfprotov6.Schema{ Block: &tfprotov6.SchemaBlock{ @@ -890,6 +1046,7 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, }, expectedEphemeralResourcesSchemas: map[string]*tfprotov6.Schema{}, + expectedListResourcesSchemas: map[string]*tfprotov6.Schema{}, expectedFunctions: map[string]*tfprotov6.Function{}, expectedProviderMetaSchema: &tfprotov6.Schema{ Block: &tfprotov6.SchemaBlock{ @@ -932,6 +1089,7 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, expectedDataSourceSchemas: map[string]*tfprotov6.Schema{}, expectedEphemeralResourcesSchemas: map[string]*tfprotov6.Schema{}, + expectedListResourcesSchemas: map[string]*tfprotov6.Schema{}, expectedFunctions: map[string]*tfprotov6.Function{}, expectedResourceSchemas: map[string]*tfprotov6.Schema{ "test_with_server_capabilities": {}, @@ -968,6 +1126,7 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, }, expectedEphemeralResourcesSchemas: map[string]*tfprotov6.Schema{}, + expectedListResourcesSchemas: map[string]*tfprotov6.Schema{}, expectedFunctions: map[string]*tfprotov6.Function{}, expectedResourceSchemas: map[string]*tfprotov6.Schema{}, expectedServerCapabilities: &tfprotov6.ServerCapabilities{ @@ -1016,6 +1175,7 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, }, expectedEphemeralResourcesSchemas: map[string]*tfprotov6.Schema{}, + expectedListResourcesSchemas: map[string]*tfprotov6.Schema{}, expectedFunctions: map[string]*tfprotov6.Function{}, expectedResourceSchemas: map[string]*tfprotov6.Schema{}, expectedServerCapabilities: &tfprotov6.ServerCapabilities{ @@ -1049,6 +1209,7 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, }, expectedEphemeralResourcesSchemas: map[string]*tfprotov6.Schema{}, + expectedListResourcesSchemas: map[string]*tfprotov6.Schema{}, expectedFunctions: map[string]*tfprotov6.Function{}, expectedResourceSchemas: map[string]*tfprotov6.Schema{}, expectedServerCapabilities: &tfprotov6.ServerCapabilities{ @@ -1097,6 +1258,7 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, }, expectedEphemeralResourcesSchemas: map[string]*tfprotov6.Schema{}, + expectedListResourcesSchemas: map[string]*tfprotov6.Schema{}, expectedFunctions: map[string]*tfprotov6.Function{}, expectedResourceSchemas: map[string]*tfprotov6.Schema{}, expectedServerCapabilities: &tfprotov6.ServerCapabilities{ @@ -1145,6 +1307,7 @@ func TestMuxServerGetProviderSchema(t *testing.T) { }, }, expectedEphemeralResourcesSchemas: map[string]*tfprotov6.Schema{}, + expectedListResourcesSchemas: map[string]*tfprotov6.Schema{}, expectedFunctions: map[string]*tfprotov6.Function{}, expectedResourceSchemas: map[string]*tfprotov6.Schema{}, expectedServerCapabilities: &tfprotov6.ServerCapabilities{ @@ -1184,6 +1347,10 @@ func TestMuxServerGetProviderSchema(t *testing.T) { t.Errorf("ephemeral resources schemas didn't match expectations: %s", diff) } + if diff := cmp.Diff(resp.ListResourceSchemas, testCase.expectedListResourcesSchemas); diff != "" { + t.Errorf("list resources schemas didn't match expectations: %s", diff) + } + if diff := cmp.Diff(resp.Functions, testCase.expectedFunctions); diff != "" { t.Errorf("functions didn't match expectations: %s", diff) } diff --git a/tf6muxserver/mux_server_ValidateListResourceConfig.go b/tf6muxserver/mux_server_ValidateListResourceConfig.go index 488a5d7..3f2a844 100644 --- a/tf6muxserver/mux_server_ValidateListResourceConfig.go +++ b/tf6muxserver/mux_server_ValidateListResourceConfig.go @@ -11,7 +11,7 @@ import ( ) func (s *muxServer) ValidateListResourceConfig(ctx context.Context, req *tfprotov6.ValidateListResourceConfigRequest) (*tfprotov6.ValidateListResourceConfigResponse, error) { - rpc := "ValidateListResourceTypeConfig" + rpc := "ValidateListResourceConfig" ctx = logging.InitContext(ctx) ctx = logging.RpcContext(ctx, rpc) diff --git a/tf6to5server/tf6to5server_test.go b/tf6to5server/tf6to5server_test.go index 85c020c..e3abbff 100644 --- a/tf6to5server/tf6to5server_test.go +++ b/tf6to5server/tf6to5server_test.go @@ -916,7 +916,7 @@ func TestV6ToV5ServerValidateListResourceConfig(t *testing.T) { //nolint:staticcheck // Intentionally verifying interface implementation listResourceServer, ok := v5server.(tfprotov5.ProviderServerWithListResource) if !ok { - t.Fatal("v6server should implement tfprotov5.ProviderServerWithResourceIdentity") + t.Fatal("v6server should implement tfprotov5.ProviderServerWithListResource") } _, err = listResourceServer.ValidateListResourceConfig(ctx, &tfprotov5.ValidateListResourceConfigRequest{