Skip to content

Commit 6f2c534

Browse files
committed
Apply the DataSource refactor to the InventoryDataSource and related tests
1 parent edc0b4d commit 6f2c534

File tree

5 files changed

+68
-280
lines changed

5 files changed

+68
-280
lines changed

docs/data-sources/inventory.md

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
---
22
page_title: "aap_inventory Data Source - terraform-provider-aap"
33
description: |-
4-
Get an existing inventory.
4+
55
---
66

77
# aap_inventory (Data Source)
88

9-
Get an existing inventory.
9+
1010

1111

1212
## Example Usage
@@ -53,17 +53,3 @@ output "inventory_details_with_name_and_org_name" {
5353

5454
<!-- schema generated by tfplugindocs -->
5555
## Schema
56-
57-
### Optional
58-
59-
- `id` (Number) Inventory id
60-
- `name` (String) Name of the inventory
61-
- `organization_name` (String) The name for the organization to which the inventory belongs
62-
63-
### Read-Only
64-
65-
- `description` (String) Description of the inventory
66-
- `named_url` (String) The Named Url of the inventory
67-
- `organization` (Number) Identifier for the organization to which the inventory belongs
68-
- `url` (String) Url of the inventory
69-
- `variables` (String) Variables of the inventory. Will be either JSON or YAML string depending on how the variables were entered into AAP.
Lines changed: 14 additions & 213 deletions
Original file line numberDiff line numberDiff line change
@@ -1,230 +1,31 @@
11
package provider
22

33
import (
4-
"context"
5-
"encoding/json"
6-
"fmt"
7-
"path"
8-
9-
"github.com/ansible/terraform-provider-aap/internal/provider/customtypes"
10-
"github.com/hashicorp/terraform-plugin-framework-validators/datasourcevalidator"
114
"github.com/hashicorp/terraform-plugin-framework/datasource"
12-
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
13-
"github.com/hashicorp/terraform-plugin-framework/diag"
14-
tfpath "github.com/hashicorp/terraform-plugin-framework/path"
15-
"github.com/hashicorp/terraform-plugin-framework/types"
165
)
176

18-
// inventoryDataSourceModel maps the data source schema data.
7+
// Inventory AAP API model
8+
type InventoryAPIModel struct {
9+
BaseDetailAPIModelWithOrg
10+
}
11+
12+
// InventoryDataSourceModel maps the data source schema data.
1913
type InventoryDataSourceModel struct {
20-
Id types.Int64 `tfsdk:"id"`
21-
Organization types.Int64 `tfsdk:"organization"`
22-
OrganizationName types.String `tfsdk:"organization_name"`
23-
Url types.String `tfsdk:"url"`
24-
NamedUrl types.String `tfsdk:"named_url"`
25-
Name types.String `tfsdk:"name"`
26-
Description types.String `tfsdk:"description"`
27-
Variables customtypes.AAPCustomStringValue `tfsdk:"variables"`
14+
BaseDetailDataSourceModelWithOrg
2815
}
2916

3017
// InventoryDataSource is the data source implementation.
3118
type InventoryDataSource struct {
32-
client ProviderHTTPClient
19+
BaseDataSourceWithOrg
3320
}
3421

35-
// Ensure the implementation satisfies the expected interfaces.
36-
var (
37-
_ datasource.DataSource = &InventoryDataSource{}
38-
_ datasource.DataSourceWithConfigure = &InventoryDataSource{}
39-
_ datasource.DataSourceWithConfigValidators = &InventoryDataSource{}
40-
_ datasource.DataSourceWithValidateConfig = &InventoryDataSource{}
41-
)
42-
4322
// NewInventoryDataSource is a helper function to simplify the provider implementation.
4423
func NewInventoryDataSource() datasource.DataSource {
45-
return &InventoryDataSource{}
46-
}
47-
48-
// Metadata returns the data source type name.
49-
func (d *InventoryDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
50-
resp.TypeName = req.ProviderTypeName + "_inventory"
51-
}
52-
53-
// Schema defines the schema for the data source.
54-
func (d *InventoryDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
55-
resp.Schema = schema.Schema{
56-
Attributes: map[string]schema.Attribute{
57-
"id": schema.Int64Attribute{
58-
Optional: true,
59-
Description: "Inventory id",
60-
},
61-
"organization": schema.Int64Attribute{
62-
Computed: true,
63-
Description: "Identifier for the organization to which the inventory belongs",
64-
},
65-
"organization_name": schema.StringAttribute{
66-
Computed: true,
67-
Optional: true,
68-
Description: "The name for the organization to which the inventory belongs",
69-
},
70-
"url": schema.StringAttribute{
71-
Computed: true,
72-
Description: "Url of the inventory",
73-
},
74-
"named_url": schema.StringAttribute{
75-
Computed: true,
76-
Description: "The Named Url of the inventory",
77-
},
78-
"name": schema.StringAttribute{
79-
Computed: true,
80-
Optional: true,
81-
Description: "Name of the inventory",
82-
},
83-
"description": schema.StringAttribute{
84-
Computed: true,
85-
Description: "Description of the inventory",
86-
},
87-
"variables": schema.StringAttribute{
88-
Computed: true,
89-
CustomType: customtypes.AAPCustomStringType{},
90-
Description: "Variables of the inventory. Will be either JSON or YAML string depending on how the variables were entered into AAP.",
91-
},
92-
},
93-
Description: `Get an existing inventory.`,
94-
}
95-
}
96-
97-
// Read refreshes the Terraform state with the latest data.
98-
func (d *InventoryDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
99-
var state InventoryDataSourceModel
100-
var diags diag.Diagnostics
101-
102-
// Read Terraform configuration data into the model
103-
resp.Diagnostics.Append(req.Config.Get(ctx, &state)...)
104-
if resp.Diagnostics.HasError() {
105-
return
106-
}
107-
108-
uri := path.Join(d.client.getApiEndpoint(), "inventories")
109-
resourceURL, err := ReturnAAPNamedURL(state.Id, state.Name, state.OrganizationName, uri)
110-
if err != nil {
111-
resp.Diagnostics.AddError("Minimal Data Not Supplied", "Expected either [id] or [name + organization_name] pair")
112-
return
113-
}
114-
115-
readResponseBody, diags := d.client.Get(resourceURL)
116-
resp.Diagnostics.Append(diags...)
117-
if resp.Diagnostics.HasError() {
118-
return
119-
}
120-
121-
diags = state.ParseHttpResponse(readResponseBody)
122-
resp.Diagnostics.Append(diags...)
123-
if resp.Diagnostics.HasError() {
124-
return
125-
}
126-
// Set state
127-
// Save updated data into Terraform state
128-
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
129-
if resp.Diagnostics.HasError() {
130-
return
131-
}
132-
}
133-
134-
// Configure adds the provider configured client to the data source.
135-
func (d *InventoryDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
136-
if req.ProviderData == nil {
137-
return
138-
}
139-
140-
client, ok := req.ProviderData.(*AAPClient)
141-
if !ok {
142-
resp.Diagnostics.AddError(
143-
"Unexpected Data Source Configure Type",
144-
fmt.Sprintf("Expected *AAPClient, got: %T. Please report this issue to the provider developers.", req.ProviderData),
145-
)
146-
147-
return
24+
return &InventoryDataSource{
25+
BaseDataSourceWithOrg: *NewBaseDataSourceWithOrg(nil, StringDescriptions{
26+
MetadataEntitySlug: "inventory",
27+
DescriptiveEntityName: "Inventory",
28+
ApiEntitySlug: "inventories",
29+
}),
14830
}
149-
150-
d.client = client
151-
}
152-
153-
func (d *InventoryDataSource) ConfigValidators(_ context.Context) []datasource.ConfigValidator {
154-
// You have at least an id or a name + organization_name pair
155-
return []datasource.ConfigValidator{
156-
datasourcevalidator.Any(
157-
datasourcevalidator.AtLeastOneOf(
158-
tfpath.MatchRoot("id")),
159-
datasourcevalidator.RequiredTogether(
160-
tfpath.MatchRoot("name"),
161-
tfpath.MatchRoot("organization_name")),
162-
),
163-
}
164-
}
165-
166-
func (d *InventoryDataSource) ValidateConfig(ctx context.Context, req datasource.ValidateConfigRequest, resp *datasource.ValidateConfigResponse) {
167-
var data InventoryDataSourceModel
168-
169-
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
170-
171-
if resp.Diagnostics.HasError() {
172-
return
173-
}
174-
175-
if IsValueProvided(data.Id) {
176-
return
177-
}
178-
179-
if IsValueProvided(data.Name) && IsValueProvided(data.OrganizationName) {
180-
return
181-
}
182-
183-
if !IsValueProvided(data.Id) && !IsValueProvided(data.Name) {
184-
resp.Diagnostics.AddAttributeWarning(
185-
tfpath.Root("id"),
186-
"Missing Attribute Configuration",
187-
"Expected either [id] or [name + organization_name] pair",
188-
)
189-
}
190-
191-
if IsValueProvided(data.Name) && !IsValueProvided(data.OrganizationName) {
192-
resp.Diagnostics.AddAttributeWarning(
193-
tfpath.Root("organization_name"),
194-
"Missing Attribute Configuration",
195-
"Expected organization_name to be configured with name.",
196-
)
197-
}
198-
199-
if !IsValueProvided(data.Name) && IsValueProvided(data.OrganizationName) {
200-
resp.Diagnostics.AddAttributeWarning(
201-
tfpath.Root("name"),
202-
"Missing Attribute Configuration",
203-
"Expected name to be configured with organization_name.",
204-
)
205-
}
206-
}
207-
208-
func (dm *InventoryDataSourceModel) ParseHttpResponse(body []byte) diag.Diagnostics {
209-
var diags diag.Diagnostics
210-
211-
// Unmarshal the JSON response
212-
var apiInventory InventoryAPIModel
213-
err := json.Unmarshal(body, &apiInventory)
214-
if err != nil {
215-
diags.AddError("Error parsing JSON response from AAP", err.Error())
216-
return diags
217-
}
218-
219-
// Map response to the inventory datesource schema
220-
dm.Id = types.Int64Value(apiInventory.Id)
221-
dm.Organization = types.Int64Value(apiInventory.Organization)
222-
dm.OrganizationName = types.StringValue(apiInventory.SummaryFields.Organization.Name)
223-
dm.Url = types.StringValue(apiInventory.Url)
224-
dm.NamedUrl = types.StringValue(apiInventory.Related.NamedUrl)
225-
dm.Name = ParseStringValue(apiInventory.Name)
226-
dm.Description = ParseStringValue(apiInventory.Description)
227-
dm.Variables = ParseAAPCustomStringValue(apiInventory.Variables)
228-
229-
return diags
23031
}

internal/provider/inventory_data_source_test.go

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,18 @@ func TestInventoryDataSourceParseHttpResponse(t *testing.T) {
5555
name: "missing values",
5656
input: []byte(`{"id":1,"organization":2,"url":"/inventories/1/"}`),
5757
expected: InventoryDataSourceModel{
58-
Id: types.Int64Value(1),
59-
Organization: types.Int64Value(2),
60-
OrganizationName: types.StringValue(""),
61-
Url: types.StringValue("/inventories/1/"),
62-
NamedUrl: types.StringValue(""),
63-
Name: types.StringNull(),
64-
Description: types.StringNull(),
65-
Variables: customtypes.NewAAPCustomStringNull(),
58+
BaseDetailDataSourceModelWithOrg: BaseDetailDataSourceModelWithOrg{
59+
BaseDetailDataSourceModel: BaseDetailDataSourceModel{
60+
Id: types.Int64Value(1),
61+
Name: types.StringNull(),
62+
Description: types.StringNull(),
63+
Variables: customtypes.NewAAPCustomStringNull(),
64+
URL: types.StringValue("/inventories/1/"),
65+
NamedUrl: types.StringNull(),
66+
},
67+
Organization: types.Int64Value(2),
68+
OrganizationName: types.StringNull(),
69+
},
6670
},
6771
errors: diag.Diagnostics{},
6872
},
@@ -72,14 +76,18 @@ func TestInventoryDataSourceParseHttpResponse(t *testing.T) {
7276
`{"id":1,"organization":2,"url":"/inventories/1/","name":"my inventory","description":"My Test Inventory","variables":"{\"foo\":\"bar\"}"}`,
7377
),
7478
expected: InventoryDataSourceModel{
75-
Id: types.Int64Value(1),
76-
Organization: types.Int64Value(2),
77-
OrganizationName: types.StringValue(""),
78-
Url: types.StringValue("/inventories/1/"),
79-
NamedUrl: types.StringValue(""),
80-
Name: types.StringValue("my inventory"),
81-
Description: types.StringValue("My Test Inventory"),
82-
Variables: customtypes.NewAAPCustomStringValue("{\"foo\":\"bar\"}"),
79+
BaseDetailDataSourceModelWithOrg: BaseDetailDataSourceModelWithOrg{
80+
BaseDetailDataSourceModel: BaseDetailDataSourceModel{
81+
Id: types.Int64Value(1),
82+
Name: types.StringValue("my inventory"),
83+
Description: types.StringValue("My Test Inventory"),
84+
URL: types.StringValue("/inventories/1/"),
85+
NamedUrl: types.StringNull(),
86+
Variables: customtypes.NewAAPCustomStringValue("{\"foo\":\"bar\"}"),
87+
},
88+
Organization: types.Int64Value(2),
89+
OrganizationName: types.StringNull(),
90+
},
8391
},
8492
errors: diag.Diagnostics{},
8593
},

0 commit comments

Comments
 (0)