Skip to content

Commit 99781ac

Browse files
authored
Merge pull request #136 from patientsknowbest/feature/PHR-15044-aidbox-search-resource
Support Aidbox search resource PHR-15044
2 parents 158c90c + 9c3a3f7 commit 99781ac

File tree

7 files changed

+308
-1
lines changed

7 files changed

+308
-1
lines changed

aidbox/search.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package aidbox
2+
3+
import (
4+
"context"
5+
)
6+
7+
// Aidbox Search resource: https://docs.aidbox.app/api/rest-api/aidbox-search#search-resource
8+
type Search struct {
9+
ResourceBase
10+
Name string `json:"name"`
11+
Module string `json:"module,omitempty"`
12+
Resource Reference `json:"resource"`
13+
Where string `json:"where"`
14+
}
15+
16+
func (*Search) GetResourcePath() string {
17+
return "Search"
18+
}
19+
20+
func (apiClient *ApiClient) CreateSearch(ctx context.Context, searchParameter *Search) (*Search, error) {
21+
response := &Search{}
22+
return response, apiClient.createResource(ctx, searchParameter, response)
23+
}
24+
25+
func (apiClient *ApiClient) GetSearch(ctx context.Context, id string) (*Search, error) {
26+
response := &Search{}
27+
return response, apiClient.getResource(ctx, id, response)
28+
}
29+
30+
func (apiClient *ApiClient) UpdateSearch(ctx context.Context, q *Search) (*Search, error) {
31+
response := &Search{}
32+
return response, apiClient.updateResource(ctx, q, response)
33+
}
34+
35+
func (apiClient *ApiClient) DeleteSearch(ctx context.Context, id string) error {
36+
return apiClient.deleteResource(ctx, id, &Search{})
37+
}

docs/resources/fhir_search_parameter.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,20 @@ description: |-
1010

1111
FHIR R4 SearchParameter https://hl7.org/fhir/R4/searchparameter.html
1212

13-
13+
## Example Usage
14+
15+
```terraform
16+
resource "aidbox_fhir_search_parameter" "example_extension" {
17+
name = "custom-date"
18+
type = "date"
19+
base = ["Appointment"]
20+
code = "custom-date"
21+
expression = "Appointment.meta.extension.where(url = 'https://fhir.yourcompany.com/structuredefinition/custom-date').valueDateTime"
22+
description = "Search appointments by custom date expression"
23+
url = "https://fhir.yourcompany.com/searchparameter/custom-date"
24+
status = "active"
25+
}
26+
```
1427

1528
<!-- schema generated by tfplugindocs -->
1629
## Schema

docs/resources/search.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "aidbox_search Resource - terraform-provider-aidbox"
4+
subcategory: ""
5+
description: |-
6+
Search https://docs.aidbox.app/api/rest-api/aidbox-search#search-resource
7+
---
8+
9+
# aidbox_search (Resource)
10+
11+
Search https://docs.aidbox.app/api/rest-api/aidbox-search#search-resource
12+
13+
## Example Usage
14+
15+
```terraform
16+
resource "aidbox_search" "example_extension" {
17+
name = "custom-date"
18+
module = "fhir-4.0.1"
19+
reference {
20+
resource_id = "Appointment"
21+
resource_type = "Entity"
22+
}
23+
where = "date = '01 Jan 2014"
24+
}
25+
```
26+
27+
<!-- schema generated by tfplugindocs -->
28+
## Schema
29+
30+
### Required
31+
32+
- `name` (String) Name of search, used in search query string
33+
- `reference` (Block List, Min: 1, Max: 1) Reference to resource this search param attached to (see [below for nested schema](#nestedblock--reference))
34+
- `where` (String) SQL of search
35+
36+
### Optional
37+
38+
- `module` (String) Module name
39+
40+
### Read-Only
41+
42+
- `id` (String) The ID of this resource.
43+
44+
<a id="nestedblock--reference"></a>
45+
### Nested Schema for `reference`
46+
47+
Required:
48+
49+
- `resource_id` (String) The ID of the referenced resource
50+
- `resource_type` (String) The type of the referenced resource
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
resource "aidbox_search" "example_extension" {
2+
name = "custom-date"
3+
module = "fhir-4.0.1"
4+
reference {
5+
resource_id = "Appointment"
6+
resource_type = "Entity"
7+
}
8+
where = "date = '01 Jan 2014"
9+
}

internal/provider/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ func New(apiClient *aidbox.ApiClient) func() *schema.Provider {
5555
"aidbox_access_policy": resourceAccessPolicy(),
5656
"aidbox_client": resourceClient(),
5757
"aidbox_db_migration": resourceDbMigration(),
58+
"aidbox_search": resourceSearch(),
5859
"aidbox_search_parameter": resourceSearchParameter(),
5960
"aidbox_fhir_search_parameter": resourceSearchParameterV2(),
6061
"aidbox_aidbox_subscription_topic": resourceAidboxSubscriptionTopic(),
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
package provider
2+
3+
import (
4+
"context"
5+
6+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
8+
"github.com/patientsknowbest/terraform-provider-aidbox/aidbox"
9+
)
10+
11+
func resourceSearch() *schema.Resource {
12+
return &schema.Resource{
13+
Description: "Search https://docs.aidbox.app/api/rest-api/aidbox-search#search-resource",
14+
CreateContext: resourceSearchCreate,
15+
ReadContext: resourceSearchRead,
16+
UpdateContext: resourceSearchUpdate,
17+
DeleteContext: resourceSearchDelete,
18+
Importer: &schema.ResourceImporter{
19+
StateContext: resourceSearchImport,
20+
},
21+
Schema: resourceFullSchema(resourceSchemaSearch()),
22+
}
23+
}
24+
25+
func resourceSchemaSearch() map[string]*schema.Schema {
26+
return map[string]*schema.Schema{
27+
"name": {
28+
Description: "Name of search, used in search query string",
29+
Type: schema.TypeString,
30+
Required: true,
31+
},
32+
"module": {
33+
Description: "Module name",
34+
Type: schema.TypeString,
35+
Optional: true,
36+
},
37+
"where": {
38+
Description: "SQL of search",
39+
Type: schema.TypeString,
40+
Required: true,
41+
},
42+
"reference": {
43+
Description: "Reference to resource this search param attached to",
44+
// not a TypeMap because "using the Elem block to define specific keys for the map is currently not possible"
45+
Type: schema.TypeList,
46+
Required: true,
47+
MinItems: 1,
48+
MaxItems: 1,
49+
Elem: &schema.Resource{
50+
Schema: map[string]*schema.Schema{
51+
"resource_id": {
52+
Description: "The ID of the referenced resource",
53+
Type: schema.TypeString,
54+
Required: true,
55+
},
56+
"resource_type": {
57+
Description: "The type of the referenced resource",
58+
Type: schema.TypeString,
59+
Required: true,
60+
},
61+
},
62+
},
63+
},
64+
}
65+
}
66+
67+
func mapSearchFromData(data *schema.ResourceData) (*aidbox.Search, error) {
68+
res := &aidbox.Search{}
69+
res.Name = data.Get("name").(string)
70+
res.Module = data.Get("module").(string)
71+
res.Where = data.Get("where").(string)
72+
73+
// resource
74+
ref := data.Get("reference").([]interface{})[0].(map[string]interface{})
75+
r := aidbox.Reference{
76+
ResourceId: ref["resource_id"].(string),
77+
ResourceType: ref["resource_type"].(string),
78+
}
79+
res.Resource = r
80+
81+
res.ID = res.Resource.ResourceId + "." + res.Name
82+
83+
return res, nil
84+
}
85+
86+
func mapSearchToData(res *aidbox.Search, data *schema.ResourceData) {
87+
data.SetId(res.ID)
88+
data.Set("name", res.Name)
89+
data.Set("module", res.Module)
90+
data.Set("where", res.Where)
91+
92+
// resource
93+
var ref []interface{}
94+
r := map[string]string{
95+
"resource_id": res.Resource.ResourceId,
96+
"resource_type": res.Resource.ResourceType,
97+
}
98+
data.Set("reference", append(ref, r))
99+
}
100+
101+
func resourceSearchCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
102+
apiClient := meta.(*aidbox.ApiClient)
103+
q, err := mapSearchFromData(d)
104+
if err != nil {
105+
return diag.FromErr(err)
106+
}
107+
res, err := apiClient.CreateSearch(ctx, q)
108+
if err != nil {
109+
return diag.FromErr(err)
110+
}
111+
mapSearchToData(res, d)
112+
return nil
113+
}
114+
115+
func resourceSearchRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
116+
apiClient := meta.(*aidbox.ApiClient)
117+
res, err := apiClient.GetSearch(ctx, d.Id())
118+
if err != nil {
119+
if handleNotFoundError(err, d) {
120+
return nil
121+
}
122+
return diag.FromErr(err)
123+
}
124+
mapSearchToData(res, d)
125+
return nil
126+
}
127+
128+
func resourceSearchUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
129+
apiClient := meta.(*aidbox.ApiClient)
130+
q, err := mapSearchFromData(d)
131+
if err != nil {
132+
return diag.FromErr(err)
133+
}
134+
ac, err := apiClient.UpdateSearch(ctx, q)
135+
if err != nil {
136+
return diag.FromErr(err)
137+
}
138+
mapSearchToData(ac, d)
139+
return nil
140+
}
141+
142+
func resourceSearchDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
143+
apiClient := meta.(*aidbox.ApiClient)
144+
err := apiClient.DeleteSearch(ctx, d.Id())
145+
if err != nil {
146+
return diag.FromErr(err)
147+
}
148+
return nil
149+
}
150+
151+
func resourceSearchImport(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
152+
apiClient := meta.(*aidbox.ApiClient)
153+
res, err := apiClient.GetSearch(ctx, d.Id())
154+
if err != nil {
155+
return nil, err
156+
}
157+
mapSearchToData(res, d)
158+
return []*schema.ResourceData{d}, nil
159+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package provider
2+
3+
import (
4+
"testing"
5+
6+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
7+
)
8+
9+
func TestAccResourceSearch_happyPath(t *testing.T) {
10+
resource.Test(t, resource.TestCase{
11+
PreCheck: func() { requireSchemaMode(t) },
12+
ProviderFactories: testProviderFactories,
13+
Steps: []resource.TestStep{
14+
{
15+
Config: testAccResourceSearch_happyPath,
16+
Check: resource.ComposeTestCheckFunc(
17+
resource.TestCheckResourceAttr("aidbox_search.example_phone", "name", "phone-number"),
18+
resource.TestCheckResourceAttr("aidbox_search.example_phone", "module", "fhir-4.0.1"),
19+
resource.TestCheckResourceAttr("aidbox_search.example_phone", "reference.0.resource_id", "Patient"),
20+
resource.TestCheckResourceAttr("aidbox_search.example_phone", "reference.0.resource_type", "Entity"),
21+
resource.TestCheckResourceAttr("aidbox_search.example_phone", "where", "phone-number = 01125636365"),
22+
),
23+
},
24+
},
25+
})
26+
}
27+
28+
const testAccResourceSearch_happyPath = `
29+
resource "aidbox_search" "example_phone" {
30+
name = "phone-number"
31+
module = "fhir-4.0.1"
32+
reference {
33+
resource_id = "Patient"
34+
resource_type = "Entity"
35+
}
36+
where = "phone-number = 01125636365"
37+
}
38+
`

0 commit comments

Comments
 (0)