Skip to content

Commit ac1baee

Browse files
committed
feat: add keyed sections and fields
1 parent ac9d006 commit ac1baee

File tree

2 files changed

+139
-67
lines changed

2 files changed

+139
-67
lines changed

onepassword/data_source_onepassword_item.go

Lines changed: 75 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,66 @@ import (
1313

1414
func dataSourceOnepasswordItem() *schema.Resource {
1515
exactlyOneOfUUIDAndTitle := []string{"uuid", "title"}
16+
fieldResource := &schema.Resource{
17+
Description: fieldDescription,
18+
Schema: map[string]*schema.Schema{
19+
"id": {
20+
Description: fieldIDDescription,
21+
Type: schema.TypeString,
22+
Computed: true,
23+
},
24+
"label": {
25+
Description: fieldLabelDescription,
26+
Type: schema.TypeString,
27+
Computed: true,
28+
},
29+
"purpose": {
30+
Description: fmt.Sprintf(enumDescription, fieldPurposeDescription, fieldPurposes),
31+
Type: schema.TypeString,
32+
Computed: true,
33+
},
34+
"type": {
35+
Description: fmt.Sprintf(enumDescription, fieldTypeDescription, fieldTypes),
36+
Type: schema.TypeString,
37+
Computed: true,
38+
},
39+
"value": {
40+
Description: fieldValueDescription,
41+
Type: schema.TypeString,
42+
Computed: true,
43+
Sensitive: true,
44+
},
45+
},
46+
}
47+
sectionResource := &schema.Resource{
48+
Description: sectionDescription,
49+
Schema: map[string]*schema.Schema{
50+
"id": {
51+
Description: sectionIDDescription,
52+
Type: schema.TypeString,
53+
Computed: true,
54+
},
55+
"label": {
56+
Description: sectionLabelDescription,
57+
Type: schema.TypeString,
58+
Computed: true,
59+
},
60+
"keyed_fields": {
61+
Description: sectionFieldsDescription,
62+
Type: schema.TypeMap,
63+
Computed: true,
64+
Elem: fieldResource,
65+
},
66+
"field": {
67+
Deprecated: "Use `keyed_fields` instead.", // bringing the conversation up
68+
Description: sectionFieldsDescription,
69+
Type: schema.TypeList,
70+
Computed: true,
71+
MinItems: 0,
72+
Elem: fieldResource,
73+
},
74+
},
75+
}
1676

1777
return &schema.Resource{
1878
Description: "Use this data source to get details of an item by its vault uuid and either the title or the uuid of the item.",
@@ -96,63 +156,19 @@ func dataSourceOnepasswordItem() *schema.Resource {
96156
Optional: true,
97157
Sensitive: true,
98158
},
159+
"keyed_sections": {
160+
Description: sectionsDescription,
161+
Type: schema.TypeMap,
162+
Computed: true,
163+
Elem: sectionResource,
164+
},
99165
"section": {
166+
Deprecated: "Use `keyed_sections` instead.", // bringing the conversation up
100167
Description: sectionsDescription,
101168
Type: schema.TypeList,
102169
Computed: true,
103170
MinItems: 0,
104-
Elem: &schema.Resource{
105-
Description: sectionDescription,
106-
Schema: map[string]*schema.Schema{
107-
"id": {
108-
Description: sectionIDDescription,
109-
Type: schema.TypeString,
110-
Computed: true,
111-
},
112-
"label": {
113-
Description: sectionLabelDescription,
114-
Type: schema.TypeString,
115-
Computed: true,
116-
},
117-
"field": {
118-
Description: sectionFieldsDescription,
119-
Type: schema.TypeList,
120-
Computed: true,
121-
MinItems: 0,
122-
Elem: &schema.Resource{
123-
Description: fieldDescription,
124-
Schema: map[string]*schema.Schema{
125-
"id": {
126-
Description: fieldIDDescription,
127-
Type: schema.TypeString,
128-
Computed: true,
129-
},
130-
"label": {
131-
Description: fieldLabelDescription,
132-
Type: schema.TypeString,
133-
Computed: true,
134-
},
135-
"purpose": {
136-
Description: fmt.Sprintf(enumDescription, fieldPurposeDescription, fieldPurposes),
137-
Type: schema.TypeString,
138-
Computed: true,
139-
},
140-
"type": {
141-
Description: fmt.Sprintf(enumDescription, fieldTypeDescription, fieldTypes),
142-
Type: schema.TypeString,
143-
Computed: true,
144-
},
145-
"value": {
146-
Description: fieldValueDescription,
147-
Type: schema.TypeString,
148-
Computed: true,
149-
Sensitive: true,
150-
},
151-
},
152-
},
153-
},
154-
},
155-
},
171+
Elem: sectionResource,
156172
},
157173
},
158174
}
@@ -181,13 +197,16 @@ func dataSourceOnepasswordItemRead(ctx context.Context, data *schema.ResourceDat
181197
data.Set("category", strings.ToLower(string(item.Category)))
182198

183199
dataSections := []interface{}{}
200+
dataKeyedSections := make(map[string]interface{}, len(item.Sections))
201+
184202
for _, s := range item.Sections {
185203
section := map[string]interface{}{}
186204

187205
section["id"] = s.ID
188206
section["label"] = s.Label
189207

190208
fields := []interface{}{}
209+
keyedFields := make(map[string]interface{}, len(item.Fields))
191210

192211
for _, f := range item.Fields {
193212
if f.Section != nil && f.Section.ID == s.ID {
@@ -199,14 +218,18 @@ func dataSourceOnepasswordItemRead(ctx context.Context, data *schema.ResourceDat
199218
dataField["value"] = f.Value
200219

201220
fields = append(fields, dataField)
221+
keyedFields[f.Label] = dataField
202222
}
203223
}
204224
section["field"] = fields
225+
section["keyed_fields"] = keyedFields
205226

206227
dataSections = append(dataSections, section)
228+
dataKeyedSections[s.Label] = section
207229
}
208230

209231
data.Set("section", dataSections)
232+
data.Set("keyed_sections", dataKeyedSections)
210233

211234
for _, f := range item.Fields {
212235
switch f.Purpose {

onepassword/data_source_onepassword_item_test.go

Lines changed: 64 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,31 @@ func compareItemToSource(t *testing.T, dataSourceData *schema.ResourceData, item
9595
}
9696
compareStringSlice(t, getTags(dataSourceData), item.Tags)
9797

98+
for _, section := range item.Sections {
99+
t.Errorf("Missing Implementation for %s", section.Label)
100+
//keyedSection := dataSourceData.Get(fmt.Sprintf("keyed_sections.%s", section.Label)).(map[string]interface{})
101+
//dataSourceData.GetRawState()
102+
//if keyedSection == nil {
103+
// t.Errorf("Expected keyed section %v to exist", section.Label)
104+
//}
105+
//if keyedSection["id"] != section.ID {
106+
// t.Errorf("Expected keyed section %v to have id %v got %v", section.Label, section.ID, keyedSection["id"])
107+
//}
108+
//
109+
//for _, field := range item.Fields {
110+
// if field.Section != nil && field.Section.ID == section.ID {
111+
// keyedField := dataSourceData.Get(fmt.Sprintf("keyed_sections.%s.keyed_fields.%s", section.Label, field.Label)).(map[string]interface{})
112+
//
113+
// if keyedField == nil {
114+
// t.Errorf("Expected keyed field %v to exist", field.Label)
115+
// }
116+
// if keyedField["id"] != field.ID {
117+
// t.Errorf("Expected keyed field %v to have id %v got %v", field.Label, field.ID, keyedField["id"])
118+
// }
119+
// }
120+
//}
121+
}
122+
98123
for _, f := range item.Fields {
99124
path := f.Label
100125
if f.Section != nil {
@@ -136,8 +161,10 @@ func generateDataSource(t *testing.T, item *onepassword.Item) *schema.ResourceDa
136161
}
137162

138163
func generateItem() *onepassword.Item {
164+
fields, sections := generateFields()
139165
item := onepassword.Item{}
140-
item.Fields = generateFields()
166+
item.Sections = sections
167+
item.Fields = fields
141168
item.ID = "79841a98-dd4a-4c34-8be5-32dca20a7328"
142169
item.Vault.ID = "df2e9643-45ad-4ff9-8b98-996f801afa75"
143170
item.Category = "USERNAME"
@@ -151,34 +178,56 @@ func generateItem() *onepassword.Item {
151178
return &item
152179
}
153180

154-
func generateFields() []*onepassword.ItemField {
181+
func generateFields() ([]*onepassword.ItemField, []*onepassword.ItemSection) {
182+
sections := []*onepassword.ItemSection{
183+
{
184+
ID: "r9d6nt77oacycnjhp3tm3ihjka",
185+
Label: "Section 1",
186+
//Label: "", // seems to be the default section name
187+
},
188+
{
189+
ID: "hbvbe4469kak5njjuthnhszcae",
190+
Label: "Section 2",
191+
},
192+
}
193+
194+
// TODO: this is confusing, based on the JSON payload, fields live inside of sections there is only
195+
// payload.details.sections and inside of that there is a payload.details.sections.fields
155196
fields := []*onepassword.ItemField{
156197
{
157-
Label: "username",
158-
Value: "test_user",
198+
Label: "username",
199+
Value: "test_user",
200+
Section: sections[0],
159201
},
160202
{
161-
Label: "password",
162-
Value: "test_password",
203+
Label: "password",
204+
Value: "test_password",
205+
Section: sections[0],
163206
},
164207
{
165-
Label: "hostname",
166-
Value: "test_host",
208+
Label: "hostname",
209+
Value: "test_host",
210+
Section: sections[0],
167211
},
168212
{
169-
Label: "database",
170-
Value: "test_database",
213+
Label: "database",
214+
Value: "test_database",
215+
Section: sections[0],
171216
},
172217
{
173-
Label: "port",
174-
Value: "test_port",
218+
Label: "port",
219+
Value: "test_port",
220+
Section: sections[0],
221+
//Section: nil, TODO: why is Section a pointer when there HAVE to be a section for the field?
175222
},
176223
{
177-
Label: "type",
178-
Value: "test_type",
224+
Label: "type",
225+
Value: "test_type",
226+
Section: sections[1],
179227
},
180228
}
181-
return fields
229+
230+
return fields, sections
182231
}
183232

184233
func compareStringSlice(t *testing.T, actual, expected []string) {

0 commit comments

Comments
 (0)