From 1a28d748330ec57764580372b287c4c3af454e3b Mon Sep 17 00:00:00 2001
From: Aastha Mahendru <aastha.mahendru@mongodb.com>
Date: Tue, 15 Oct 2024 17:21:00 +0100
Subject: [PATCH 01/12] support list and nested list

---
 tools/codegen/codespec/api_spec_schema.go     |   4 +
 .../api_to_provider_spec_mapper_test.go       |  95 ++++-
 tools/codegen/codespec/attribute.go           |  79 +++-
 tools/codegen/codespec/element_type.go        | 106 +++++
 tools/codegen/codespec/model.go               |  10 -
 tools/codegen/codespec/testdata/api-spec.yml  | 362 +++++++++++++++++-
 .../testdata/config-nested-schema.yml         |  14 +
 7 files changed, 653 insertions(+), 17 deletions(-)
 create mode 100644 tools/codegen/codespec/element_type.go
 create mode 100644 tools/codegen/codespec/testdata/config-nested-schema.yml

diff --git a/tools/codegen/codespec/api_spec_schema.go b/tools/codegen/codespec/api_spec_schema.go
index c8d0c44f87..a15cc98084 100644
--- a/tools/codegen/codespec/api_spec_schema.go
+++ b/tools/codegen/codespec/api_spec_schema.go
@@ -57,3 +57,7 @@ func (s *APISpecSchema) IsSensitive() *bool {
 
 	return &isSensitive
 }
+
+func (s *APISpecSchema) IsMap() bool {
+	return s.Schema.AdditionalProperties != nil && s.Schema.AdditionalProperties.IsA()
+}
diff --git a/tools/codegen/codespec/api_to_provider_spec_mapper_test.go b/tools/codegen/codespec/api_to_provider_spec_mapper_test.go
index 8a999bb2a7..a449926a26 100644
--- a/tools/codegen/codespec/api_to_provider_spec_mapper_test.go
+++ b/tools/codegen/codespec/api_to_provider_spec_mapper_test.go
@@ -12,7 +12,7 @@ import (
 
 const (
 	testFieldDesc     = "Test field description"
-	testResourceDesc  = "Configures the project level settings for the Test Resource feature."
+	testResourceDesc  = "POST API description"
 	testPathParamDesc = "Path param test description"
 )
 
@@ -104,3 +104,96 @@ func TestConvertToProviderSpec(t *testing.T) {
 		})
 	}
 }
+
+func TestConvertToProviderSpec_nested(t *testing.T) {
+	testCases := map[string]convertToSpecTestCase{
+		"Valid input": {
+			inputOpenAPISpecPath: "testdata/api-spec.yml",
+			inputConfigPath:      "testdata/config-nested-schema.yml",
+			inputResourceName:    "test_resource_with_nested_attr",
+
+			expectedResult: &codespec.Model{
+				Resources: []codespec.Resource{{
+					Schema: &codespec.Schema{
+						Description: conversion.StringPtr(testResourceDesc),
+						Attributes: codespec.Attributes{
+							codespec.Attribute{
+								Name:                     "cluster_name",
+								ComputedOptionalRequired: codespec.Required,
+								String:                   &codespec.StringAttribute{},
+								Description:              conversion.StringPtr(testPathParamDesc),
+							},
+							codespec.Attribute{
+								Name:                     "group_id",
+								ComputedOptionalRequired: codespec.Required,
+								String:                   &codespec.StringAttribute{},
+								Description:              conversion.StringPtr(testPathParamDesc),
+							},
+							codespec.Attribute{
+								Name:                     "id",
+								ComputedOptionalRequired: codespec.Computed,
+								String:                   &codespec.StringAttribute{},
+								Description:              conversion.StringPtr(testFieldDesc),
+							},
+							codespec.Attribute{
+								Name:                     "list_primitive_string_attr",
+								ComputedOptionalRequired: codespec.Computed,
+								List: &codespec.ListAttribute{
+									ElementType: codespec.String,
+								},
+								Description: conversion.StringPtr(testFieldDesc),
+							},
+							codespec.Attribute{
+								Name:                     "nested_object_array_attr",
+								ComputedOptionalRequired: codespec.Required,
+								ListNested: &codespec.ListNestedAttribute{
+									NestedObject: codespec.NestedAttributeObject{
+										Attributes: codespec.Attributes{
+											codespec.Attribute{
+												Name:                     "inner_num_attr",
+												ComputedOptionalRequired: codespec.Required,
+												Int64:                    &codespec.Int64Attribute{},
+												Description:              conversion.StringPtr(testFieldDesc),
+											},
+											codespec.Attribute{
+												Name:                     "inner_str_attr",
+												ComputedOptionalRequired: codespec.Required,
+												String:                   &codespec.StringAttribute{},
+												Description:              conversion.StringPtr(testFieldDesc),
+											},
+											codespec.Attribute{
+												Name:                     "list_primitive_string_attr",
+												ComputedOptionalRequired: codespec.Optional,
+												List: &codespec.ListAttribute{
+													ElementType: codespec.String,
+												},
+												Description: conversion.StringPtr(testFieldDesc),
+											},
+										},
+									},
+								},
+								Description: conversion.StringPtr(testFieldDesc),
+							},
+							codespec.Attribute{
+								Name:                     "str_computed_attr",
+								ComputedOptionalRequired: codespec.Computed,
+								String:                   &codespec.StringAttribute{},
+								Description:              conversion.StringPtr(testFieldDesc),
+							},
+						},
+					},
+					Name: "test_resource_with_nested_attr",
+				},
+				},
+			},
+		},
+	}
+
+	for name, tc := range testCases {
+		t.Run(name, func(t *testing.T) {
+			result, err := codespec.ToCodeSpecModel(tc.inputOpenAPISpecPath, tc.inputConfigPath, tc.inputResourceName)
+			require.NoError(t, err)
+			assert.Equal(t, tc.expectedResult, result, "Expected result to match the specified structure")
+		})
+	}
+}
diff --git a/tools/codegen/codespec/attribute.go b/tools/codegen/codespec/attribute.go
index b00f0f0722..1372ce30e4 100644
--- a/tools/codegen/codespec/attribute.go
+++ b/tools/codegen/codespec/attribute.go
@@ -43,7 +43,9 @@ func (s *APISpecSchema) buildResourceAttr(name string, computability ComputedOpt
 		return s.buildNumberAttr(name, computability)
 	case OASTypeBoolean:
 		return s.buildBoolAttr(name, computability)
-	case OASTypeArray, OASTypeObject:
+	case OASTypeArray:
+		return s.buildArrayAttr(name, computability)
+	case OASTypeObject:
 		return nil, nil
 	default:
 		return nil, fmt.Errorf("invalid schema type '%s'", s.Type)
@@ -143,3 +145,78 @@ func (s *APISpecSchema) buildBoolAttr(name string, computability ComputedOptiona
 
 	return result, nil
 }
+
+func (s *APISpecSchema) buildArrayAttr(name string, computability ComputedOptionalRequired) (*Attribute, error) {
+	if !s.Schema.Items.IsA() {
+		return nil, fmt.Errorf("invalid array items property, doesn't have a schema: %s", name)
+	}
+	itemSchema, err := BuildSchema(s.Schema.Items.A)
+	if err != nil {
+		return nil, fmt.Errorf("error while building nested schema: %s", name)
+	}
+
+	if itemSchema.Type == OASTypeObject {
+		objectAttributes, err := buildResourceAttrs(itemSchema)
+		if err != nil {
+			return nil, fmt.Errorf("error while building nested schema: %s", name)
+		}
+
+		result := &Attribute{
+			Name:                     terraformAttrName(name),
+			ComputedOptionalRequired: computability,
+			DeprecationMessage:       s.GetDeprecationMessage(),
+			Description:              s.GetDescription(),
+			ListNested: &ListNestedAttribute{
+				NestedObject: NestedAttributeObject{
+					Attributes: objectAttributes,
+				},
+			},
+		}
+
+		return result, nil
+	}
+
+	elemType, err := itemSchema.buildElementType()
+	if err != nil {
+		return nil, fmt.Errorf("error while building nested schema: %s", name)
+	}
+
+	// if s.Format == util.TF_format_set {
+	// 	result := &attrmapper.ResourceSetAttribute{
+	// 		Name: name,
+	// 		SetAttribute: resource.SetAttribute{
+	// 			ElementType:              elemType,
+	// 			ComputedOptionalRequired: computability,
+	// 			DeprecationMessage:       s.GetDeprecationMessage(),
+	// 			Description:              s.GetDescription(),
+	// 		},
+	// 	}
+
+	// 	if computability != schema.Computed {
+	// 		result.Validators = s.GetSetValidators()
+	// 	}
+
+	// 	return result, nil
+	// }
+
+	result := &Attribute{
+		Name:                     terraformAttrName(name),
+		ComputedOptionalRequired: computability,
+		DeprecationMessage:       s.GetDeprecationMessage(),
+		Description:              s.GetDescription(),
+		List: &ListAttribute{
+			ElementType: elemType,
+			// Default: ,
+		},
+	}
+
+	if s.Schema.Default != nil {
+		var staticDefault bool
+		if err := s.Schema.Default.Decode(&staticDefault); err == nil {
+			result.ComputedOptionalRequired = ComputedOptional
+			result.Bool.Default = &staticDefault
+		}
+	}
+
+	return result, nil
+}
diff --git a/tools/codegen/codespec/element_type.go b/tools/codegen/codespec/element_type.go
new file mode 100644
index 0000000000..eac553e1f2
--- /dev/null
+++ b/tools/codegen/codespec/element_type.go
@@ -0,0 +1,106 @@
+package codespec
+
+import "fmt"
+
+type ElemType int
+
+const (
+	Bool ElemType = iota
+	Float64
+	Int64
+	Number
+	String
+	Unknown
+)
+
+// type ElemType struct {
+// 	Bool    *BoolType    `json:"bool,omitempty"`
+// 	Float64 *Float64Type `json:"float64,omitempty"`
+// 	Int64   *Int64Type   `json:"int64,omitempty"`
+// 	List    *ListType    `json:"list,omitempty"`
+// 	Number  *NumberType  `json:"number,omitempty"`
+// 	String  *StringType  `json:"string,omitempty"`
+// }
+
+// type BoolType struct{}
+// type Float64Type struct{}
+// type Int64Type struct{}
+// type StringType struct{}
+
+// type NumberType struct{}
+// type ListType struct {
+// 	ElementType ElemType `json:"element_type"`
+// }
+// type SetType struct {
+// 	ElementType ElemType `json:"element_type"`
+// }
+
+// // type ObjectType struct{} // TODO
+// type MapType struct {
+// 	ElementType ElemType `json:"element_type"`
+// }
+
+func (s *APISpecSchema) buildElementType() (ElemType, error) {
+	switch s.Type {
+	case OASTypeString:
+		return String, nil
+	case OASTypeBoolean:
+		return Bool, nil
+	case OASTypeInteger:
+		return Int64, nil
+	case OASTypeNumber:
+		return Number, nil
+	case OASTypeArray, OASTypeObject:
+		return Unknown, nil // ignoring because complex element types unsupported
+	default:
+		return Unknown, fmt.Errorf("invalid schema type '%s'", s.Type)
+	}
+}
+
+func (s *APISpecSchema) buildArrayElementType() (ElemType, error) {
+	if !s.Schema.Items.IsA() {
+		return Unknown, fmt.Errorf("invalid array type for nested elem array, doesn't have a schema")
+	}
+
+	itemSchema, err := BuildSchema(s.Schema.Items.A)
+	if err != nil {
+		return Unknown, err
+	}
+
+	elemType, err := itemSchema.buildElementType()
+	if err != nil {
+		return Unknown, err
+	}
+
+	return elemType, nil
+}
+
+// func (s *APISpecSchema) buildStringElementType() (ElemType, error) {
+// 	return ElemType{
+// 		String: &StringType{},
+// 	}, nil
+// }
+
+// func (s *APISpecSchema) buildIntegerElementType() (ElemType, error) {
+// 	return ElemType{
+// 		Int64: &Int64Type{},
+// 	}, nil
+// }
+
+// func (s *APISpecSchema) buildBoolElementType() (ElemType, error) {
+// 	return ElemType{
+// 		Bool: &BoolType{},
+// 	}, nil
+// }
+
+// func (s *APISpecSchema) buildNumberElementType() (ElemType, error) {
+// 	if s.Schema.Format == OASFormatDouble || s.Schema.Format == OASFormatFloat {
+// 		return ElemType{
+// 			Float64: &Float64Type{},
+// 		}, nil
+// 	}
+
+// 	return ElemType{
+// 		Number: &NumberType{},
+// 	}, nil
+// }
diff --git a/tools/codegen/codespec/model.go b/tools/codegen/codespec/model.go
index ccb754892c..abdb21aab2 100644
--- a/tools/codegen/codespec/model.go
+++ b/tools/codegen/codespec/model.go
@@ -1,15 +1,5 @@
 package codespec
 
-type ElemType int
-
-const (
-	Bool ElemType = iota
-	Float64
-	Int64
-	Number
-	String
-)
-
 type Model struct {
 	Resources []Resource
 }
diff --git a/tools/codegen/codespec/testdata/api-spec.yml b/tools/codegen/codespec/testdata/api-spec.yml
index f4b70687af..f5b773545a 100644
--- a/tools/codegen/codespec/testdata/api-spec.yml
+++ b/tools/codegen/codespec/testdata/api-spec.yml
@@ -36,7 +36,7 @@ tags:
 paths:
   "/api/atlas/v2/groups/{groupId}/testResource":
     delete:
-      description: Test Resource disable operation
+      description: DELETE API description
       operationId: deleteTestResourceConfiguration
       parameters:
         - $ref: "#/components/parameters/groupId"
@@ -70,7 +70,7 @@ paths:
       tags:
         - Test Resource
     patch:
-      description: Updates the project level settings for the Test Resource feature.
+      description: PATCH API description
       operationId: updateTestResourceConfiguration
       parameters:
         - $ref: "#/components/parameters/groupId"
@@ -94,8 +94,7 @@ paths:
       tags:
         - Test Resource
     post:
-      description: Configures the project level settings for the Test Resource
-        feature.
+      description: POST API description
       operationId: createTestResourceConfiguration
       parameters:
         - $ref: "#/components/parameters/groupId"
@@ -118,6 +117,159 @@ paths:
       summary: Enable the Test Resource feature for a project
       tags:
         - Test Resource
+  "/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/nestedTestResource":
+    delete:
+      description: DELETE API description
+      operationId: deleteNestedTestResource
+      parameters:
+        - $ref: "#/components/parameters/groupId"
+        - description: Path param test description
+          in: path
+          name: clusterName
+          required: true
+          schema:
+            type: string
+            maxLength: 64
+            minLength: 1
+            pattern: ^([a-zA-Z0-9][a-zA-Z0-9-]*)?[a-zA-Z0-9]+$
+      responses:
+        "204":
+          content:
+            application/vnd.atlas.2024-05-30+json:
+              schema:
+                $ref: "#/components/schemas/NoBody"
+              x-xgen-version: 2024-05-30
+          description: This endpoint does not return a response body.
+        "400":
+          $ref: "#/components/responses/badRequest"
+        "404":
+          $ref: "#/components/responses/notFound"
+        "409":
+          $ref: "#/components/responses/conflict"
+        "500":
+          $ref: "#/components/responses/internalServerError"
+      security:
+        - DigestAuth: []
+      summary: Delete Search Nodes
+      tags:
+        - Atlas Search
+    get:
+      description: GET API description
+      operationId: getNestedTestResource
+      parameters:
+        - $ref: "#/components/parameters/groupId"
+        - description: Path param test description
+          in: path
+          name: clusterName
+          required: true
+          schema:
+            type: string
+            maxLength: 64
+            minLength: 1
+            pattern: ^([a-zA-Z0-9][a-zA-Z0-9-]*)?[a-zA-Z0-9]+$
+      responses:
+        "200":
+          content:
+            application/vnd.atlas.2024-05-30+json:
+              schema:
+                $ref: "#/components/schemas/NestedTestResourceResponse"
+              x-xgen-version: 2024-05-30
+          description: OK
+        "400":
+          $ref: "#/components/responses/badRequest"
+        "404":
+          $ref: "#/components/responses/notFound"
+        "500":
+          $ref: "#/components/responses/internalServerError"
+      security:
+        - DigestAuth: []
+      summary: Return Search Nodes
+      tags:
+        - Atlas Search
+    patch:
+      description: PATCH API description
+      operationId: updateNestedTestResource
+      parameters:
+        - $ref: "#/components/parameters/groupId"
+        - description: Path param test description
+          in: path
+          name: clusterName
+          required: true
+          schema:
+            type: string
+            maxLength: 64
+            minLength: 1
+            pattern: ^([a-zA-Z0-9][a-zA-Z0-9-]*)?[a-zA-Z0-9]+$
+      requestBody:
+        content:
+          application/vnd.atlas.2024-05-30+json:
+            schema:
+              $ref: "#/components/schemas/NestedTestResourceRequest"
+        description: Updates the Search Nodes for the specified cluster.
+        required: true
+      responses:
+        "200":
+          content:
+            application/vnd.atlas.2024-05-30+json:
+              schema:
+                $ref: "#/components/schemas/NestedTestResourceResponse"
+              x-xgen-version: 2024-05-30
+          description: OK
+        "400":
+          $ref: "#/components/responses/badRequest"
+        "404":
+          $ref: "#/components/responses/notFound"
+        "409":
+          $ref: "#/components/responses/conflict"
+        "500":
+          $ref: "#/components/responses/internalServerError"
+      security:
+        - DigestAuth: []
+      summary: Update Search Nodes
+      tags:
+        - Atlas Search
+    post:
+      description: POST API description      
+      operationId: createNestedTestResource
+      parameters:
+        - $ref: "#/components/parameters/groupId"
+        - description: Path param test description
+          in: path
+          name: clusterName
+          required: true
+          schema:
+            type: string
+            maxLength: 64
+            minLength: 1
+            pattern: ^([a-zA-Z0-9][a-zA-Z0-9-]*)?[a-zA-Z0-9]+$
+      requestBody:
+        content:
+          application/vnd.atlas.2024-05-30+json:
+            schema:
+              $ref: "#/components/schemas/NestedTestResourceRequest"
+        description: Creates Search Nodes for the specified cluster.
+        required: true
+      responses:
+        "201":
+          content:
+            application/vnd.atlas.2024-05-30+json:
+              schema:
+                $ref: "#/components/schemas/NestedTestResourceResponse"
+              x-xgen-version: 2024-05-30
+          description: Created
+        "400":
+          $ref: "#/components/responses/badRequest"
+        "404":
+          $ref: "#/components/responses/notFound"
+        "409":
+          $ref: "#/components/responses/conflict"
+        "500":
+          $ref: "#/components/responses/internalServerError"
+      security:
+        - DigestAuth: []
+      summary: Create Search Nodes
+      tags:
+        - Atlas Search 
 components:
   parameters:
     groupId:
@@ -135,8 +287,93 @@ components:
   responses:
     accepted:
       description: Accepted.
+    badRequest:
+      content:
+        application/json:
+          example:
+            detail: (This is just an example, the exception may not be related to this
+              endpoint) No provider AWS exists.
+            error: 400
+            errorCode: VALIDATION_ERROR
+            reason: Bad Request
+          schema:
+            $ref: "#/components/schemas/ApiError"
+      description: Bad Request.
+    conflict:
+      content:
+        application/json:
+          example:
+            detail: "(This is just an example, the exception may not be related to this
+              endpoint) Cannot delete organization link while there is active
+              migration in following project ids: 60c4fd418ebe251047c50554"
+            error: 409
+            errorCode: CANNOT_DELETE_ORG_ACTIVE_LIVE_MIGRATION_ATLAS_ORG_LINK
+            reason: Conflict
+          schema:
+            $ref: "#/components/schemas/ApiError"
+      description: Conflict.
+    forbidden:
+      content:
+        application/json:
+          example:
+            detail: (This is just an example, the exception may not be related to this
+              endpoint)
+            error: 403
+            errorCode: CANNOT_CHANGE_GROUP_NAME
+            reason: Forbidden
+          schema:
+            $ref: "#/components/schemas/ApiError"
+      description: Forbidden.
+    gone:
+      content:
+        application/json:
+          example:
+            detail: This happens when a resource is marked for sunset and the sunset date is
+              in the past.
+            error: 410
+            errorCode: VERSION_GONE
+            reason: Gone
+          schema:
+            $ref: "#/components/schemas/ApiError"
+      description: Gone.
+    internalServerError:
+      content:
+        application/json:
+          example:
+            detail: (This is just an example, the exception may not be related to this
+              endpoint)
+            error: 500
+            errorCode: UNEXPECTED_ERROR
+            reason: Internal Server Error
+          schema:
+            $ref: "#/components/schemas/ApiError"
+      description: Internal Server Error.
+    methodNotAllowed:
+      content:
+        application/json:
+          example:
+            detail: (This is just an example, the exception may not be related to this
+              endpoint)
+            error: 405
+            errorCode: ATLAS_BACKUP_CANCEL_SHARD_RESTORE_JOB_NOT_ALLOWED
+            reason: Method Not Allowed
+          schema:
+            $ref: "#/components/schemas/ApiError"
+      description: Method Not Allowed.
     noBody:
       description: This endpoint does not return a response body.
+    notFound:
+      content:
+        application/json:
+          example:
+            detail: (This is just an example, the exception may not be related to this
+              endpoint) Cannot find resource AWS
+            error: 404
+            errorCode: RESOURCE_NOT_FOUND
+            reason: Not Found
+          schema:
+            $ref: "#/components/schemas/ApiError"
+      description: Not Found.
   schemas:
     CreateTestResourceRequest:
       type: object
@@ -234,4 +471,119 @@ components:
             relationship between this resource and another API resource. This
             URL often begins with `https://cloud.mongodb.com/api/atlas`.
           example: self
-    
\ No newline at end of file
+    NestedTestResourceResponse:
+      type: object
+      properties:
+        groupId:
+          type: string
+          description: Path param test description
+          example: 32b6e34b3d91647abb20e7b8
+          maxLength: 24
+          minLength: 24
+          pattern: ^([a-f0-9]{24})$
+          readOnly: true
+        id:
+          type: string
+          description: Test field description
+          example: 32b6e34b3d91647abb20e7b8
+          maxLength: 24
+          minLength: 24
+          pattern: ^([a-f0-9]{24})$
+          readOnly: true
+        nestedObjectArrayAttr:
+          type: array
+          description: Test field description
+          items:
+            $ref: "#/components/schemas/NestedObjectAttr"
+          readOnly: true
+        listPrimitiveStringAttr:
+          type: array
+          description: Test field description
+          items:
+            type: string
+          uniqueItems: true
+        strComputedAttr:
+          type: string
+          description: Test field description
+          readOnly: true
+    NestedObjectAttr:
+      type: object
+      properties:
+        innerStrAttr:
+          type: string
+          description: Test field description
+        innerNumAttr:
+          type: integer
+          format: int32
+          description: Test field description
+          example: 2
+          maximum: 32
+          minimum: 2
+        listPrimitiveStringAttr:
+          type: array
+          description: Test field description
+          items:
+            type: string
+          uniqueItems: true
+      required:
+        - innerStrAttr
+        - innerNumAttr
+    NestedTestResourceRequest:
+      type: object
+      properties:
+        nestedObjectArrayAttr:
+          type: array
+          description: Test field description
+          items:
+            $ref: "#/components/schemas/NestedObjectAttr"
+          maxItems: 1
+          minItems: 1
+      required:
+        - nestedObjectArrayAttr
+    ApiError:
+      type: object
+      properties:
+        badRequestDetail:
+          $ref: "#/components/schemas/BadRequestDetail"
+        detail:
+          type: string
+          description: Describes the specific conditions or reasons that cause each type
+            of error.
+        error:
+          type: integer
+          format: int32
+          description: HTTP status code returned with this error.
+          externalDocs:
+            url: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
+        errorCode:
+          type: string
+          description: Application error code returned with this error.
+        parameters:
+          type: array
+          description: Parameters used to give more information about the error.
+          items: {}
+        reason:
+          type: string
+          description: Application error message returned with this error.
+    BadRequestDetail:
+      type: object
+      description: Bad request detail.
+      properties:
+        fields:
+          type: array
+          description: Describes all violations in a client request.
+          items:
+            $ref: "#/components/schemas/FieldViolation"
+    NoBody:
+      type: object
+      description: Endpoint does not return a response body.
+    FieldViolation:
+      type: object
+      properties:
+        description:
+          type: string
+          description: A description of why the request element is bad.
+        field:
+          type: string
+          description: A path that leads to a field in the request body.
+   
\ No newline at end of file
diff --git a/tools/codegen/codespec/testdata/config-nested-schema.yml b/tools/codegen/codespec/testdata/config-nested-schema.yml
new file mode 100644
index 0000000000..ac6be492c6
--- /dev/null
+++ b/tools/codegen/codespec/testdata/config-nested-schema.yml
@@ -0,0 +1,14 @@
+resources:
+  test_resource_with_nested_attr:
+    read:
+      path: /api/atlas/v2/groups/{groupId}/clusters/{clusterName}/nestedTestResource
+      method: GET
+    create:
+      path: /api/atlas/v2/groups/{groupId}/clusters/{clusterName}/nestedTestResource
+      method: POST
+    update:
+      path: /api/atlas/v2/groups/{groupId}/clusters/{clusterName}/nestedTestResource
+      method: PATCH
+    delete:
+      path: /api/atlas/v2/groups/{groupId}/clusters/{clusterName}/nestedTestResource
+      method: DELETE
\ No newline at end of file

From cb964657680a8a2d8a1fb2523bcdcd7bde4a91a8 Mon Sep 17 00:00:00 2001
From: Aastha Mahendru <aastha.mahendru@mongodb.com>
Date: Tue, 15 Oct 2024 17:33:11 +0100
Subject: [PATCH 02/12] cleanup

---
 tools/codegen/codespec/api_spec_schema.go    |  4 --
 tools/codegen/codespec/attribute.go          | 25 +------
 tools/codegen/codespec/element_type.go       | 75 --------------------
 tools/codegen/codespec/testdata/api-spec.yml | 57 +--------------
 4 files changed, 4 insertions(+), 157 deletions(-)

diff --git a/tools/codegen/codespec/api_spec_schema.go b/tools/codegen/codespec/api_spec_schema.go
index a15cc98084..c8d0c44f87 100644
--- a/tools/codegen/codespec/api_spec_schema.go
+++ b/tools/codegen/codespec/api_spec_schema.go
@@ -57,7 +57,3 @@ func (s *APISpecSchema) IsSensitive() *bool {
 
 	return &isSensitive
 }
-
-func (s *APISpecSchema) IsMap() bool {
-	return s.Schema.AdditionalProperties != nil && s.Schema.AdditionalProperties.IsA()
-}
diff --git a/tools/codegen/codespec/attribute.go b/tools/codegen/codespec/attribute.go
index 1372ce30e4..81d274b65c 100644
--- a/tools/codegen/codespec/attribute.go
+++ b/tools/codegen/codespec/attribute.go
@@ -46,7 +46,7 @@ func (s *APISpecSchema) buildResourceAttr(name string, computability ComputedOpt
 	case OASTypeArray:
 		return s.buildArrayAttr(name, computability)
 	case OASTypeObject:
-		return nil, nil
+		return nil, nil // TODO: add support for SingleNestedObject and MapAttribute
 	default:
 		return nil, fmt.Errorf("invalid schema type '%s'", s.Type)
 	}
@@ -148,14 +148,14 @@ func (s *APISpecSchema) buildBoolAttr(name string, computability ComputedOptiona
 
 func (s *APISpecSchema) buildArrayAttr(name string, computability ComputedOptionalRequired) (*Attribute, error) {
 	if !s.Schema.Items.IsA() {
-		return nil, fmt.Errorf("invalid array items property, doesn't have a schema: %s", name)
+		return nil, fmt.Errorf("invalid array items property, schema doesn't exist: %s", name)
 	}
 	itemSchema, err := BuildSchema(s.Schema.Items.A)
 	if err != nil {
 		return nil, fmt.Errorf("error while building nested schema: %s", name)
 	}
 
-	if itemSchema.Type == OASTypeObject {
+	if itemSchema.Type == OASTypeObject { // TODO: add support for Set and SetNested Attributes
 		objectAttributes, err := buildResourceAttrs(itemSchema)
 		if err != nil {
 			return nil, fmt.Errorf("error while building nested schema: %s", name)
@@ -181,24 +181,6 @@ func (s *APISpecSchema) buildArrayAttr(name string, computability ComputedOption
 		return nil, fmt.Errorf("error while building nested schema: %s", name)
 	}
 
-	// if s.Format == util.TF_format_set {
-	// 	result := &attrmapper.ResourceSetAttribute{
-	// 		Name: name,
-	// 		SetAttribute: resource.SetAttribute{
-	// 			ElementType:              elemType,
-	// 			ComputedOptionalRequired: computability,
-	// 			DeprecationMessage:       s.GetDeprecationMessage(),
-	// 			Description:              s.GetDescription(),
-	// 		},
-	// 	}
-
-	// 	if computability != schema.Computed {
-	// 		result.Validators = s.GetSetValidators()
-	// 	}
-
-	// 	return result, nil
-	// }
-
 	result := &Attribute{
 		Name:                     terraformAttrName(name),
 		ComputedOptionalRequired: computability,
@@ -206,7 +188,6 @@ func (s *APISpecSchema) buildArrayAttr(name string, computability ComputedOption
 		Description:              s.GetDescription(),
 		List: &ListAttribute{
 			ElementType: elemType,
-			// Default: ,
 		},
 	}
 
diff --git a/tools/codegen/codespec/element_type.go b/tools/codegen/codespec/element_type.go
index eac553e1f2..c27dada213 100644
--- a/tools/codegen/codespec/element_type.go
+++ b/tools/codegen/codespec/element_type.go
@@ -13,33 +13,6 @@ const (
 	Unknown
 )
 
-// type ElemType struct {
-// 	Bool    *BoolType    `json:"bool,omitempty"`
-// 	Float64 *Float64Type `json:"float64,omitempty"`
-// 	Int64   *Int64Type   `json:"int64,omitempty"`
-// 	List    *ListType    `json:"list,omitempty"`
-// 	Number  *NumberType  `json:"number,omitempty"`
-// 	String  *StringType  `json:"string,omitempty"`
-// }
-
-// type BoolType struct{}
-// type Float64Type struct{}
-// type Int64Type struct{}
-// type StringType struct{}
-
-// type NumberType struct{}
-// type ListType struct {
-// 	ElementType ElemType `json:"element_type"`
-// }
-// type SetType struct {
-// 	ElementType ElemType `json:"element_type"`
-// }
-
-// // type ObjectType struct{} // TODO
-// type MapType struct {
-// 	ElementType ElemType `json:"element_type"`
-// }
-
 func (s *APISpecSchema) buildElementType() (ElemType, error) {
 	switch s.Type {
 	case OASTypeString:
@@ -56,51 +29,3 @@ func (s *APISpecSchema) buildElementType() (ElemType, error) {
 		return Unknown, fmt.Errorf("invalid schema type '%s'", s.Type)
 	}
 }
-
-func (s *APISpecSchema) buildArrayElementType() (ElemType, error) {
-	if !s.Schema.Items.IsA() {
-		return Unknown, fmt.Errorf("invalid array type for nested elem array, doesn't have a schema")
-	}
-
-	itemSchema, err := BuildSchema(s.Schema.Items.A)
-	if err != nil {
-		return Unknown, err
-	}
-
-	elemType, err := itemSchema.buildElementType()
-	if err != nil {
-		return Unknown, err
-	}
-
-	return elemType, nil
-}
-
-// func (s *APISpecSchema) buildStringElementType() (ElemType, error) {
-// 	return ElemType{
-// 		String: &StringType{},
-// 	}, nil
-// }
-
-// func (s *APISpecSchema) buildIntegerElementType() (ElemType, error) {
-// 	return ElemType{
-// 		Int64: &Int64Type{},
-// 	}, nil
-// }
-
-// func (s *APISpecSchema) buildBoolElementType() (ElemType, error) {
-// 	return ElemType{
-// 		Bool: &BoolType{},
-// 	}, nil
-// }
-
-// func (s *APISpecSchema) buildNumberElementType() (ElemType, error) {
-// 	if s.Schema.Format == OASFormatDouble || s.Schema.Format == OASFormatFloat {
-// 		return ElemType{
-// 			Float64: &Float64Type{},
-// 		}, nil
-// 	}
-
-// 	return ElemType{
-// 		Number: &NumberType{},
-// 	}, nil
-// }
diff --git a/tools/codegen/codespec/testdata/api-spec.yml b/tools/codegen/codespec/testdata/api-spec.yml
index f5b773545a..40d96a2e05 100644
--- a/tools/codegen/codespec/testdata/api-spec.yml
+++ b/tools/codegen/codespec/testdata/api-spec.yml
@@ -144,8 +144,6 @@ paths:
           $ref: "#/components/responses/badRequest"
         "404":
           $ref: "#/components/responses/notFound"
-        "409":
-          $ref: "#/components/responses/conflict"
         "500":
           $ref: "#/components/responses/internalServerError"
       security:
@@ -219,8 +217,6 @@ paths:
           $ref: "#/components/responses/badRequest"
         "404":
           $ref: "#/components/responses/notFound"
-        "409":
-          $ref: "#/components/responses/conflict"
         "500":
           $ref: "#/components/responses/internalServerError"
       security:
@@ -261,13 +257,11 @@ paths:
           $ref: "#/components/responses/badRequest"
         "404":
           $ref: "#/components/responses/notFound"
-        "409":
-          $ref: "#/components/responses/conflict"
         "500":
           $ref: "#/components/responses/internalServerError"
       security:
         - DigestAuth: []
-      summary: Create Search Nodes
+      summary: Create Nested Test Resource
       tags:
         - Atlas Search 
 components:
@@ -299,43 +293,6 @@ components:
           schema:
             $ref: "#/components/schemas/ApiError"
       description: Bad Request.
-    conflict:
-      content:
-        application/json:
-          example:
-            detail: "(This is just an example, the exception may not be related to this
-              endpoint) Cannot delete organization link while there is active
-              migration in following project ids: 60c4fd418ebe251047c50554"
-            error: 409
-            errorCode: CANNOT_DELETE_ORG_ACTIVE_LIVE_MIGRATION_ATLAS_ORG_LINK
-            reason: Conflict
-          schema:
-            $ref: "#/components/schemas/ApiError"
-      description: Conflict.
-    forbidden:
-      content:
-        application/json:
-          example:
-            detail: (This is just an example, the exception may not be related to this
-              endpoint)
-            error: 403
-            errorCode: CANNOT_CHANGE_GROUP_NAME
-            reason: Forbidden
-          schema:
-            $ref: "#/components/schemas/ApiError"
-      description: Forbidden.
-    gone:
-      content:
-        application/json:
-          example:
-            detail: This happens when a resource is marked for sunset and the sunset date is
-              in the past.
-            error: 410
-            errorCode: VERSION_GONE
-            reason: Gone
-          schema:
-            $ref: "#/components/schemas/ApiError"
-      description: Gone.
     internalServerError:
       content:
         application/json:
@@ -348,18 +305,6 @@ components:
           schema:
             $ref: "#/components/schemas/ApiError"
       description: Internal Server Error.
-    methodNotAllowed:
-      content:
-        application/json:
-          example:
-            detail: (This is just an example, the exception may not be related to this
-              endpoint)
-            error: 405
-            errorCode: ATLAS_BACKUP_CANCEL_SHARD_RESTORE_JOB_NOT_ALLOWED
-            reason: Method Not Allowed
-          schema:
-            $ref: "#/components/schemas/ApiError"
-      description: Method Not Allowed.
     noBody:
       description: This endpoint does not return a response body.
     notFound:

From 646179153e0cdde879370503e1b4bc561afa9648 Mon Sep 17 00:00:00 2001
From: Aastha Mahendru <aastha.mahendru@mongodb.com>
Date: Tue, 15 Oct 2024 17:36:41 +0100
Subject: [PATCH 03/12] cleanup

---
 .../api_to_provider_spec_mapper_test.go       | 36 +++++++++---------
 tools/codegen/codespec/testdata/api-spec.yml  | 37 -------------------
 2 files changed, 18 insertions(+), 55 deletions(-)

diff --git a/tools/codegen/codespec/api_to_provider_spec_mapper_test.go b/tools/codegen/codespec/api_to_provider_spec_mapper_test.go
index a449926a26..a507f960bb 100644
--- a/tools/codegen/codespec/api_to_provider_spec_mapper_test.go
+++ b/tools/codegen/codespec/api_to_provider_spec_mapper_test.go
@@ -35,53 +35,53 @@ func TestConvertToProviderSpec(t *testing.T) {
 					Schema: &codespec.Schema{
 						Description: conversion.StringPtr(testResourceDesc),
 						Attributes: codespec.Attributes{
-							codespec.Attribute{
+							{
 								Name:                     "bool_default_attr",
 								ComputedOptionalRequired: codespec.ComputedOptional,
 								Bool:                     &codespec.BoolAttribute{Default: conversion.Pointer(false)},
 							},
-							codespec.Attribute{
+							{
 								Name:                     "count",
 								ComputedOptionalRequired: codespec.Optional,
 								Int64:                    &codespec.Int64Attribute{},
 								Description:              conversion.StringPtr(testFieldDesc),
 							},
-							codespec.Attribute{
+							{
 								Name:                     "create_date",
 								String:                   &codespec.StringAttribute{},
 								ComputedOptionalRequired: codespec.Computed,
 								Description:              conversion.StringPtr(testFieldDesc),
 							},
-							codespec.Attribute{
+							{
 								Name:                     "group_id",
 								ComputedOptionalRequired: codespec.Required,
 								String:                   &codespec.StringAttribute{},
 								Description:              conversion.StringPtr(testPathParamDesc),
 							},
-							codespec.Attribute{
+							{
 								Name:                     "num_double_default_attr",
 								Float64:                  &codespec.Float64Attribute{Default: conversion.Pointer(2.0)},
 								ComputedOptionalRequired: codespec.ComputedOptional,
 							},
-							codespec.Attribute{
+							{
 								Name:                     "str_computed_attr",
 								ComputedOptionalRequired: codespec.Computed,
 								String:                   &codespec.StringAttribute{},
 								Description:              conversion.StringPtr(testFieldDesc),
 							},
-							codespec.Attribute{
+							{
 								Name:                     "str_req_attr1",
 								ComputedOptionalRequired: codespec.Required,
 								String:                   &codespec.StringAttribute{},
 								Description:              conversion.StringPtr(testFieldDesc),
 							},
-							codespec.Attribute{
+							{
 								Name:                     "str_req_attr2",
 								ComputedOptionalRequired: codespec.Required,
 								String:                   &codespec.StringAttribute{},
 								Description:              conversion.StringPtr(testFieldDesc),
 							},
-							codespec.Attribute{
+							{
 								Name:                     "str_req_attr3",
 								String:                   &codespec.StringAttribute{},
 								ComputedOptionalRequired: codespec.Required,
@@ -117,25 +117,25 @@ func TestConvertToProviderSpec_nested(t *testing.T) {
 					Schema: &codespec.Schema{
 						Description: conversion.StringPtr(testResourceDesc),
 						Attributes: codespec.Attributes{
-							codespec.Attribute{
+							{
 								Name:                     "cluster_name",
 								ComputedOptionalRequired: codespec.Required,
 								String:                   &codespec.StringAttribute{},
 								Description:              conversion.StringPtr(testPathParamDesc),
 							},
-							codespec.Attribute{
+							{
 								Name:                     "group_id",
 								ComputedOptionalRequired: codespec.Required,
 								String:                   &codespec.StringAttribute{},
 								Description:              conversion.StringPtr(testPathParamDesc),
 							},
-							codespec.Attribute{
+							{
 								Name:                     "id",
 								ComputedOptionalRequired: codespec.Computed,
 								String:                   &codespec.StringAttribute{},
 								Description:              conversion.StringPtr(testFieldDesc),
 							},
-							codespec.Attribute{
+							{
 								Name:                     "list_primitive_string_attr",
 								ComputedOptionalRequired: codespec.Computed,
 								List: &codespec.ListAttribute{
@@ -143,25 +143,25 @@ func TestConvertToProviderSpec_nested(t *testing.T) {
 								},
 								Description: conversion.StringPtr(testFieldDesc),
 							},
-							codespec.Attribute{
+							{
 								Name:                     "nested_object_array_attr",
 								ComputedOptionalRequired: codespec.Required,
 								ListNested: &codespec.ListNestedAttribute{
 									NestedObject: codespec.NestedAttributeObject{
 										Attributes: codespec.Attributes{
-											codespec.Attribute{
+											{
 												Name:                     "inner_num_attr",
 												ComputedOptionalRequired: codespec.Required,
 												Int64:                    &codespec.Int64Attribute{},
 												Description:              conversion.StringPtr(testFieldDesc),
 											},
-											codespec.Attribute{
+											{
 												Name:                     "inner_str_attr",
 												ComputedOptionalRequired: codespec.Required,
 												String:                   &codespec.StringAttribute{},
 												Description:              conversion.StringPtr(testFieldDesc),
 											},
-											codespec.Attribute{
+											{
 												Name:                     "list_primitive_string_attr",
 												ComputedOptionalRequired: codespec.Optional,
 												List: &codespec.ListAttribute{
@@ -174,7 +174,7 @@ func TestConvertToProviderSpec_nested(t *testing.T) {
 								},
 								Description: conversion.StringPtr(testFieldDesc),
 							},
-							codespec.Attribute{
+							{
 								Name:                     "str_computed_attr",
 								ComputedOptionalRequired: codespec.Computed,
 								String:                   &codespec.StringAttribute{},
diff --git a/tools/codegen/codespec/testdata/api-spec.yml b/tools/codegen/codespec/testdata/api-spec.yml
index 40d96a2e05..29b7a6aeb0 100644
--- a/tools/codegen/codespec/testdata/api-spec.yml
+++ b/tools/codegen/codespec/testdata/api-spec.yml
@@ -329,17 +329,6 @@ components:
         strReqAttr2:
           type: string
           description: Test field description
-        links:
-          type: array
-          description: List of one or more Uniform Resource Locators (URLs) that point to
-            API sub-resources, related API resources, or both. RFC 5988 outlines
-            these relationships.
-          externalDocs:
-            description: Web Linking Specification (RFC 5988)
-            url: https://datatracker.ietf.org/doc/html/rfc5988
-          items:
-            $ref: "#/components/schemas/Link"
-          readOnly: true
         strReqAttr3:
           type: string
           description: Test field description
@@ -372,17 +361,6 @@ components:
         strReqAttr2:
           type: string
           description: Test field description
-        links:
-          type: array
-          description: List of one or more Uniform Resource Locators (URLs) that point to
-            API sub-resources, related API resources, or both. RFC 5988 outlines
-            these relationships.
-          externalDocs:
-            description: Web Linking Specification (RFC 5988)
-            url: https://datatracker.ietf.org/doc/html/rfc5988
-          items:
-            $ref: "#/components/schemas/Link"
-          readOnly: true
         strReqAttr3:
           type: string
           description: Test field description
@@ -401,21 +379,6 @@ components:
           type: number
           format: double
           default: 2.0
-    Link:
-      type: object
-      properties:
-        href:
-          type: string
-          description: Uniform Resource Locator (URL) that points another API resource to
-            which this response has some relationship. This URL often begins
-            with `https://cloud.mongodb.com/api/atlas`.
-          example: https://cloud.mongodb.com/api/atlas
-        rel:
-          type: string
-          description: Uniform Resource Locator (URL) that defines the semantic
-            relationship between this resource and another API resource. This
-            URL often begins with `https://cloud.mongodb.com/api/atlas`.
-          example: self
     NestedTestResourceResponse:
       type: object
       properties:

From 16450d62bb4d92b1fba96fbc22e13db23032cb02 Mon Sep 17 00:00:00 2001
From: Aastha Mahendru <aastha.mahendru@mongodb.com>
Date: Tue, 15 Oct 2024 17:38:23 +0100
Subject: [PATCH 04/12] minor

---
 tools/codegen/codespec/merge_attributes.go | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tools/codegen/codespec/merge_attributes.go b/tools/codegen/codespec/merge_attributes.go
index 697cccf465..c722df4f13 100644
--- a/tools/codegen/codespec/merge_attributes.go
+++ b/tools/codegen/codespec/merge_attributes.go
@@ -2,6 +2,7 @@ package codespec
 
 import "sort"
 
+// TODO: update to infer computability of inner nested attributes
 func mergeAttributes(pathParams, createRequest, createResponse, readResponse Attributes) Attributes {
 	merged := make(map[string]*Attribute)
 

From 18d39e7ac74f0cd96f7eaf2e90f43ed8f38cdbff Mon Sep 17 00:00:00 2001
From: Aastha Mahendru <aastha.mahendru@mongodb.com>
Date: Tue, 15 Oct 2024 17:41:17 +0100
Subject: [PATCH 05/12] minor

---
 tools/codegen/codespec/testdata/api-spec.yml | 72 --------------------
 1 file changed, 72 deletions(-)

diff --git a/tools/codegen/codespec/testdata/api-spec.yml b/tools/codegen/codespec/testdata/api-spec.yml
index 29b7a6aeb0..3653f8a3a3 100644
--- a/tools/codegen/codespec/testdata/api-spec.yml
+++ b/tools/codegen/codespec/testdata/api-spec.yml
@@ -140,12 +140,6 @@ paths:
                 $ref: "#/components/schemas/NoBody"
               x-xgen-version: 2024-05-30
           description: This endpoint does not return a response body.
-        "400":
-          $ref: "#/components/responses/badRequest"
-        "404":
-          $ref: "#/components/responses/notFound"
-        "500":
-          $ref: "#/components/responses/internalServerError"
       security:
         - DigestAuth: []
       summary: Delete Search Nodes
@@ -173,12 +167,6 @@ paths:
                 $ref: "#/components/schemas/NestedTestResourceResponse"
               x-xgen-version: 2024-05-30
           description: OK
-        "400":
-          $ref: "#/components/responses/badRequest"
-        "404":
-          $ref: "#/components/responses/notFound"
-        "500":
-          $ref: "#/components/responses/internalServerError"
       security:
         - DigestAuth: []
       summary: Return Search Nodes
@@ -213,12 +201,6 @@ paths:
                 $ref: "#/components/schemas/NestedTestResourceResponse"
               x-xgen-version: 2024-05-30
           description: OK
-        "400":
-          $ref: "#/components/responses/badRequest"
-        "404":
-          $ref: "#/components/responses/notFound"
-        "500":
-          $ref: "#/components/responses/internalServerError"
       security:
         - DigestAuth: []
       summary: Update Search Nodes
@@ -253,12 +235,6 @@ paths:
                 $ref: "#/components/schemas/NestedTestResourceResponse"
               x-xgen-version: 2024-05-30
           description: Created
-        "400":
-          $ref: "#/components/responses/badRequest"
-        "404":
-          $ref: "#/components/responses/notFound"
-        "500":
-          $ref: "#/components/responses/internalServerError"
       security:
         - DigestAuth: []
       summary: Create Nested Test Resource
@@ -281,44 +257,6 @@ components:
   responses:
     accepted:
       description: Accepted.
-    badRequest:
-      content:
-        application/json:
-          example:
-            detail: (This is just an example, the exception may not be related to this
-              endpoint) No provider AWS exists.
-            error: 400
-            errorCode: VALIDATION_ERROR
-            reason: Bad Request
-          schema:
-            $ref: "#/components/schemas/ApiError"
-      description: Bad Request.
-    internalServerError:
-      content:
-        application/json:
-          example:
-            detail: (This is just an example, the exception may not be related to this
-              endpoint)
-            error: 500
-            errorCode: UNEXPECTED_ERROR
-            reason: Internal Server Error
-          schema:
-            $ref: "#/components/schemas/ApiError"
-      description: Internal Server Error.
-    noBody:
-      description: This endpoint does not return a response body.
-    notFound:
-      content:
-        application/json:
-          example:
-            detail: (This is just an example, the exception may not be related to this
-              endpoint) Cannot find resource AWS
-            error: 404
-            errorCode: RESOURCE_NOT_FOUND
-            reason: Not Found
-          schema:
-            $ref: "#/components/schemas/ApiError"
-      description: Not Found.
   schemas:
     CreateTestResourceRequest:
       type: object
@@ -485,13 +423,3 @@ components:
     NoBody:
       type: object
       description: Endpoint does not return a response body.
-    FieldViolation:
-      type: object
-      properties:
-        description:
-          type: string
-          description: A description of why the request element is bad.
-        field:
-          type: string
-          description: A path that leads to a field in the request body.
-   
\ No newline at end of file

From bf4beaf251673066a1c871688d13e9e8cff36267 Mon Sep 17 00:00:00 2001
From: Aastha Mahendru <aastha.mahendru@mongodb.com>
Date: Tue, 15 Oct 2024 17:44:37 +0100
Subject: [PATCH 06/12] cleanup

---
 tools/codegen/codespec/testdata/api-spec.yml | 34 --------------------
 1 file changed, 34 deletions(-)

diff --git a/tools/codegen/codespec/testdata/api-spec.yml b/tools/codegen/codespec/testdata/api-spec.yml
index 3653f8a3a3..abb140e583 100644
--- a/tools/codegen/codespec/testdata/api-spec.yml
+++ b/tools/codegen/codespec/testdata/api-spec.yml
@@ -386,40 +386,6 @@ components:
           minItems: 1
       required:
         - nestedObjectArrayAttr
-    ApiError:
-      type: object
-      properties:
-        badRequestDetail:
-          $ref: "#/components/schemas/BadRequestDetail"
-        detail:
-          type: string
-          description: Describes the specific conditions or reasons that cause each type
-            of error.
-        error:
-          type: integer
-          format: int32
-          description: HTTP status code returned with this error.
-          externalDocs:
-            url: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
-        errorCode:
-          type: string
-          description: Application error code returned with this error.
-        parameters:
-          type: array
-          description: Parameters used to give more information about the error.
-          items: {}
-        reason:
-          type: string
-          description: Application error message returned with this error.
-    BadRequestDetail:
-      type: object
-      description: Bad request detail.
-      properties:
-        fields:
-          type: array
-          description: Describes all violations in a client request.
-          items:
-            $ref: "#/components/schemas/FieldViolation"
     NoBody:
       type: object
       description: Endpoint does not return a response body.

From 4705ae02d9532a6aa168b38086aa8b8f39d64221 Mon Sep 17 00:00:00 2001
From: Aastha Mahendru <aastha.mahendru@mongodb.com>
Date: Wed, 16 Oct 2024 11:24:09 +0100
Subject: [PATCH 07/12] add support for sets

---
 .../api_to_provider_spec_mapper_test.go       |  8 +++
 tools/codegen/codespec/attribute.go           | 51 +++++++++++--------
 tools/codegen/codespec/element_type.go        | 13 +----
 tools/codegen/codespec/model.go               | 11 ++++
 tools/codegen/codespec/testdata/api-spec.yml  |  8 ++-
 5 files changed, 56 insertions(+), 35 deletions(-)

diff --git a/tools/codegen/codespec/api_to_provider_spec_mapper_test.go b/tools/codegen/codespec/api_to_provider_spec_mapper_test.go
index a507f960bb..94e033bfd4 100644
--- a/tools/codegen/codespec/api_to_provider_spec_mapper_test.go
+++ b/tools/codegen/codespec/api_to_provider_spec_mapper_test.go
@@ -174,6 +174,14 @@ func TestConvertToProviderSpec_nested(t *testing.T) {
 								},
 								Description: conversion.StringPtr(testFieldDesc),
 							},
+							{
+								Name:                     "set_primitive_string_attr",
+								ComputedOptionalRequired: codespec.Computed,
+								Set: &codespec.SetAttribute{
+									ElementType: codespec.String,
+								},
+								Description: conversion.StringPtr(testFieldDesc),
+							},
 							{
 								Name:                     "str_computed_attr",
 								ComputedOptionalRequired: codespec.Computed,
diff --git a/tools/codegen/codespec/attribute.go b/tools/codegen/codespec/attribute.go
index 81d274b65c..3b20f5aaba 100644
--- a/tools/codegen/codespec/attribute.go
+++ b/tools/codegen/codespec/attribute.go
@@ -150,30 +150,47 @@ func (s *APISpecSchema) buildArrayAttr(name string, computability ComputedOption
 	if !s.Schema.Items.IsA() {
 		return nil, fmt.Errorf("invalid array items property, schema doesn't exist: %s", name)
 	}
+
 	itemSchema, err := BuildSchema(s.Schema.Items.A)
 	if err != nil {
 		return nil, fmt.Errorf("error while building nested schema: %s", name)
 	}
 
-	if itemSchema.Type == OASTypeObject { // TODO: add support for Set and SetNested Attributes
-		objectAttributes, err := buildResourceAttrs(itemSchema)
-		if err != nil {
-			return nil, fmt.Errorf("error while building nested schema: %s", name)
-		}
+	isSet := s.Schema.UniqueItems != nil && *s.Schema.UniqueItems
 
-		result := &Attribute{
+	createAttribute := func(nestedObject *NestedAttributeObject, elemType ElemType) *Attribute {
+		attr := &Attribute{
 			Name:                     terraformAttrName(name),
 			ComputedOptionalRequired: computability,
 			DeprecationMessage:       s.GetDeprecationMessage(),
 			Description:              s.GetDescription(),
-			ListNested: &ListNestedAttribute{
-				NestedObject: NestedAttributeObject{
-					Attributes: objectAttributes,
-				},
-			},
 		}
 
-		return result, nil
+		if nestedObject != nil {
+			if isSet {
+				attr.SetNested = &SetNestedAttribute{NestedObject: *nestedObject}
+			} else {
+				attr.ListNested = &ListNestedAttribute{NestedObject: *nestedObject}
+			}
+		} else {
+			if isSet {
+				attr.Set = &SetAttribute{ElementType: elemType}
+			} else {
+				attr.List = &ListAttribute{ElementType: elemType}
+			}
+		}
+
+		return attr
+	}
+
+	if itemSchema.Type == OASTypeObject {
+		objectAttributes, err := buildResourceAttrs(itemSchema)
+		if err != nil {
+			return nil, fmt.Errorf("error while building nested schema: %s", name)
+		}
+		nestedObject := &NestedAttributeObject{Attributes: objectAttributes}
+
+		return createAttribute(nestedObject, Unknown), nil // Using Unknown ElemType as a placeholder for no ElemType
 	}
 
 	elemType, err := itemSchema.buildElementType()
@@ -181,15 +198,7 @@ func (s *APISpecSchema) buildArrayAttr(name string, computability ComputedOption
 		return nil, fmt.Errorf("error while building nested schema: %s", name)
 	}
 
-	result := &Attribute{
-		Name:                     terraformAttrName(name),
-		ComputedOptionalRequired: computability,
-		DeprecationMessage:       s.GetDeprecationMessage(),
-		Description:              s.GetDescription(),
-		List: &ListAttribute{
-			ElementType: elemType,
-		},
-	}
+	result := createAttribute(nil, elemType)
 
 	if s.Schema.Default != nil {
 		var staticDefault bool
diff --git a/tools/codegen/codespec/element_type.go b/tools/codegen/codespec/element_type.go
index c27dada213..1546786211 100644
--- a/tools/codegen/codespec/element_type.go
+++ b/tools/codegen/codespec/element_type.go
@@ -2,17 +2,6 @@ package codespec
 
 import "fmt"
 
-type ElemType int
-
-const (
-	Bool ElemType = iota
-	Float64
-	Int64
-	Number
-	String
-	Unknown
-)
-
 func (s *APISpecSchema) buildElementType() (ElemType, error) {
 	switch s.Type {
 	case OASTypeString:
@@ -24,7 +13,7 @@ func (s *APISpecSchema) buildElementType() (ElemType, error) {
 	case OASTypeNumber:
 		return Number, nil
 	case OASTypeArray, OASTypeObject:
-		return Unknown, nil // ignoring because complex element types unsupported
+		return String, nil // complex element types are unsupported so this defaults to string for now to provide best effort generation
 	default:
 		return Unknown, fmt.Errorf("invalid schema type '%s'", s.Type)
 	}
diff --git a/tools/codegen/codespec/model.go b/tools/codegen/codespec/model.go
index abdb21aab2..a0700b91da 100644
--- a/tools/codegen/codespec/model.go
+++ b/tools/codegen/codespec/model.go
@@ -1,5 +1,16 @@
 package codespec
 
+type ElemType int
+
+const (
+	Bool ElemType = iota
+	Float64
+	Int64
+	Number
+	String
+	Unknown
+)
+
 type Model struct {
 	Resources []Resource
 }
diff --git a/tools/codegen/codespec/testdata/api-spec.yml b/tools/codegen/codespec/testdata/api-spec.yml
index abb140e583..70903f0334 100644
--- a/tools/codegen/codespec/testdata/api-spec.yml
+++ b/tools/codegen/codespec/testdata/api-spec.yml
@@ -342,12 +342,17 @@ components:
           items:
             $ref: "#/components/schemas/NestedObjectAttr"
           readOnly: true
-        listPrimitiveStringAttr:
+        setPrimitiveStringAttr:
           type: array
           description: Test field description
           items:
             type: string
           uniqueItems: true
+        listPrimitiveStringAttr:
+          type: array
+          description: Test field description
+          items:
+            type: string
         strComputedAttr:
           type: string
           description: Test field description
@@ -370,7 +375,6 @@ components:
           description: Test field description
           items:
             type: string
-          uniqueItems: true
       required:
         - innerStrAttr
         - innerNumAttr

From c0aa200bc14eef58616a5994cd367ee5f4343939 Mon Sep 17 00:00:00 2001
From: Aastha Mahendru <aastha.mahendru@mongodb.com>
Date: Wed, 16 Oct 2024 12:21:44 +0100
Subject: [PATCH 08/12] add set format

---
 tools/codegen/codespec/attribute.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/codegen/codespec/attribute.go b/tools/codegen/codespec/attribute.go
index 3b20f5aaba..d8b767efef 100644
--- a/tools/codegen/codespec/attribute.go
+++ b/tools/codegen/codespec/attribute.go
@@ -156,7 +156,7 @@ func (s *APISpecSchema) buildArrayAttr(name string, computability ComputedOption
 		return nil, fmt.Errorf("error while building nested schema: %s", name)
 	}
 
-	isSet := s.Schema.UniqueItems != nil && *s.Schema.UniqueItems
+	isSet := s.Schema.Format == OASFormatSet || (s.Schema.UniqueItems != nil && *s.Schema.UniqueItems)
 
 	createAttribute := func(nestedObject *NestedAttributeObject, elemType ElemType) *Attribute {
 		attr := &Attribute{

From 5147a270b071fc583d0629b6633296732c84837a Mon Sep 17 00:00:00 2001
From: Aastha Mahendru <aastha.mahendru@mongodb.com>
Date: Wed, 16 Oct 2024 12:21:50 +0100
Subject: [PATCH 09/12] minor

---
 tools/codegen/codespec/constants.go | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tools/codegen/codespec/constants.go b/tools/codegen/codespec/constants.go
index 12f09506ca..cd41c1b8c0 100644
--- a/tools/codegen/codespec/constants.go
+++ b/tools/codegen/codespec/constants.go
@@ -10,6 +10,7 @@ const (
 	OASFormatDouble   = "double"
 	OASFormatFloat    = "float"
 	OASFormatPassword = "password"
+	OASFormatSet      = "set"
 
 	OASResponseCodeOK      = "200"
 	OASResponseCodeCreated = "201"

From 8b03a314a816c870d724d82e67470a36028b6aad Mon Sep 17 00:00:00 2001
From: Aastha Mahendru <aastha.mahendru@mongodb.com>
Date: Wed, 16 Oct 2024 15:48:37 +0100
Subject: [PATCH 10/12] add maps and singles nested attr

---
 .../api_to_provider_spec_mapper_test.go       | 79 ++++++++++++++++---
 tools/codegen/codespec/attribute.go           | 74 ++++++++++++++++-
 tools/codegen/codespec/testdata/api-spec.yml  | 60 ++++++++++----
 3 files changed, 184 insertions(+), 29 deletions(-)

diff --git a/tools/codegen/codespec/api_to_provider_spec_mapper_test.go b/tools/codegen/codespec/api_to_provider_spec_mapper_test.go
index 94e033bfd4..6f9076b395 100644
--- a/tools/codegen/codespec/api_to_provider_spec_mapper_test.go
+++ b/tools/codegen/codespec/api_to_provider_spec_mapper_test.go
@@ -129,12 +129,6 @@ func TestConvertToProviderSpec_nested(t *testing.T) {
 								String:                   &codespec.StringAttribute{},
 								Description:              conversion.StringPtr(testPathParamDesc),
 							},
-							{
-								Name:                     "id",
-								ComputedOptionalRequired: codespec.Computed,
-								String:                   &codespec.StringAttribute{},
-								Description:              conversion.StringPtr(testFieldDesc),
-							},
 							{
 								Name:                     "list_primitive_string_attr",
 								ComputedOptionalRequired: codespec.Computed,
@@ -144,7 +138,7 @@ func TestConvertToProviderSpec_nested(t *testing.T) {
 								Description: conversion.StringPtr(testFieldDesc),
 							},
 							{
-								Name:                     "nested_object_array_attr",
+								Name:                     "nested_object_array_list_attr",
 								ComputedOptionalRequired: codespec.Required,
 								ListNested: &codespec.ListNestedAttribute{
 									NestedObject: codespec.NestedAttributeObject{
@@ -156,9 +150,28 @@ func TestConvertToProviderSpec_nested(t *testing.T) {
 												Description:              conversion.StringPtr(testFieldDesc),
 											},
 											{
-												Name:                     "inner_str_attr",
+												Name:                     "list_primitive_string_attr",
+												ComputedOptionalRequired: codespec.Optional,
+												List: &codespec.ListAttribute{
+													ElementType: codespec.String,
+												},
+												Description: conversion.StringPtr(testFieldDesc),
+											},
+										},
+									},
+								},
+								Description: conversion.StringPtr(testFieldDesc),
+							},
+							{
+								Name:                     "nested_object_array_set_attr",
+								ComputedOptionalRequired: codespec.Computed,
+								SetNested: &codespec.SetNestedAttribute{
+									NestedObject: codespec.NestedAttributeObject{
+										Attributes: codespec.Attributes{
+											{
+												Name:                     "inner_num_attr",
 												ComputedOptionalRequired: codespec.Required,
-												String:                   &codespec.StringAttribute{},
+												Int64:                    &codespec.Int64Attribute{},
 												Description:              conversion.StringPtr(testFieldDesc),
 											},
 											{
@@ -183,10 +196,52 @@ func TestConvertToProviderSpec_nested(t *testing.T) {
 								Description: conversion.StringPtr(testFieldDesc),
 							},
 							{
-								Name:                     "str_computed_attr",
+								Name:                     "single_nested_attr",
 								ComputedOptionalRequired: codespec.Computed,
-								String:                   &codespec.StringAttribute{},
-								Description:              conversion.StringPtr(testFieldDesc),
+								SingleNested: &codespec.SingleNestedAttribute{
+									NestedObject: codespec.NestedAttributeObject{
+										Attributes: codespec.Attributes{
+											{
+												Name:                     "inner_int_attr",
+												ComputedOptionalRequired: codespec.Required,
+												Int64:                    &codespec.Int64Attribute{},
+												Description:              conversion.StringPtr(testFieldDesc),
+											},
+											{
+												Name:                     "inner_str_attr",
+												ComputedOptionalRequired: codespec.Required,
+												String:                   &codespec.StringAttribute{},
+												Description:              conversion.StringPtr(testFieldDesc),
+											},
+										},
+									},
+								},
+								Description: conversion.StringPtr(testFieldDesc),
+							},
+							{
+								Name:                     "single_nested_attr_with_nested_maps",
+								ComputedOptionalRequired: codespec.Computed,
+								SingleNested: &codespec.SingleNestedAttribute{
+									NestedObject: codespec.NestedAttributeObject{
+										Attributes: codespec.Attributes{
+											{
+												Name:                     "aws",
+												ComputedOptionalRequired: codespec.Optional,
+												Map: &codespec.MapAttribute{
+													ElementType: codespec.String,
+												},
+											},
+											{
+												Name:                     "azure",
+												ComputedOptionalRequired: codespec.Optional,
+												Map: &codespec.MapAttribute{
+													ElementType: codespec.String,
+												},
+											},
+										},
+									},
+								},
+								Description: conversion.StringPtr(testFieldDesc),
 							},
 						},
 					},
diff --git a/tools/codegen/codespec/attribute.go b/tools/codegen/codespec/attribute.go
index d8b767efef..e6e299decd 100644
--- a/tools/codegen/codespec/attribute.go
+++ b/tools/codegen/codespec/attribute.go
@@ -46,7 +46,10 @@ func (s *APISpecSchema) buildResourceAttr(name string, computability ComputedOpt
 	case OASTypeArray:
 		return s.buildArrayAttr(name, computability)
 	case OASTypeObject:
-		return nil, nil // TODO: add support for SingleNestedObject and MapAttribute
+		if s.Schema.AdditionalProperties != nil {
+			return s.buildMapAttr(name, computability)
+		}
+		return s.buildSingleNestedAttr(name, computability)
 	default:
 		return nil, fmt.Errorf("invalid schema type '%s'", s.Type)
 	}
@@ -210,3 +213,72 @@ func (s *APISpecSchema) buildArrayAttr(name string, computability ComputedOption
 
 	return result, nil
 }
+
+func (s *APISpecSchema) buildMapAttr(name string, computability ComputedOptionalRequired) (*Attribute, error) {
+	// // Maps are detected as `type: object`, with an `additionalProperties` field that is a schema. `additionalProperties` can
+	// // also be a boolean (which we should ignore and map to an SingleNestedAttribute), so calling functions should call s.IsMap() first.
+	// if !s.IsMap() {
+	// 	return nil, s.SchemaErrorFromProperty(errors.New("invalid map, additionalProperties doesn't have a valid schema"), name)
+	// }
+
+	mapSchema, err := BuildSchema(s.Schema.AdditionalProperties.A)
+	if err != nil {
+		return nil, err
+	}
+
+	if mapSchema.Type == OASTypeObject {
+		mapAttributes, err := buildResourceAttrs(mapSchema)
+		if err != nil {
+			return nil, err
+		}
+		result := &Attribute{
+			Name:                     terraformAttrName(name),
+			ComputedOptionalRequired: computability,
+			DeprecationMessage:       s.GetDeprecationMessage(),
+			Description:              s.GetDescription(),
+			MapNested: &MapNestedAttribute{
+				NestedObject: NestedAttributeObject{
+					Attributes: mapAttributes,
+				},
+			},
+		}
+
+		return result, nil
+	}
+
+	elemType, err := mapSchema.buildElementType()
+	if err != nil {
+		return nil, err
+	}
+
+	result := &Attribute{
+		Name:                     terraformAttrName(name),
+		ComputedOptionalRequired: computability,
+		DeprecationMessage:       s.GetDeprecationMessage(),
+		Description:              s.GetDescription(),
+		Map: &MapAttribute{
+			ElementType: elemType,
+		},
+	}
+
+	return result, nil
+}
+
+func (s *APISpecSchema) buildSingleNestedAttr(name string, computability ComputedOptionalRequired) (*Attribute, error) {
+	objectAttributes, err := buildResourceAttrs(s)
+	if err != nil {
+		return nil, err
+	}
+
+	return &Attribute{
+		Name:                     terraformAttrName(name),
+		ComputedOptionalRequired: computability,
+		DeprecationMessage:       s.GetDeprecationMessage(),
+		Description:              s.GetDescription(),
+		SingleNested: &SingleNestedAttribute{
+			NestedObject: NestedAttributeObject{
+				Attributes: objectAttributes,
+			},
+		},
+	}, nil
+}
diff --git a/tools/codegen/codespec/testdata/api-spec.yml b/tools/codegen/codespec/testdata/api-spec.yml
index 70903f0334..83d78bdd69 100644
--- a/tools/codegen/codespec/testdata/api-spec.yml
+++ b/tools/codegen/codespec/testdata/api-spec.yml
@@ -328,20 +328,19 @@ components:
           minLength: 24
           pattern: ^([a-f0-9]{24})$
           readOnly: true
-        id:
-          type: string
+        nestedObjectArrayListAttr:
+          type: array
           description: Test field description
-          example: 32b6e34b3d91647abb20e7b8
-          maxLength: 24
-          minLength: 24
-          pattern: ^([a-f0-9]{24})$
+          items:
+            $ref: "#/components/schemas/NestedObjectAttr"
           readOnly: true
-        nestedObjectArrayAttr:
+        nestedObjectArraySetAttr:
           type: array
           description: Test field description
           items:
             $ref: "#/components/schemas/NestedObjectAttr"
           readOnly: true
+          uniqueItems: true
         setPrimitiveStringAttr:
           type: array
           description: Test field description
@@ -353,16 +352,43 @@ components:
           description: Test field description
           items:
             type: string
-        strComputedAttr:
-          type: string
-          description: Test field description
+        singleNestedAttrWithNestedMaps:
+          $ref: "#/components/schemas/SingleNestedAttrWithNestedMaps"
+        singleNestedAttr:
+          $ref: "#/components/schemas/SingleNestedAttr"
+    SingleNestedAttrWithNestedMaps:
+      type: object
+      description: Test field description
+      properties:
+        aws:
+          type: object
+          additionalProperties:
+            type: string
+            readOnly: true
           readOnly: true
-    NestedObjectAttr:
+        azure:
+          type: object
+          additionalProperties:
+            type: string
+            readOnly: true
+          readOnly: true
+      readOnly: true
+      title: Outbound Control Plane IP Addresses By Cloud Provider
+    SingleNestedAttr:
       type: object
+      description: Test field description
       properties:
-        innerStrAttr:
-          type: string
+        innerIntAttr:
+          type: integer
           description: Test field description
+        innerStrAttr:
+          $ref: "#/components/schemas/SimpleStringRefObject"
+      required:
+        - innerIntAttr
+        - innerStrAttr
+    NestedObjectAttr:
+      type: object
+      properties:
         innerNumAttr:
           type: integer
           format: int32
@@ -376,12 +402,11 @@ components:
           items:
             type: string
       required:
-        - innerStrAttr
         - innerNumAttr
     NestedTestResourceRequest:
       type: object
       properties:
-        nestedObjectArrayAttr:
+        nestedObjectArrayListAttr:
           type: array
           description: Test field description
           items:
@@ -389,7 +414,10 @@ components:
           maxItems: 1
           minItems: 1
       required:
-        - nestedObjectArrayAttr
+        - nestedObjectArrayListAttr
+    SimpleStringRefObject:
+      type: string
+      description: Test field description
     NoBody:
       type: object
       description: Endpoint does not return a response body.

From 47e1c29ca56af38ef00b7ed33419b53830d99448 Mon Sep 17 00:00:00 2001
From: Aastha Mahendru <aastha.mahendru@mongodb.com>
Date: Wed, 16 Oct 2024 16:36:48 +0100
Subject: [PATCH 11/12] update test o use nested map

---
 .../codespec/api_to_provider_spec_mapper_test.go  | 15 +++++++++++++++
 tools/codegen/codespec/testdata/api-spec.yml      | 10 ++++++++++
 2 files changed, 25 insertions(+)

diff --git a/tools/codegen/codespec/api_to_provider_spec_mapper_test.go b/tools/codegen/codespec/api_to_provider_spec_mapper_test.go
index 6f9076b395..16745caad5 100644
--- a/tools/codegen/codespec/api_to_provider_spec_mapper_test.go
+++ b/tools/codegen/codespec/api_to_provider_spec_mapper_test.go
@@ -187,6 +187,21 @@ func TestConvertToProviderSpec_nested(t *testing.T) {
 								},
 								Description: conversion.StringPtr(testFieldDesc),
 							},
+							{
+								Name:                     "nested_object_map_attr",
+								ComputedOptionalRequired: codespec.Computed,
+								MapNested: &codespec.MapNestedAttribute{
+									NestedObject: codespec.NestedAttributeObject{
+										Attributes: codespec.Attributes{
+											{
+												Name:                     "attr",
+												ComputedOptionalRequired: codespec.Optional,
+												String:                   &codespec.StringAttribute{},
+											},
+										},
+									},
+								},
+							},
 							{
 								Name:                     "set_primitive_string_attr",
 								ComputedOptionalRequired: codespec.Computed,
diff --git a/tools/codegen/codespec/testdata/api-spec.yml b/tools/codegen/codespec/testdata/api-spec.yml
index 83d78bdd69..62ded9b5d3 100644
--- a/tools/codegen/codespec/testdata/api-spec.yml
+++ b/tools/codegen/codespec/testdata/api-spec.yml
@@ -356,6 +356,8 @@ components:
           $ref: "#/components/schemas/SingleNestedAttrWithNestedMaps"
         singleNestedAttr:
           $ref: "#/components/schemas/SingleNestedAttr"
+        nestedObjectMapAttr:
+          $ref: "#/components/schemas/NestedObjectMapAttr"
     SingleNestedAttrWithNestedMaps:
       type: object
       description: Test field description
@@ -421,3 +423,11 @@ components:
     NoBody:
       type: object
       description: Endpoint does not return a response body.
+    NestedObjectMapAttr:
+      type: object
+      additionalProperties:
+        type: object
+        properties:
+          attr:
+            type: string
+

From 1150ec44ef1d4a9f32c4844fc9a4405f00e80008 Mon Sep 17 00:00:00 2001
From: Aastha Mahendru <aastha.mahendru@mongodb.com>
Date: Wed, 16 Oct 2024 16:59:56 +0100
Subject: [PATCH 12/12] minor

---
 .../api_to_provider_spec_mapper_test.go       | 38 +++++++-------
 tools/codegen/codespec/attribute.go           | 50 +++++++------------
 tools/codegen/codespec/testdata/api-spec.yml  | 18 +++----
 3 files changed, 47 insertions(+), 59 deletions(-)

diff --git a/tools/codegen/codespec/api_to_provider_spec_mapper_test.go b/tools/codegen/codespec/api_to_provider_spec_mapper_test.go
index 16745caad5..3caafe6076 100644
--- a/tools/codegen/codespec/api_to_provider_spec_mapper_test.go
+++ b/tools/codegen/codespec/api_to_provider_spec_mapper_test.go
@@ -138,7 +138,7 @@ func TestConvertToProviderSpec_nested(t *testing.T) {
 								Description: conversion.StringPtr(testFieldDesc),
 							},
 							{
-								Name:                     "nested_object_array_list_attr",
+								Name:                     "nested_list_array_attr",
 								ComputedOptionalRequired: codespec.Required,
 								ListNested: &codespec.ListNestedAttribute{
 									NestedObject: codespec.NestedAttributeObject{
@@ -163,7 +163,22 @@ func TestConvertToProviderSpec_nested(t *testing.T) {
 								Description: conversion.StringPtr(testFieldDesc),
 							},
 							{
-								Name:                     "nested_object_array_set_attr",
+								Name:                     "nested_map_object_attr",
+								ComputedOptionalRequired: codespec.Computed,
+								MapNested: &codespec.MapNestedAttribute{
+									NestedObject: codespec.NestedAttributeObject{
+										Attributes: codespec.Attributes{
+											{
+												Name:                     "attr",
+												ComputedOptionalRequired: codespec.Optional,
+												String:                   &codespec.StringAttribute{},
+											},
+										},
+									},
+								},
+							},
+							{
+								Name:                     "nested_set_array_attr",
 								ComputedOptionalRequired: codespec.Computed,
 								SetNested: &codespec.SetNestedAttribute{
 									NestedObject: codespec.NestedAttributeObject{
@@ -187,21 +202,6 @@ func TestConvertToProviderSpec_nested(t *testing.T) {
 								},
 								Description: conversion.StringPtr(testFieldDesc),
 							},
-							{
-								Name:                     "nested_object_map_attr",
-								ComputedOptionalRequired: codespec.Computed,
-								MapNested: &codespec.MapNestedAttribute{
-									NestedObject: codespec.NestedAttributeObject{
-										Attributes: codespec.Attributes{
-											{
-												Name:                     "attr",
-												ComputedOptionalRequired: codespec.Optional,
-												String:                   &codespec.StringAttribute{},
-											},
-										},
-									},
-								},
-							},
 							{
 								Name:                     "set_primitive_string_attr",
 								ComputedOptionalRequired: codespec.Computed,
@@ -240,14 +240,14 @@ func TestConvertToProviderSpec_nested(t *testing.T) {
 									NestedObject: codespec.NestedAttributeObject{
 										Attributes: codespec.Attributes{
 											{
-												Name:                     "aws",
+												Name:                     "map_attr1",
 												ComputedOptionalRequired: codespec.Optional,
 												Map: &codespec.MapAttribute{
 													ElementType: codespec.String,
 												},
 											},
 											{
-												Name:                     "azure",
+												Name:                     "map_attr2",
 												ComputedOptionalRequired: codespec.Optional,
 												Map: &codespec.MapAttribute{
 													ElementType: codespec.String,
diff --git a/tools/codegen/codespec/attribute.go b/tools/codegen/codespec/attribute.go
index e6e299decd..d2444aaf0d 100644
--- a/tools/codegen/codespec/attribute.go
+++ b/tools/codegen/codespec/attribute.go
@@ -46,7 +46,7 @@ func (s *APISpecSchema) buildResourceAttr(name string, computability ComputedOpt
 	case OASTypeArray:
 		return s.buildArrayAttr(name, computability)
 	case OASTypeObject:
-		if s.Schema.AdditionalProperties != nil {
+		if s.Schema.AdditionalProperties != nil && s.Schema.AdditionalProperties.IsA() {
 			return s.buildMapAttr(name, computability)
 		}
 		return s.buildSingleNestedAttr(name, computability)
@@ -215,50 +215,38 @@ func (s *APISpecSchema) buildArrayAttr(name string, computability ComputedOption
 }
 
 func (s *APISpecSchema) buildMapAttr(name string, computability ComputedOptionalRequired) (*Attribute, error) {
-	// // Maps are detected as `type: object`, with an `additionalProperties` field that is a schema. `additionalProperties` can
-	// // also be a boolean (which we should ignore and map to an SingleNestedAttribute), so calling functions should call s.IsMap() first.
-	// if !s.IsMap() {
-	// 	return nil, s.SchemaErrorFromProperty(errors.New("invalid map, additionalProperties doesn't have a valid schema"), name)
-	// }
-
 	mapSchema, err := BuildSchema(s.Schema.AdditionalProperties.A)
 	if err != nil {
 		return nil, err
 	}
 
+	result := &Attribute{
+		Name:                     terraformAttrName(name),
+		ComputedOptionalRequired: computability,
+		DeprecationMessage:       s.GetDeprecationMessage(),
+		Description:              s.GetDescription(),
+	}
+
 	if mapSchema.Type == OASTypeObject {
 		mapAttributes, err := buildResourceAttrs(mapSchema)
 		if err != nil {
 			return nil, err
 		}
-		result := &Attribute{
-			Name:                     terraformAttrName(name),
-			ComputedOptionalRequired: computability,
-			DeprecationMessage:       s.GetDeprecationMessage(),
-			Description:              s.GetDescription(),
-			MapNested: &MapNestedAttribute{
-				NestedObject: NestedAttributeObject{
-					Attributes: mapAttributes,
-				},
+
+		result.MapNested = &MapNestedAttribute{
+			NestedObject: NestedAttributeObject{
+				Attributes: mapAttributes,
 			},
 		}
+	} else {
+		elemType, err := mapSchema.buildElementType()
+		if err != nil {
+			return nil, err
+		}
 
-		return result, nil
-	}
-
-	elemType, err := mapSchema.buildElementType()
-	if err != nil {
-		return nil, err
-	}
-
-	result := &Attribute{
-		Name:                     terraformAttrName(name),
-		ComputedOptionalRequired: computability,
-		DeprecationMessage:       s.GetDeprecationMessage(),
-		Description:              s.GetDescription(),
-		Map: &MapAttribute{
+		result.Map = &MapAttribute{
 			ElementType: elemType,
-		},
+		}
 	}
 
 	return result, nil
diff --git a/tools/codegen/codespec/testdata/api-spec.yml b/tools/codegen/codespec/testdata/api-spec.yml
index 62ded9b5d3..006f0c13d3 100644
--- a/tools/codegen/codespec/testdata/api-spec.yml
+++ b/tools/codegen/codespec/testdata/api-spec.yml
@@ -328,13 +328,13 @@ components:
           minLength: 24
           pattern: ^([a-f0-9]{24})$
           readOnly: true
-        nestedObjectArrayListAttr:
+        nestedListArrayAttr:
           type: array
           description: Test field description
           items:
             $ref: "#/components/schemas/NestedObjectAttr"
           readOnly: true
-        nestedObjectArraySetAttr:
+        nestedSetArrayAttr:
           type: array
           description: Test field description
           items:
@@ -356,19 +356,19 @@ components:
           $ref: "#/components/schemas/SingleNestedAttrWithNestedMaps"
         singleNestedAttr:
           $ref: "#/components/schemas/SingleNestedAttr"
-        nestedObjectMapAttr:
-          $ref: "#/components/schemas/NestedObjectMapAttr"
+        nestedMapObjectAttr:
+          $ref: "#/components/schemas/NestedMapObjectAttr"
     SingleNestedAttrWithNestedMaps:
       type: object
       description: Test field description
       properties:
-        aws:
+        mapAttr1:
           type: object
           additionalProperties:
             type: string
             readOnly: true
           readOnly: true
-        azure:
+        mapAttr2:
           type: object
           additionalProperties:
             type: string
@@ -408,7 +408,7 @@ components:
     NestedTestResourceRequest:
       type: object
       properties:
-        nestedObjectArrayListAttr:
+        nestedListArrayAttr:
           type: array
           description: Test field description
           items:
@@ -416,14 +416,14 @@ components:
           maxItems: 1
           minItems: 1
       required:
-        - nestedObjectArrayListAttr
+        - nestedListArrayAttr
     SimpleStringRefObject:
       type: string
       description: Test field description
     NoBody:
       type: object
       description: Endpoint does not return a response body.
-    NestedObjectMapAttr:
+    NestedMapObjectAttr:
       type: object
       additionalProperties:
         type: object