Skip to content

Commit

Permalink
added support for query parameters in datasource
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrei-Predoiu committed Sep 27, 2022
1 parent 4ad494d commit 7512055
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 57 deletions.
8 changes: 5 additions & 3 deletions examples/providers.tf
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,17 @@ data "servicenow-data_table_row" "LasseG" {

data "servicenow-data_table_row" "AndreiP" {
table_id = "sys_user"
sys_id = "254400dbdb0bc34032fe9ea9db96190b"
row_data = {
"email" : "[email protected]"
}
}

resource "servicenow-data_table_row" "eng-services-vault" {
table_id = "x_beas_team_engi_0_lasse"
row_data = {
"team": "engineering-services",
"team": "engineering-services2",
"group_id_reader": "cd699222-ce5b-47ba-8d20-da254757c45c"
"group_id_admin": "a8d94edc-8f08-4db7-a4c1-8e2a00d55795"
"approvers": "${data.servicenow-data_table_row.LasseG.sys_id},${data.servicenow-data_table_row.AndreiP.sys_id}"
"approvers": "${data.servicenow-data_table_row.AndreiP.sys_id},${data.servicenow-data_table_row.LasseG.sys_id}"
}
}
55 changes: 44 additions & 11 deletions internal/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,25 @@ func NewClient(url, user, pass string) *Client {
}
}

func (client *Client) GetTableRow(tableName, sysID string) (*models.ParsedResult, error) {
rowPath := fmt.Sprintf("/table/%s/%s", tableName, sysID)
func (client *Client) GetTableRow(tableID string, params map[string]interface{}) (*models.ParsedResult, error) {
if params == nil || len(params) == 0 {
return nil, fmt.Errorf("sys_id and params cannot be both empty")
}
query := "?"
for k, v := range params {
query = fmt.Sprintf("%s&%s=%s", query, k, v)
}
rowPath := fmt.Sprintf("/table/%s%s", tableID, query)

rawData, err := client.sendRequest(http.MethodGet, rowPath, nil, 200)
if err != nil {
return nil, err
}
return parseRawData(rawData)
return parseRawListData(rawData)
}

func (client *Client) InsertTableRow(tableName string, tableData interface{}) (*models.ParsedResult, error) {
rowPath := fmt.Sprintf("/table/%s", tableName)
func (client *Client) InsertTableRow(tableID string, tableData interface{}) (*models.ParsedResult, error) {
rowPath := fmt.Sprintf("/table/%s", tableID)
rawData, err := client.sendRequest(http.MethodPost, rowPath, tableData, 201)
if err != nil {
return nil, err
Expand Down Expand Up @@ -101,8 +109,8 @@ func (client *Client) sendRequest(method, path string, payload interface{}, expe
return &body, nil
}

func (client *Client) UpdateTableRow(tableName, sysID string, payload interface{}) (*models.ParsedResult, error) {
rowPath := fmt.Sprintf("/table/%s/%s", tableName, sysID)
func (client *Client) UpdateTableRow(tableID, sysID string, payload interface{}) (*models.ParsedResult, error) {
rowPath := fmt.Sprintf("/table/%s/%s", tableID, sysID)
rawData, err := client.sendRequest(http.MethodPut, rowPath, payload, 200)
if err != nil {
return nil, err
Expand All @@ -112,15 +120,40 @@ func (client *Client) UpdateTableRow(tableName, sysID string, payload interface{

func parseRawData(rawData *[]byte) (*models.ParsedResult, error) {
var rawResult models.RawResult
var parsedResult = models.ParsedResult{}
err := json.Unmarshal(*rawData, &rawResult)
if err != nil {
return nil, err
}
rowData := make(map[string]string, len(rawResult.Result)-7)
sysData := make(map[string]string, 7)

for k, message := range rawResult.Result {
result, err := rawMapParse(rawResult.Result)
if err != nil {
return nil, err
}
return result, nil
}

func parseRawListData(rawData *[]byte) (*models.ParsedResult, error) {
var rawResult models.RawResultList
err := json.Unmarshal(*rawData, &rawResult)
if err != nil {
return nil, err
}
if len(rawResult.Result) != 1 {
return nil, fmt.Errorf("received more than one row as result, make sure your query returns a single item")
}

result, err := rawMapParse(rawResult.Result[0])
if err != nil {
return nil, err
}
return result, nil
}

func rawMapParse(rawResult map[string]json.RawMessage) (*models.ParsedResult, error) {
var parsedResult = models.ParsedResult{}
rowData := make(map[string]string, len(rawResult)-7)
sysData := make(map[string]string, 7)
for k, message := range rawResult {
rv, err := extractRowValue(message)
if err != nil {
return nil, err
Expand Down
53 changes: 19 additions & 34 deletions internal/datasource/data_source_database_row.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import (
"fmt"
"github.com/BESTSELLER/terraform-provider-servicenow-data/internal/client"
"github.com/BESTSELLER/terraform-provider-servicenow-data/internal/models"
"github.com/BESTSELLER/terraform-provider-servicenow-data/internal/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"strings"
)

func TableRowDatasource() *schema.Resource {
Expand All @@ -16,6 +16,7 @@ func TableRowDatasource() *schema.Resource {
"sys_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"row_data": {
Description: "Columns",
Expand All @@ -34,55 +35,39 @@ func TableRowDatasource() *schema.Resource {

func tableRowRead(_ context.Context, data *schema.ResourceData, m interface{}) diag.Diagnostics {
c := m.(*client.Client)
var tableID, sysID string
var err error
// Warning or errors can be collected in a slice type
var diags diag.Diagnostics

tableID = data.Get("table_id").(string)
if tableID == "" {
var payload map[string]interface{}
tableID, ok := data.GetOk("table_id")
if !ok {
diags = append(diags, diag.Diagnostic{
Severity: diag.Error,
Summary: "tableID is mandatory",
})
return diags
}
sysID = data.Get("sys_id").(string)
if sysID == "" {
return append(diags, diag.Diagnostic{
Severity: diag.Error,
Summary: "sys_id is mandatory",
})
sysID, ok := data.GetOk("sys_id")
if !ok {
payload = data.Get("row_data").(map[string]interface{})
if payload == nil || len(payload) == 0 {
return append(diags, diag.Diagnostic{
Severity: diag.Error,
Summary: "sys_id or row_data is mandatory",
})
}
} else {
payload = map[string]interface{}{"sys_id": sysID}
}

rowData, err := c.GetTableRow(tableID, sysID)
rowData, err := c.GetTableRow(tableID.(string), payload)
if err != nil {
return diag.FromErr(err)
}

diags = append(diags, ParsedResultToSchema(data, rowData)...)
diags = append(diags, resource.ParsedResultToSchema(data, rowData)...)

data.SetId(fmt.Sprintf("%s/%s", tableID, sysID))
data.SetId(fmt.Sprintf("%s/%s", tableID, rowData.SysData["sys_id"]))

return diags
}

func ExtractIDs(ID string) (tableID, sysID string, err error) {
ids := strings.Split(ID, `/`)
if len(ids) != 2 {
return "", "", fmt.Errorf("faulty id!%s", ID)
}
return ids[0], ids[1], nil
}

func ParsedResultToSchema(d *schema.ResourceData, result *models.ParsedResult) diag.Diagnostics {
for k, v := range result.SysData {
if err := d.Set(k, v); err != nil {
return diag.FromErr(err)
}
}
if err := d.Set("row_data", result.RowData); err != nil {
return diag.FromErr(err)
}
return nil
}
4 changes: 4 additions & 0 deletions internal/models/sn_row.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ type RawResult struct {
Result map[string]json.RawMessage `json:"result"`
}

type RawResultList struct {
Result []map[string]json.RawMessage `json:"result"`
}

type ParsedResult struct {
SysData map[string]string `json:"sys_data"`
RowData map[string]string `json:"row_data"`
Expand Down
33 changes: 26 additions & 7 deletions internal/resource/resource_database_row.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"fmt"
"github.com/BESTSELLER/terraform-provider-servicenow-data/internal/client"
"github.com/BESTSELLER/terraform-provider-servicenow-data/internal/datasource"
"github.com/BESTSELLER/terraform-provider-servicenow-data/internal/models"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
Expand Down Expand Up @@ -65,7 +64,7 @@ func tableRowCreate(_ context.Context, d *schema.ResourceData, m interface{}) di
return diag.FromErr(err)
}

diags = append(diags, datasource.ParsedResultToSchema(d, insertResult)...)
diags = append(diags, ParsedResultToSchema(d, insertResult)...)
sysID, ok := d.GetOk("sys_id")
if !ok {
diags = append(diags, diag.Diagnostic{
Expand All @@ -87,17 +86,17 @@ func tableRowRead(_ context.Context, data *schema.ResourceData, m interface{}) d
var err error
// Warning or errors can be collected in a slice type
var diags diag.Diagnostics
tableID, sysID, err = datasource.ExtractIDs(data.Id())
tableID, sysID, err = ExtractIDs(data.Id())
if err != nil {
return append(diags, diag.FromErr(err)...)
}

rowData, err := c.GetTableRow(tableID, sysID)
rowData, err := c.GetTableRow(tableID, map[string]interface{}{"sys_id": sysID})
if err != nil {
return diag.FromErr(err)
}

diags = append(diags, datasource.ParsedResultToSchema(data, rowData)...)
diags = append(diags, ParsedResultToSchema(data, rowData)...)

data.SetId(fmt.Sprintf("%s/%s", tableID, sysID))

Expand Down Expand Up @@ -125,7 +124,7 @@ func tableRowUpdate(_ context.Context, d *schema.ResourceData, m interface{}) di
return diags
}

tableID, sysID, err := datasource.ExtractIDs(d.Id())
tableID, sysID, err := ExtractIDs(d.Id())
if err != nil {
return append(diags, diag.FromErr(err)...)
}
Expand All @@ -136,7 +135,7 @@ func tableRowUpdate(_ context.Context, d *schema.ResourceData, m interface{}) di
return diag.FromErr(err)
}

diags = append(diags, datasource.ParsedResultToSchema(d, rowData)...)
diags = append(diags, ParsedResultToSchema(d, rowData)...)

return diags
}
Expand All @@ -156,3 +155,23 @@ func tableRowDelete(_ context.Context, d *schema.ResourceData, m interface{}) di
}
return diags
}

func ExtractIDs(ID string) (tableID, sysID string, err error) {
ids := strings.Split(ID, `/`)
if len(ids) != 2 {
return "", "", fmt.Errorf("faulty id!%s", ID)
}
return ids[0], ids[1], nil
}

func ParsedResultToSchema(d *schema.ResourceData, result *models.ParsedResult) diag.Diagnostics {
for k, v := range result.SysData {
if err := d.Set(k, v); err != nil {
return diag.FromErr(err)
}
}
if err := d.Set("row_data", result.RowData); err != nil {
return diag.FromErr(err)
}
return nil
}
3 changes: 1 addition & 2 deletions resource_database_row_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package main
import (
"fmt"
"github.com/BESTSELLER/terraform-provider-servicenow-data/internal/client"
"github.com/BESTSELLER/terraform-provider-servicenow-data/internal/datasource"
resource2 "github.com/BESTSELLER/terraform-provider-servicenow-data/internal/resource"
"testing"

Expand Down Expand Up @@ -38,7 +37,7 @@ func testAccCheckRowDestroy(s *terraform.State) error {
continue
}

tableID, rowID, err := datasource.ExtractIDs(rs.Primary.ID)
tableID, rowID, err := resource2.ExtractIDs(rs.Primary.ID)

if err != nil {
return err
Expand Down

0 comments on commit 7512055

Please sign in to comment.