diff --git a/examples/ibm-event-streams/main.tf b/examples/ibm-event-streams/main.tf index a16618467b..cf2b8af17d 100644 --- a/examples/ibm-event-streams/main.tf +++ b/examples/ibm-event-streams/main.tf @@ -99,3 +99,53 @@ resource "ibm_resource_tag" "tag_example_on_es" { tag_type = "access" resource_id = data.ibm_resource_instance.es_instance_5.id } + +#### Scenario 6: Create a target Event Streams service instance with mirroring enabled and its mirroring config +data "ibm_resource_instance" "es_instance_source" { + name = "terraform-integration-source" + resource_group_id = data.ibm_resource_group.group.id +} +# setup s2s at service level for mirroring to work +resource "ibm_iam_authorization_policy" "service-policy" { + source_service_name = "messagehub" + target_service_name = "messagehub" + roles = ["Reader"] + description = "test mirroring setup via terraform" +} + +resource "ibm_resource_instance" "es_instance_target" { + name = "terraform-integration-target" + service = "messagehub" + plan = "enterprise-3nodes-2tb" + location = "us-south" + resource_group_id = data.ibm_resource_group.group.id + parameters_json = jsonencode( + { + mirroring = { + source_crn = data.ibm_resource_instance.es_instance_source.id + source_alias = "source-alias" + target_alias = "target-alias" + } + } + ) + timeouts { + create = "3h" + update = "1h" + delete = "15m" + } +} +# Configure a service-to-service binding between both instances to allow both instances to communicate. +resource "ibm_iam_authorization_policy" "instance_policy" { + source_service_name = "messagehub" + source_resource_instance_id = ibm_resource_instance.es_instance_target.guid + target_service_name = "messagehub" + target_resource_instance_id = data.ibm_resource_instance.es_instance_source.guid + roles = ["Reader"] + description = "test mirroring setup via terraform" +} + +# Select some topics from the source cluster to mirror. +resource "ibm_event_streams_mirroring_config" "es_mirroring_config" { + resource_instance_id = ibm_resource_instance.es_instance_target.id + mirroring_topic_patterns = ["topicA", "topicB"] +} diff --git a/ibm/provider/provider.go b/ibm/provider/provider.go index 2bf3bbb6bb..540a0d37ef 100644 --- a/ibm/provider/provider.go +++ b/ibm/provider/provider.go @@ -359,6 +359,7 @@ func Provider() *schema.Provider { "ibm_event_streams_topic": eventstreams.DataSourceIBMEventStreamsTopic(), "ibm_event_streams_schema": eventstreams.DataSourceIBMEventStreamsSchema(), "ibm_event_streams_quota": eventstreams.DataSourceIBMEventStreamsQuota(), + "ibm_event_streams_mirroring_config": eventstreams.DataSourceIBMEventStreamsMirroringConfig(), "ibm_hpcs": hpcs.DataSourceIBMHPCS(), "ibm_hpcs_managed_key": hpcs.DataSourceIbmManagedKey(), "ibm_hpcs_key_template": hpcs.DataSourceIbmKeyTemplate(), @@ -1114,6 +1115,7 @@ func Provider() *schema.Provider { "ibm_event_streams_topic": eventstreams.ResourceIBMEventStreamsTopic(), "ibm_event_streams_schema": eventstreams.ResourceIBMEventStreamsSchema(), "ibm_event_streams_quota": eventstreams.ResourceIBMEventStreamsQuota(), + "ibm_event_streams_mirroring_config": eventstreams.ResourceIBMEventStreamsMirroringConfig(), "ibm_firewall": classicinfrastructure.ResourceIBMFirewall(), "ibm_firewall_policy": classicinfrastructure.ResourceIBMFirewallPolicy(), "ibm_hpcs": hpcs.ResourceIBMHPCS(), diff --git a/ibm/service/eventstreams/data_source_ibm_event_streams_mirroring_config.go b/ibm/service/eventstreams/data_source_ibm_event_streams_mirroring_config.go new file mode 100644 index 0000000000..bf913d41bb --- /dev/null +++ b/ibm/service/eventstreams/data_source_ibm_event_streams_mirroring_config.go @@ -0,0 +1,114 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package eventstreams + +import ( + "context" + "fmt" + "log" + "strings" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/eventstreams-go-sdk/pkg/adminrestv1" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +const ( + mirroringConfigResourceType = "mirroring-config" +) + +// The mirroring config for topic selection in an Event Streams service instance. +// The ID is the CRN with the last two components "mirroring-config:". +// The mirroring topic patterns defines the topic selection. +func DataSourceIBMEventStreamsMirroringConfig() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceIBMEventStreamsMirroringConfigRead, + Schema: map[string]*schema.Schema{ + "resource_instance_id": { + Type: schema.TypeString, + Required: true, + Description: "The ID or CRN of the Event Streams service instance", + }, + "mirroring_topic_patterns": { + Type: schema.TypeList, + Computed: true, + Description: "The topic pattern to use for mirroring", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + } + +} + +// read mirroring config using the admin-rest API +func dataSourceIBMEventStreamsMirroringConfigRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + adminrestClient, err := meta.(conns.ClientSession).ESadminRestSession() + if err != nil { + tfErr := flex.TerraformErrorf(err, "Error getting Event Streams admin rest session", "ibm_event_streams_mirroring_config", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + adminURL, instanceCRN, err := getMirroringConfigInstanceURL(d, meta) + if err != nil { + tfErr := flex.TerraformErrorf(err, "Error getting Event Streams mirroring config URL", "ibm_event_streams_mirroring_config", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + adminrestClient.SetServiceURL(adminURL) + + getMirroringConfigOptions := &adminrestv1.GetMirroringTopicSelectionOptions{} + mirroringConfig, _, err := adminrestClient.GetMirroringTopicSelectionWithContext(context, getMirroringConfigOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, "GetMirroringTopicSelection returned error", "ibm_event_streams_mirroring_config", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + if mirroringConfig == nil { + tfErr := flex.TerraformErrorf(err, "Unexpected nil config when getting mirroring config", "ibm_event_streams_mirroring_config", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + d.SetId(getMirroringConfigID(instanceCRN)) + d.Set("resource_instance_id", instanceCRN) + d.Set("mirroring_topic_patterns", mirroringConfig.Includes) + return nil +} + +func getMirroringConfigInstanceURL(d *schema.ResourceData, meta interface{}) (string, string, error) { + instanceCRN := d.Get("resource_instance_id").(string) + if instanceCRN == "" { // importing + id := d.Id() + crnSegments := strings.Split(id, ":") + if len(crnSegments) != 10 || crnSegments[8] != mirroringConfigResourceType { + return "", "", fmt.Errorf("ID '%s' is not a mirroring config resource", id) + } + crnSegments[8] = "" + crnSegments[9] = "" + instanceCRN = strings.Join(crnSegments, ":") + d.Set("resource_instance_id", instanceCRN) + } + + instance, err := getInstanceDetails(instanceCRN, meta) + if err != nil { + return "", "", err + } + adminURL := instance.Extensions["kafka_http_url"].(string) + planID := *instance.ResourcePlanID + valid := strings.Contains(planID, "enterprise") + if !valid { + return "", "", fmt.Errorf("mirroring config is not supported by the Event Streams %s plan, enterprise plan is expected", + planID) + } + return adminURL, instanceCRN, nil +} + +func getMirroringConfigID(instanceCRN string) string { + crnSegments := strings.Split(instanceCRN, ":") + crnSegments[8] = mirroringConfigResourceType + crnSegments[9] = "" + return strings.Join(crnSegments, ":") +} diff --git a/ibm/service/eventstreams/data_source_ibm_event_streams_mirroring_config_test.go b/ibm/service/eventstreams/data_source_ibm_event_streams_mirroring_config_test.go new file mode 100644 index 0000000000..27483e0085 --- /dev/null +++ b/ibm/service/eventstreams/data_source_ibm_event_streams_mirroring_config_test.go @@ -0,0 +1,64 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package eventstreams_test + +import ( + "fmt" + "strings" + "testing" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestAccIBMEventStreamsMirroringConfigDataSource(t *testing.T) { + instanceName := "ES Integration Pipeline MZR" + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMEventStreamsMirroringConfigDataSource(instanceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMEventStreamsMirroringConfigProperties("data.ibm_event_streams_mirroring_config.es_mirroring_config"), + resource.TestCheckResourceAttr("data.ibm_event_streams_mirroring_config.es_mirroring_config", "mirroring_topic_patterns.#", "1"), + resource.TestCheckResourceAttr("data.ibm_event_streams_mirroring_config.es_mirroring_config", "mirroring_topic_patterns.0", ".*"), + ), + }, + }, + }) +} + +// check properties of the mirroring config data source or resource object +func testAccCheckIBMEventStreamsMirroringConfigProperties(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + mcID := rs.Primary.ID + if mcID == "" { + return fmt.Errorf("[ERROR] Mirroring config ID is not set") + } + if !strings.HasSuffix(mcID, ":mirroring-config:") { + return fmt.Errorf("[ERROR] Mirroring config ID %s not expected CRN", mcID) + } + return nil + } +} + +func testAccCheckIBMEventStreamsMirroringConfigDataSource(instanceName string) string { + return fmt.Sprintf(` +data "ibm_resource_group" "group" { + is_default = true +} +data "ibm_resource_instance" "es_instance" { + resource_group_id = data.ibm_resource_group.group.id + name = "%s" +} +data "ibm_event_streams_mirroring_config" "es_mirroring_config" { + resource_instance_id = data.ibm_resource_instance.es_instance.id +}`, instanceName) +} diff --git a/ibm/service/eventstreams/resource_ibm_event_streams_mirroring_config.go b/ibm/service/eventstreams/resource_ibm_event_streams_mirroring_config.go new file mode 100644 index 0000000000..eaef8ed04f --- /dev/null +++ b/ibm/service/eventstreams/resource_ibm_event_streams_mirroring_config.go @@ -0,0 +1,102 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package eventstreams + +import ( + "context" + "log" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/eventstreams-go-sdk/pkg/adminrestv1" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +// The mirroring config for topic selection in an Event Streams service instance. +// The ID is the CRN with the last two components "mirroring-config:". +// The mirroring topic patterns defines the topic selection. +func ResourceIBMEventStreamsMirroringConfig() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceIBMEventStreamsMirroringConfigUpdate, + ReadContext: resourceIBMEventStreamsMirroringConfigRead, + UpdateContext: resourceIBMEventStreamsMirroringConfigUpdate, + DeleteContext: resourceIBMEventStreamsMirroringConfigDelete, + Importer: &schema.ResourceImporter{}, + Schema: map[string]*schema.Schema{ + "resource_instance_id": { + Type: schema.TypeString, + Required: true, + Description: "The ID or CRN of the Event Streams service instance", + }, + "mirroring_topic_patterns": { + Type: schema.TypeList, + Required: true, + Description: "The topic pattern to use for mirroring", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + } +} + +func resourceIBMEventStreamsMirroringConfigRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + return dataSourceIBMEventStreamsMirroringConfigRead(context, d, meta) +} + +// The mirroring topic selection for a mirroring enabled instance is always replaced, +// so create and update have the same behavior +func resourceIBMEventStreamsMirroringConfigUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + adminrestClient, err := meta.(conns.ClientSession).ESadminRestSession() + if err != nil { + tfErr := flex.TerraformErrorf(err, "Error getting Event Streams admin rest session", "ibm_event_streams_mirroring_config", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + adminURL, _, err := getMirroringConfigInstanceURL(d, meta) + if err != nil { + tfErr := flex.TerraformErrorf(err, "Error getting Event Streams mirroring config URL", "ibm_event_streams_mirroring_config", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + adminrestClient.SetServiceURL(adminURL) + mirroringOptions := &adminrestv1.ReplaceMirroringTopicSelectionOptions{} + mirroringOptions.SetIncludes(flex.ExpandStringList(d.Get("mirroring_topic_patterns").([]interface{}))) + + _, _, err = adminrestClient.ReplaceMirroringTopicSelectionWithContext(context, mirroringOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, "ReplaceMirroringTopicSelection returned error", "ibm_event_streams_mirroring_config", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + return resourceIBMEventStreamsMirroringConfigRead(context, d, meta) +} + +// The mirroring config can't be deleted, but we reset with an empty list. +func resourceIBMEventStreamsMirroringConfigDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + adminrestClient, err := meta.(conns.ClientSession).ESadminRestSession() + if err != nil { + tfErr := flex.TerraformErrorf(err, "Error getting Event Streams admin rest session", "ibm_event_streams_mirroring_config", "delete") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + adminURL, _, err := getMirroringConfigInstanceURL(d, meta) + if err != nil { + tfErr := flex.TerraformErrorf(err, "Error getting Event Streams mirroring config URL", "ibm_event_streams_mirroring_config", "delete") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + adminrestClient.SetServiceURL(adminURL) + mirroringOptions := &adminrestv1.ReplaceMirroringTopicSelectionOptions{} + mirroringOptions.SetIncludes([]string{}) + _, _, err = adminrestClient.ReplaceMirroringTopicSelectionWithContext(context, mirroringOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, "ReplaceMirroringTopicSelection returned error", "ibm_event_streams_mirroring_config", "delete") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + d.SetId("") + return nil +} diff --git a/ibm/service/eventstreams/resource_ibm_event_streams_topic_test.go b/ibm/service/eventstreams/resource_ibm_event_streams_topic_test.go index 680fd68775..1c0a78aef6 100644 --- a/ibm/service/eventstreams/resource_ibm_event_streams_topic_test.go +++ b/ibm/service/eventstreams/resource_ibm_event_streams_topic_test.go @@ -155,11 +155,14 @@ func TestAccIBMEventStreamsEnterprise(t *testing.T) { topicName := fmt.Sprintf("es_topic_%d", acctest.RandInt()) partitions := 1 parameters := map[string]string{ - "service-endpoints": "public-and-private", - "private_ip_allowlist": "[9.0.0.0/8]", // allowing jenkins access - "throughput": "150", - "storage_size": "2048", - "kms_key_crn": "crn:v1:staging:public:kms:us-south:a/6db1b0d0b5c54ee5c201552547febcd8:0aa69b09-941b-41b2-bbf9-9f9f0f6a6f79:key:dd37a0b6-eff4-4708-8459-e29ae0a8f256", //preprod-byok-customer-key from KMS instance keyprotect-preprod-customer-keys + "service-endpoints": "public", + "throughput": "150", + "storage_size": "2048", + "kms_key_crn": "crn:v1:staging:public:kms:us-south:a/6db1b0d0b5c54ee5c201552547febcd8:0aa69b09-941b-41b2-bbf9-9f9f0f6a6f79:key:dd37a0b6-eff4-4708-8459-e29ae0a8f256", //preprod-byok-customer-key from KMS instance keyprotect-preprod-customer-keys + //ES Preprod Pipeline Mirror E2E + "source_crn": "crn:v1:staging:public:messagehub:eu-gb:a/6db1b0d0b5c54ee5c201552547febcd8:4414aa6e-237a-495d-b0b1-1b69d64d874b::", + "target_alias": "target-cluster", + "source_alias": "source-cluster", } resource.Test(t, resource.TestCase{ PreCheck: func() { acc.TestAccPreCheck(t) }, @@ -177,6 +180,9 @@ func TestAccIBMEventStreamsEnterprise(t *testing.T) { resource.TestCheckResourceAttrSet("ibm_event_streams_topic.es_topic", "id"), resource.TestCheckResourceAttr("ibm_event_streams_topic.es_topic", "name", topicName), resource.TestCheckResourceAttr("ibm_event_streams_topic.es_topic", "partitions", strconv.Itoa(partitions)), + testAccCheckIBMEventStreamsMirroringConfigProperties("ibm_event_streams_mirroring_config.es_mirroring_config"), + resource.TestCheckResourceAttr("ibm_event_streams_mirroring_config.es_mirroring_config", "mirroring_topic_patterns.#", "1"), + resource.TestCheckResourceAttr("ibm_event_streams_mirroring_config.es_mirroring_config", "mirroring_topic_patterns.0", ".*"), ), }, }, @@ -197,7 +203,8 @@ func testAccCheckIBMEventStreamsTopicWithConfig(instanceName, serviceName, planI func testAccCheckIBMEventStreamsEnterpriseWithParameters(instanceName, serviceName, planID, location, topicName string, partitions int, params map[string]string) string { return createPlatformResources(instanceName, serviceName, planID, location, params) + "\n" + - createEventStreamsTopicResourceWithoutConfig(true, topicName, partitions) + createEventStreamsTopicResourceWithoutConfig(true, topicName, partitions) + "\n" + + createEventStreamsMirroringConfig(serviceName, params["source_crn"]) } func testAccCheckIBMEventStreamsTopicWithExistingInstanceWithoutConfig(instanceName, @@ -239,29 +246,54 @@ func createPlatformResources(instanceName, serviceName, planID, location string, } // create enterprise instance return fmt.Sprintf(` - data "ibm_resource_group" "group" { - is_default=true - } - resource "ibm_resource_instance" "es_instance" { - name = "%s" - service = "%s" - plan = "%s" - location = "%s" - resource_group_id = data.ibm_resource_group.group.id - parameters = { - service-endpoints = "%s" - private_ip_allowlist = "%s" - throughput = "%s" - storage_size = "%s" - kms_key_crn = "%s" - } - timeouts { - create = "3h" - update = "1h" - delete = "15m" - } - }`, instanceName, serviceName, planID, location, - parameters["service-endpoints"], parameters["private_ip_allowlist"], parameters["throughput"], parameters["storage_size"], parameters["kms_key_crn"]) +data "ibm_resource_group" "group" { + is_default = true +} +resource "ibm_resource_instance" "es_instance" { + name = "%s" + service = "%s" + plan = "%s" + location = "%s" + resource_group_id = data.ibm_resource_group.group.id + parameters_json = jsonencode( + { + service-endpoints = "%s" + throughput = "%s" + storage_size = "%s" + kms_key_crn = "%s" + mirroring = { + source_crn = "%s" + source_alias = "%s" + target_alias = "%s" + } + } + ) + timeouts { + create = "3h" + update = "1h" + delete = "15m" + } +}`, instanceName, serviceName, planID, location, + parameters["service-endpoints"], parameters["throughput"], parameters["storage_size"], parameters["kms_key_crn"], parameters["source_crn"], parameters["source_alias"], parameters["target_alias"]) +} + +func createEventStreamsMirroringConfig(serviceName, targetCrn string) string { + //get target guid from target crn + targetGuid := strings.Split(targetCrn, ":")[7] + return fmt.Sprintf(` +resource "ibm_iam_authorization_policy" "instance_policy" { + source_service_name = "%s" + source_resource_instance_id = ibm_resource_instance.es_instance.guid + target_service_name = "%s" + target_resource_instance_id = "%s" + roles = ["Reader"] + description = "test mirroring setup via terraform" +} + +resource "ibm_event_streams_mirroring_config" "es_mirroring_config" { + resource_instance_id = ibm_resource_instance.es_instance.id + mirroring_topic_patterns = [".*"] +}`, serviceName, serviceName, targetGuid) } func createEventStreamsTopicResourceWithoutConfig(createInstance bool, topicName string, partitions int) string { @@ -307,21 +339,42 @@ func testAccCheckIBMEventStreamsInstanceDestroy(s *terraform.State) error { return err } for _, rs := range s.RootModule().Resources { - if rs.Type != "ibm_resource_instance" { + if rs.Type != "ibm_resource_instance" && rs.Type != "ibm_iam_authorization_policy" { continue } - instanceID := rs.Primary.ID - instance, err := rsContClient.ResourceServiceInstanceV2().GetInstance(instanceID) - if err != nil { - if strings.Contains(err.Error(), "404") { - return nil + // adding authotization policy check for mirroring instance + if rs.Type == "ibm_iam_authorization_policy" { + iamPolicyManagementClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).IAMPolicyManagementV1API() + if err != nil { + return err + } + authPolicyID := rs.Primary.ID + + getPolicyOptions := iamPolicyManagementClient.NewGetPolicyOptions( + authPolicyID, + ) + destroyedPolicy, response, err := iamPolicyManagementClient.GetPolicy(getPolicyOptions) + + if err == nil && *destroyedPolicy.State != "deleted" { + return fmt.Errorf("Authorization policy still exists: %s\n", rs.Primary.ID) + } else if response.StatusCode != 404 && destroyedPolicy.State != nil && *destroyedPolicy.State != "deleted" { + return fmt.Errorf("[ERROR] Error waiting for authorization policy (%s) to be destroyed: %s", rs.Primary.ID, err) } - return fmt.Errorf("[ERROR] Error checking if instance (%s) has been destroyed: %s", rs.Primary.ID, err) } + if rs.Type == "ibm_resource_instance" { + instanceID := rs.Primary.ID + instance, err := rsContClient.ResourceServiceInstanceV2().GetInstance(instanceID) + if err != nil { + if strings.Contains(err.Error(), "404") { + return nil + } + return fmt.Errorf("[ERROR] Error checking if instance (%s) has been destroyed: %s", rs.Primary.ID, err) + } - if !reflect.DeepEqual(instance, models.ServiceInstanceV2{}) && - instance.State != "removed" && instance.State != "pending_reclamation" { - return fmt.Errorf("[ERROR] Instance (%s) is not removed", rs.Primary.ID) + if !reflect.DeepEqual(instance, models.ServiceInstanceV2{}) && + instance.State != "removed" && instance.State != "pending_reclamation" { + return fmt.Errorf("[ERROR] Instance (%s) is not removed", rs.Primary.ID) + } } } return nil diff --git a/website/docs/d/event_streams_mirroring_config.html.markdown b/website/docs/d/event_streams_mirroring_config.html.markdown new file mode 100644 index 0000000000..dd8a148359 --- /dev/null +++ b/website/docs/d/event_streams_mirroring_config.html.markdown @@ -0,0 +1,37 @@ +--- +subcategory: "Event Streams" +layout: "ibm" +page_title: "IBM: ibm_event_streams_mirroring_config" +description: |- + Get information about an IBM Event Streams mirroring configuration resource. +--- + +# ibm_event_streams_mirroring_config + + +Retrieve information about the mirroring config of an Event Streams service instance. This can only be performed on an Event Streams Enterprise plan service instance. For more information about the Event Streams mirroring, see [Event Streams Mirroring](https://cloud.ibm.com/docs/EventStreams?topic=EventStreams-mirroring). + +## Example usage + +```terraform +data "ibm_resource_instance" "es_instance" { + name = "terraform-integration" + resource_group_id = data.ibm_resource_group.group.id +} + +data "ibm_event_streams_mirroring_config" "es_mirroring_config" { + resource_instance_id = data.ibm_resource_instance.es_instance.id +} +``` + +## Argument reference +Review the argument parameters that you can specify for your data source. + +- `resource_instance_id` - (Required, string) The ID or CRN of the Event Streams service instance. + +## Attribute reference + +In addition to all argument reference list, you can access the following attribute reference after your data source is created. + +- `id` - (String) The ID of the mirroring config in CRN format. For example, `crn:v1:bluemix:public:messagehub:us-south:a/6db1b0d0b5c54ee5c201552547febcd8:cb5a0252-8b8d-4390-b017-80b743d32839:mirroring-config:`. +- `mirroring_topic_patterns` - (List of String) The current topic selection patterns in the Event Streams instance. diff --git a/website/docs/r/event_streams_mirroring_config.html.markdown b/website/docs/r/event_streams_mirroring_config.html.markdown new file mode 100644 index 0000000000..b8b2a29e15 --- /dev/null +++ b/website/docs/r/event_streams_mirroring_config.html.markdown @@ -0,0 +1,56 @@ +--- +subcategory: "Event Streams" +layout: "ibm" +page_title: "IBM: ibm_event_streams_mirroring_config" +description: |- + Set the mirroring configuration of an IBM Event Streams instance. +--- + +# ibm_event_streams_mirroring_config + + +Set the mirroring topic patterns of an Event Streams service instance. This can only be performed on an Event Streams Enterprise plan service instance. For more information about the Event Streams mirroring, see [Event Streams Mirroring](https://cloud.ibm.com/docs/EventStreams?topic=EventStreams-mirroring). + +**Note:** The mirroring config is a configuration property for defining topic selection pattern of the Event Streams instance, not a resource which must be created. The default value of the config is an empty list. When the terraform resource is created or updated, it changes the value of the configuration to the `mirroring_topic_patterns` argument; when the resource is deleted, it resets the value to empty list. For this reason, **only one mirroring config resource should be created** for an Event Streams service instance. Creating more than one resource for a given `resource_instance_id` will have unpredictable effects including terraform errors. + +## Example usage + +```terraform +data "ibm_resource_instance" "es_instance" { + name = "terraform-integration" + resource_group_id = data.ibm_resource_group.group.id +} + +resource "ibm_event_streams_mirroring_config" "es_mirroring_config" { + resource_instance_id = data.ibm_resource_instance.es_instance.id + mirroring_topic_patterns = ["topicA", "topicB"] +} +``` + +## Argument reference +Review the argument parameters that you can specify for your resource. + +- `resource_instance_id` - (Required, String) The ID or CRN of the Event Streams service instance. +- `mirroring_topic_patterns` - (Required, List of String) The topic selection patterns to set in instance + +## Attribute reference + +In addition to all argument reference list, you can access the following attribute reference after your resource is created. + +- `id` - (String) The ID of the mirroring config in CRN format. For example, `crn:v1:bluemix:public:messagehub:us-south:a/6db1b0d0b5c54ee5c201552547febcd8:cb5a0252-8b8d-4390-b017-80b743d32839:mirroring-config:`. + +## Import + +The `ibm_event_streams_mirroring_config` resource can be imported by using the rule's `CRN`, which is the `id` described above: the CRN of the service instance, with resource type "mirroring-config". + +**Syntax** + +``` +$ terraform import ibm_event_streams_mirroring_config.es_mirroring_config +``` + +**Example** + +``` +$ terraform import ibm_event_streams_mirroring_config.es_mirroring_config crn:v1:bluemix:public:messagehub:us-south:a/6db1b0d0b5c54ee5c201552547febcd8:cb5a0252-8b8d-4390-b017-80b743d32839:mirroring-config: +```