Skip to content

Commit

Permalink
Merge pull request #112 from NamrathaG/feature/path_query_string
Browse files Browse the repository at this point in the history
added path_query_string parameter
  • Loading branch information
DRuggeri authored Mar 27, 2021
2 parents d071f3d + b6a6262 commit 5a4c17d
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 4 deletions.
1 change: 1 addition & 0 deletions docs/data-sources/object.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ description: |-
- **id** (String, Optional) The ID of this resource.
- **id_attribute** (String, Optional) Defaults to `id_attribute` set on the provider. Allows per-resource override of `id_attribute` (see `id_attribute` provider config documentation)
- **query_string** (String, Optional) An optional query string to send when performing the search.
- **read_query_string** (String, Optional) Defaults to `query_string` set on data source. This key allows setting a different or empty query string for reading the object.
- **results_key** (String, Optional) When issuing a GET to the path, this JSON key is used to locate the results array. The format is 'field/field/field'. Example: 'results/values'. If omitted, it is assumed the results coming back are already an array and are to be used exactly as-is.

### Read-only
Expand Down
2 changes: 2 additions & 0 deletions docs/resources/object.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ description: |-
- **read_search** (Map of String, Optional) Custom search for `read_path`. This map will take `search_key`, `search_value`, `results_key` and `query_string` (see datasource config documentation)
- **update_method** (String, Optional) Defaults to `update_method` set on the provider. Allows per-resource override of `update_method` (see `update_method` provider config documentation)
- **update_path** (String, Optional) Defaults to `path/{id}`. The API path that represents where to UPDATE (PUT) objects of this type on the API server. The string `{id}` will be replaced with the terraform ID of the object.
- **query_string** (String, Optional): Query string to be included in path.


### Read-only

Expand Down
52 changes: 48 additions & 4 deletions restapi/api_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type apiObjectOpts struct {
destroy_method string
delete_path string
search_path string
query_string string
debug bool
read_search map[string]string
id string
Expand All @@ -41,6 +42,7 @@ type api_object struct {
destroy_method string
delete_path string
search_path string
query_string string
debug bool
read_search map[string]string
id string
Expand Down Expand Up @@ -107,6 +109,7 @@ func NewAPIObject(i_client *api_client, opts *apiObjectOpts) (*api_object, error
destroy_method: opts.destroy_method,
delete_path: opts.delete_path,
search_path: opts.search_path,
query_string: opts.query_string,
debug: opts.debug,
read_search: opts.read_search,
id: opts.id,
Expand Down Expand Up @@ -158,6 +161,7 @@ func (obj *api_object) toString() string {
buffer.WriteString(fmt.Sprintf("post_path: %s\n", obj.post_path))
buffer.WriteString(fmt.Sprintf("put_path: %s\n", obj.put_path))
buffer.WriteString(fmt.Sprintf("delete_path: %s\n", obj.delete_path))
buffer.WriteString(fmt.Sprintf("query_string: %s\n", obj.query_string))
buffer.WriteString(fmt.Sprintf("create_method: %s\n", obj.create_method))
buffer.WriteString(fmt.Sprintf("read_method: %s\n", obj.read_method))
buffer.WriteString(fmt.Sprintf("update_method: %s\n", obj.update_method))
Expand Down Expand Up @@ -230,7 +234,16 @@ func (obj *api_object) create_object() error {
}

b, _ := json.Marshal(obj.data)
res_str, err := obj.api_client.send_request(obj.create_method, strings.Replace(obj.post_path, "{id}", obj.id, -1), string(b))

post_path := obj.post_path
if "" != obj.query_string {
if obj.debug {
log.Printf("api_object.go: Adding query string '%s'", obj.query_string)
}
post_path = fmt.Sprintf("%s?%s", obj.post_path, obj.query_string)
}

res_str, err := obj.api_client.send_request(obj.create_method, strings.Replace(post_path, "{id}", obj.id, -1), string(b))
if err != nil {
return err
}
Expand Down Expand Up @@ -262,7 +275,15 @@ func (obj *api_object) read_object() error {
return errors.New("Cannot read an object unless the ID has been set.")
}

res_str, err := obj.api_client.send_request(obj.read_method, strings.Replace(obj.get_path, "{id}", obj.id, -1), "")
get_path := obj.get_path
if "" != obj.query_string {
if obj.debug {
log.Printf("api_object.go: Adding query string '%s'", obj.query_string)
}
get_path = fmt.Sprintf("%s?%s", obj.get_path, obj.query_string)
}

res_str, err := obj.api_client.send_request(obj.read_method, strings.Replace(get_path, "{id}", obj.id, -1), "")
if err != nil {
if strings.Contains(err.Error(), "Unexpected response code '404'") {
log.Printf("api_object.go: 404 error while refreshing state for '%s' at path '%s'. Removing from state.", obj.id, obj.get_path)
Expand All @@ -280,6 +301,12 @@ func (obj *api_object) read_object() error {
obj.search_path = strings.Replace(obj.get_path, "{id}", obj.id, -1)

query_string := obj.read_search["query_string"]
if "" != obj.query_string {
if obj.debug {
log.Printf("api_object.go: Adding query string '%s'", obj.query_string)
}
query_string = fmt.Sprintf("%s&%s", obj.read_search["query_string"], obj.query_string)
}
results_key := obj.read_search["results_key"]
obj_found, err := obj.find_object(query_string, search_key, search_value, results_key)
if err != nil {
Expand All @@ -300,7 +327,16 @@ func (obj *api_object) update_object() error {
}

b, _ := json.Marshal(obj.data)
res_str, err := obj.api_client.send_request(obj.update_method, strings.Replace(obj.put_path, "{id}", obj.id, -1), string(b))

put_path := obj.put_path
if "" != obj.query_string {
if obj.debug {
log.Printf("api_object.go: Adding query string '%s'", obj.query_string)
}
put_path = fmt.Sprintf("%s?%s", obj.put_path, obj.query_string)
}

res_str, err := obj.api_client.send_request(obj.update_method, strings.Replace(put_path, "{id}", obj.id, -1), string(b))
if err != nil {
return err
}
Expand All @@ -325,7 +361,15 @@ func (obj *api_object) delete_object() error {
return nil
}

_, err := obj.api_client.send_request(obj.destroy_method, strings.Replace(obj.delete_path, "{id}", obj.id, -1), "")
delete_path := obj.delete_path
if "" != obj.query_string {
if obj.debug {
log.Printf("api_object.go: Adding query string '%s'", obj.query_string)
}
delete_path = fmt.Sprintf("%s?%s", obj.delete_path, obj.query_string)
}

_, err := obj.api_client.send_request(obj.destroy_method, strings.Replace(delete_path, "{id}", obj.id, -1), "")
if err != nil {
return err
}
Expand Down
15 changes: 15 additions & 0 deletions restapi/datasource_api_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ func dataSourceRestApi() *schema.Resource {
Description: "An optional query string to send when performing the search.",
Optional: true,
},
"read_query_string": &schema.Schema{
Type: schema.TypeString,
/* Setting to "not-set" helps differentiate between the cases where
read_query_string is explicitly set to zero-value for string ("") and
when read_query_string is not set at all in the configuration. */
Default: "not-set",
Description: "Defaults to `query_string` set on data source. This key allows setting a different or empty query string for reading the object.",
Optional: true,
},
"search_key": &schema.Schema{
Type: schema.TypeString,
Description: "When reading search results from the API, this key is used to identify the specific record to read. This should be a unique record such as 'name'. Similar to results_key, the value may be in the format of 'field/field/field' to search for data deeper in the returned object.",
Expand Down Expand Up @@ -76,6 +85,11 @@ func dataSourceRestApiRead(d *schema.ResourceData, meta interface{}) error {
log.Printf("datasource_api_object.go: Data routine called.")
}

read_query_string := d.Get("read_query_string").(string)
if read_query_string == "not-set" {
read_query_string = query_string
}

search_key := d.Get("search_key").(string)
search_value := d.Get("search_value").(string)
results_key := d.Get("results_key").(string)
Expand All @@ -89,6 +103,7 @@ func dataSourceRestApiRead(d *schema.ResourceData, meta interface{}) error {
path: path,
search_path: search_path,
debug: debug,
query_string: read_query_string,
id_attribute: id_attribute,
}

Expand Down
8 changes: 8 additions & 0 deletions restapi/resource_api_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ func resourceRestApi() *schema.Resource {
Description: "Custom search for `read_path`. This map will take `search_key`, `search_value`, `results_key` and `query_string` (see datasource config documentation)",
Optional: true,
},
"query_string": &schema.Schema{
Type: schema.TypeString,
Description: "Query string to be included in the path",
Optional: true,
},
"api_data": &schema.Schema{
Type: schema.TypeMap,
Elem: &schema.Schema{Type: schema.TypeString},
Expand Down Expand Up @@ -336,6 +341,9 @@ func buildApiObjectOpts(d *schema.ResourceData) (*apiObjectOpts, error) {
if v, ok := d.GetOk("destroy_path"); ok {
opts.delete_path = v.(string)
}
if v, ok := d.GetOk("query_string"); ok {
opts.query_string = v.(string)
}

read_search := expandReadSearch(d.Get("read_search").(map[string]interface{}))
opts.read_search = read_search
Expand Down

0 comments on commit 5a4c17d

Please sign in to comment.