Skip to content

Commit

Permalink
Allow fields to be removed at a specific version (#3417) (#6193)
Browse files Browse the repository at this point in the history
The healthcare API has deprecated a field at beta and removed it from the GA
launch of the api. In order to support this without having to duplicate the
entire resource this change supports defining a single field multiple times
with a different configruation for each version. Specifically it allows a field
to exist as deprecated at one version but not at another.
This also introduces the removed_message field.

Signed-off-by: Modular Magician <[email protected]>
  • Loading branch information
modular-magician authored Apr 24, 2020
1 parent d3cf981 commit 01a086e
Show file tree
Hide file tree
Showing 10 changed files with 202 additions and 14 deletions.
48 changes: 48 additions & 0 deletions .changelog/3417.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
```release-note:new-resource
`google_healthcare_dataset` is now GA
```
```release-note:new-resource
`google_healthcare_dicom_store` is now GA
```
```release-note:new-resource
`google_healthcare_fhir_store` is now GA
```
```release-note:new-resource
`google_healthcare_hl7_v2_store` is now GA
```
```release-note:new-resource
`google_healthcare_dataset_iam_binding` is now GA
```
```release-note:new-resource
`google_healthcare_dataset_iam_member` is now GA
```
```release-note:new-resource
`google_healthcare_dataset_iam_policy` is now GA
```
```release-note:new-resource
`google_healthcare_dicom_store_iam_binding` is now GA
```
```release-note:new-resource
`google_healthcare_dicom_store_iam_member` is now GA
```
```release-note:new-resource
`google_healthcare_dicom_store_iam_policy` is now GA
```
```release-note:new-resource
`google_healthcare_fhir_store_iam_binding` is now GA
```
```release-note:new-resource
`google_healthcare_fhir_store_iam_member` is now GA
```
```release-note:new-resource
`google_healthcare_fhir_store_iam_policy` is now GA
```
```release-note:new-resource
`google_healthcare_hl7_v2_store_iam_binding` is now GA
```
```release-note:new-resource
`google_healthcare_hl7_v2_store_iam_member` is now GA
```
```release-note:new-resource
`google_healthcare_hl7_v2_store_iam_policy` is now GA
```
2 changes: 1 addition & 1 deletion google/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import (
"google.golang.org/api/dns/v1"
dnsBeta "google.golang.org/api/dns/v1beta2"
file "google.golang.org/api/file/v1beta1"
healthcare "google.golang.org/api/healthcare/v1beta1"
healthcare "google.golang.org/api/healthcare/v1"
"google.golang.org/api/iam/v1"
iamcredentials "google.golang.org/api/iamcredentials/v1"
cloudlogging "google.golang.org/api/logging/v2"
Expand Down
2 changes: 1 addition & 1 deletion google/iam_healthcare_dataset.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package google
import (
"fmt"

healthcare "google.golang.org/api/healthcare/v1beta1"
healthcare "google.golang.org/api/healthcare/v1"

"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
Expand Down
2 changes: 1 addition & 1 deletion google/iam_healthcare_dicom_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package google
import (
"fmt"

healthcare "google.golang.org/api/healthcare/v1beta1"
healthcare "google.golang.org/api/healthcare/v1"

"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
Expand Down
2 changes: 1 addition & 1 deletion google/iam_healthcare_fhir_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package google
import (
"fmt"

healthcare "google.golang.org/api/healthcare/v1beta1"
healthcare "google.golang.org/api/healthcare/v1"

"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
Expand Down
2 changes: 1 addition & 1 deletion google/iam_healthcare_hl7_v2_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package google
import (
"fmt"

healthcare "google.golang.org/api/healthcare/v1beta1"
healthcare "google.golang.org/api/healthcare/v1"

"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
Expand Down
122 changes: 122 additions & 0 deletions google/resource_healthcare_hl7_v2_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }.`,
"notification_config": {
Type: schema.TypeList,
Optional: true,
Removed: "This field has been replaced by notificationConfigs",
Description: `A nested object resource`,
MaxItems: 1,
Elem: &schema.Resource{
Expand All @@ -98,6 +99,44 @@ Cloud Pub/Sub topic. Not having adequate permissions will cause the calls that s
},
},
},
"notification_configs": {
Type: schema.TypeList,
Optional: true,
Description: `A list of notification configs. Each configuration uses a filter to determine whether to publish a
message (both Ingest & Create) on the corresponding notification destination. Only the message name
is sent as part of the notification. Supplied by the client.`,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"pubsub_topic": {
Type: schema.TypeString,
Required: true,
Description: `The Cloud Pub/Sub topic that notifications of changes are published on. Supplied by the client.
PubsubMessage.Data will contain the resource name. PubsubMessage.MessageId is the ID of this message.
It is guaranteed to be unique within the topic. PubsubMessage.PublishTime is the time at which the message
was published. Notifications are only sent if the topic is non-empty. Topic names must be scoped to a
project. [email protected] must have publisher permissions on the given
Cloud Pub/Sub topic. Not having adequate permissions will cause the calls that send notifications to fail.
If a notification cannot be published to Cloud Pub/Sub, errors will be logged to Stackdriver`,
},
"filter": {
Type: schema.TypeString,
Optional: true,
Description: `Restricts notifications sent for messages matching a filter. If this is empty, all messages
are matched. Syntax: https://cloud.google.com/appengine/docs/standard/python/search/query_strings
Fields/functions available for filtering are:
* messageType, from the MSH-9.1 field. For example, NOT messageType = "ADT".
* send_date or sendDate, the YYYY-MM-DD date the message was sent in the dataset's timeZone, from the MSH-7 segment. For example, send_date < "2017-01-02".
* sendTime, the timestamp when the message was sent, using the RFC3339 time format for comparisons, from the MSH-7 segment. For example, sendTime < "2017-01-02T00:00:00-05:00".
* sendFacility, the care center that the message came from, from the MSH-4 segment. For example, sendFacility = "ABC".
* PatientId(value, type), which matches if the message lists a patient having an ID of the given value and type in the PID-2, PID-3, or PID-4 segments. For example, PatientId("123456", "MRN").
* labels.x, a string value of the label with key x as set using the Message.labels map. For example, labels."priority"="high". The operator :* can be used to assert the existence of a label. For example, labels."priority":*.`,
},
},
},
},
"parser_config": {
Type: schema.TypeList,
Optional: true,
Expand Down Expand Up @@ -162,6 +201,12 @@ func resourceHealthcareHl7V2StoreCreate(d *schema.ResourceData, meta interface{}
} else if v, ok := d.GetOkExists("labels"); !isEmptyValue(reflect.ValueOf(labelsProp)) && (ok || !reflect.DeepEqual(v, labelsProp)) {
obj["labels"] = labelsProp
}
notificationConfigsProp, err := expandHealthcareHl7V2StoreNotificationConfigs(d.Get("notification_configs"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("notification_configs"); !isEmptyValue(reflect.ValueOf(notificationConfigsProp)) && (ok || !reflect.DeepEqual(v, notificationConfigsProp)) {
obj["notificationConfigs"] = notificationConfigsProp
}
notificationConfigProp, err := expandHealthcareHl7V2StoreNotificationConfig(d.Get("notification_config"), d, config)
if err != nil {
return err
Expand Down Expand Up @@ -226,6 +271,9 @@ func resourceHealthcareHl7V2StoreRead(d *schema.ResourceData, meta interface{})
if err := d.Set("labels", flattenHealthcareHl7V2StoreLabels(res["labels"], d, config)); err != nil {
return fmt.Errorf("Error reading Hl7V2Store: %s", err)
}
if err := d.Set("notification_configs", flattenHealthcareHl7V2StoreNotificationConfigs(res["notificationConfigs"], d, config)); err != nil {
return fmt.Errorf("Error reading Hl7V2Store: %s", err)
}
if err := d.Set("notification_config", flattenHealthcareHl7V2StoreNotificationConfig(res["notificationConfig"], d, config)); err != nil {
return fmt.Errorf("Error reading Hl7V2Store: %s", err)
}
Expand All @@ -249,6 +297,12 @@ func resourceHealthcareHl7V2StoreUpdate(d *schema.ResourceData, meta interface{}
} else if v, ok := d.GetOkExists("labels"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) {
obj["labels"] = labelsProp
}
notificationConfigsProp, err := expandHealthcareHl7V2StoreNotificationConfigs(d.Get("notification_configs"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("notification_configs"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, notificationConfigsProp)) {
obj["notificationConfigs"] = notificationConfigsProp
}
notificationConfigProp, err := expandHealthcareHl7V2StoreNotificationConfig(d.Get("notification_config"), d, config)
if err != nil {
return err
Expand All @@ -272,6 +326,10 @@ func resourceHealthcareHl7V2StoreUpdate(d *schema.ResourceData, meta interface{}
updateMask = append(updateMask, "labels")
}

if d.HasChange("notification_configs") {
updateMask = append(updateMask, "notificationConfigs")
}

if d.HasChange("notification_config") {
updateMask = append(updateMask, "notificationConfig")
}
Expand Down Expand Up @@ -370,6 +428,33 @@ func flattenHealthcareHl7V2StoreLabels(v interface{}, d *schema.ResourceData, co
return v
}

func flattenHealthcareHl7V2StoreNotificationConfigs(v interface{}, d *schema.ResourceData, config *Config) interface{} {
if v == nil {
return v
}
l := v.([]interface{})
transformed := make([]interface{}, 0, len(l))
for _, raw := range l {
original := raw.(map[string]interface{})
if len(original) < 1 {
// Do not include empty json objects coming back from the api
continue
}
transformed = append(transformed, map[string]interface{}{
"pubsub_topic": flattenHealthcareHl7V2StoreNotificationConfigsPubsubTopic(original["pubsubTopic"], d, config),
"filter": flattenHealthcareHl7V2StoreNotificationConfigsFilter(original["filter"], d, config),
})
}
return transformed
}
func flattenHealthcareHl7V2StoreNotificationConfigsPubsubTopic(v interface{}, d *schema.ResourceData, config *Config) interface{} {
return v
}

func flattenHealthcareHl7V2StoreNotificationConfigsFilter(v interface{}, d *schema.ResourceData, config *Config) interface{} {
return v
}

func flattenHealthcareHl7V2StoreNotificationConfig(v interface{}, d *schema.ResourceData, config *Config) interface{} {
if v == nil {
return nil
Expand Down Expand Up @@ -455,6 +540,43 @@ func expandHealthcareHl7V2StoreLabels(v interface{}, d TerraformResourceData, co
return m, nil
}

func expandHealthcareHl7V2StoreNotificationConfigs(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
l := v.([]interface{})
req := make([]interface{}, 0, len(l))
for _, raw := range l {
if raw == nil {
continue
}
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})

transformedPubsubTopic, err := expandHealthcareHl7V2StoreNotificationConfigsPubsubTopic(original["pubsub_topic"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedPubsubTopic); val.IsValid() && !isEmptyValue(val) {
transformed["pubsubTopic"] = transformedPubsubTopic
}

transformedFilter, err := expandHealthcareHl7V2StoreNotificationConfigsFilter(original["filter"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedFilter); val.IsValid() && !isEmptyValue(val) {
transformed["filter"] = transformedFilter
}

req = append(req, transformed)
}
return req, nil
}

func expandHealthcareHl7V2StoreNotificationConfigsPubsubTopic(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
return v, nil
}

func expandHealthcareHl7V2StoreNotificationConfigsFilter(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
return v, nil
}

func expandHealthcareHl7V2StoreNotificationConfig(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
Expand Down
2 changes: 1 addition & 1 deletion google/resource_healthcare_hl7_v2_store_generated_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ resource "google_healthcare_hl7_v2_store" "default" {
name = "tf-test-example-hl7-v2-store%{random_suffix}"
dataset = google_healthcare_dataset.dataset.id
notification_config {
notification_configs {
pubsub_topic = google_pubsub_topic.topic.id
}
Expand Down
11 changes: 7 additions & 4 deletions google/resource_healthcare_hl7_v2_store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ resource "google_healthcare_hl7_v2_store" "default" {
segment_terminator = "Jw=="
}
notification_config {
notification_configs {
pubsub_topic = google_pubsub_topic.topic.id
}
Expand Down Expand Up @@ -195,9 +195,12 @@ func testAccCheckGoogleHealthcareHl7V2StoreUpdate(t *testing.T, pubsubTopic stri
return fmt.Errorf("hl7_v2_store labels not updated: %s", gcpResourceUri)
}

topicName := path.Base(response.NotificationConfig.PubsubTopic)
if topicName != pubsubTopic {
return fmt.Errorf("hl7_v2_store 'NotificationConfig' not updated ('%s' != '%s'): %s", topicName, pubsubTopic, gcpResourceUri)
notifications := response.NotificationConfigs
if len(notifications) > 0 {
topicName := path.Base(notifications[0].PubsubTopic)
if topicName != pubsubTopic {
return fmt.Errorf("hl7_v2_store 'NotificationConfig' not updated ('%s' != '%s'): %s", topicName, pubsubTopic, gcpResourceUri)
}
}
}

Expand Down
23 changes: 19 additions & 4 deletions website/docs/r/healthcare_hl7_v2_store.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ resource "google_healthcare_hl7_v2_store" "default" {
name = "example-hl7-v2-store"
dataset = google_healthcare_dataset.dataset.id
notification_config {
notification_configs {
pubsub_topic = google_pubsub_topic.topic.id
}
Expand Down Expand Up @@ -204,9 +204,11 @@ The following arguments are supported:
An object containing a list of "key": value pairs.
Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }.

* `notification_config` -
* `notification_configs` -
(Optional)
A nested object resource Structure is documented below.
A list of notification configs. Each configuration uses a filter to determine whether to publish a
message (both Ingest & Create) on the corresponding notification destination. Only the message name
is sent as part of the notification. Supplied by the client. Structure is documented below.


The `parser_config` block supports:
Expand All @@ -225,7 +227,7 @@ The `parser_config` block supports:
JSON encoded string for schemas used to parse messages in this
store if schematized parsing is desired.

The `notification_config` block supports:
The `notification_configs` block supports:

* `pubsub_topic` -
(Required)
Expand All @@ -235,6 +237,19 @@ The `notification_config` block supports:
was published. Notifications are only sent if the topic is non-empty. Topic names must be scoped to a
project. [email protected] must have publisher permissions on the given
Cloud Pub/Sub topic. Not having adequate permissions will cause the calls that send notifications to fail.
If a notification cannot be published to Cloud Pub/Sub, errors will be logged to Stackdriver

* `filter` -
(Optional)
Restricts notifications sent for messages matching a filter. If this is empty, all messages
are matched. Syntax: https://cloud.google.com/appengine/docs/standard/python/search/query_strings
Fields/functions available for filtering are:
* messageType, from the MSH-9.1 field. For example, NOT messageType = "ADT".
* send_date or sendDate, the YYYY-MM-DD date the message was sent in the dataset's timeZone, from the MSH-7 segment. For example, send_date < "2017-01-02".
* sendTime, the timestamp when the message was sent, using the RFC3339 time format for comparisons, from the MSH-7 segment. For example, sendTime < "2017-01-02T00:00:00-05:00".
* sendFacility, the care center that the message came from, from the MSH-4 segment. For example, sendFacility = "ABC".
* PatientId(value, type), which matches if the message lists a patient having an ID of the given value and type in the PID-2, PID-3, or PID-4 segments. For example, PatientId("123456", "MRN").
* labels.x, a string value of the label with key x as set using the Message.labels map. For example, labels."priority"="high". The operator :* can be used to assert the existence of a label. For example, labels."priority":*.

## Attributes Reference

Expand Down

0 comments on commit 01a086e

Please sign in to comment.