diff --git a/examples/providers.tf b/examples/providers.tf index f4fbdae..a54f699 100644 --- a/examples/providers.tf +++ b/examples/providers.tf @@ -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" : "andrei.predoiu@bestseller.com" + } } 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}" } } diff --git a/internal/client/client.go b/internal/client/client.go index 137eb64..d720c39 100644 --- a/internal/client/client.go +++ b/internal/client/client.go @@ -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 @@ -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 @@ -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 diff --git a/internal/datasource/data_source_database_row.go b/internal/datasource/data_source_database_row.go index 88df5c0..49346da 100644 --- a/internal/datasource/data_source_database_row.go +++ b/internal/datasource/data_source_database_row.go @@ -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 { @@ -16,6 +16,7 @@ func TableRowDatasource() *schema.Resource { "sys_id": { Type: schema.TypeString, Optional: true, + Computed: true, }, "row_data": { Description: "Columns", @@ -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 -} diff --git a/internal/models/sn_row.go b/internal/models/sn_row.go index f1dfb67..d580d75 100644 --- a/internal/models/sn_row.go +++ b/internal/models/sn_row.go @@ -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"` diff --git a/internal/resource/resource_database_row.go b/internal/resource/resource_database_row.go index 35ba846..e670089 100644 --- a/internal/resource/resource_database_row.go +++ b/internal/resource/resource_database_row.go @@ -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" @@ -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{ @@ -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)) @@ -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)...) } @@ -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 } @@ -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 +} diff --git a/resource_database_row_test.go b/resource_database_row_test.go index 3efab96..08af31f 100644 --- a/resource_database_row_test.go +++ b/resource_database_row_test.go @@ -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" @@ -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