From 4e617269182155be7b94f3ba6e70e65556684ef9 Mon Sep 17 00:00:00 2001 From: ronan doolan Date: Fri, 19 Apr 2024 03:05:09 +0100 Subject: [PATCH] add terraform resouce for dra service broker --- ibm/provider/provider.go | 1 + ..._ibm_cd_toolchain_tool_draservicebroker.go | 365 ++++++++++++++++++ ...cd_toolchain_tool_draservicebroker_test.go | 112 ++++++ 3 files changed, 478 insertions(+) create mode 100644 ibm/service/cdtoolchain/resource_ibm_cd_toolchain_tool_draservicebroker.go create mode 100644 ibm/service/cdtoolchain/resource_ibm_cd_toolchain_tool_draservicebroker_test.go diff --git a/ibm/provider/provider.go b/ibm/provider/provider.go index d992bbd2d44..8ce9b652aa5 100644 --- a/ibm/provider/provider.go +++ b/ibm/provider/provider.go @@ -1416,6 +1416,7 @@ func Provider() *schema.Provider { "ibm_cd_toolchain_tool_saucelabs": cdtoolchain.ResourceIBMCdToolchainToolSaucelabs(), "ibm_cd_toolchain_tool_jira": cdtoolchain.ResourceIBMCdToolchainToolJira(), "ibm_cd_toolchain_tool_eventnotifications": cdtoolchain.ResourceIBMCdToolchainToolEventnotifications(), + "ibm_cd_toolchain_tool_draservicebroker": cdtoolchain.ResourceIBMCdToolchainToolDRAServiceBroker(), // Added for Tekton Pipeline "ibm_cd_tekton_pipeline_definition": cdtektonpipeline.ResourceIBMCdTektonPipelineDefinition(), diff --git a/ibm/service/cdtoolchain/resource_ibm_cd_toolchain_tool_draservicebroker.go b/ibm/service/cdtoolchain/resource_ibm_cd_toolchain_tool_draservicebroker.go new file mode 100644 index 00000000000..d74a2d03ecb --- /dev/null +++ b/ibm/service/cdtoolchain/resource_ibm_cd_toolchain_tool_draservicebroker.go @@ -0,0 +1,365 @@ +package cdtoolchain + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" + "github.com/IBM/continuous-delivery-go-sdk/cdtoolchainv2" +) + +func ResourceIBMCdToolchainToolDRAServiceBroker() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceIBMCdToolchainToolDRAServiceBrokerCreate, + ReadContext: resourceIBMCdToolchainToolDRAServiceBrokerRead, + UpdateContext: resourceIBMCdToolchainToolDRAServiceBrokerUpdate, + DeleteContext: resourceIBMCdToolchainToolDRAServiceBrokerDelete, + Importer: &schema.ResourceImporter{}, + + Schema: map[string]*schema.Schema{ + "toolchain_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.InvokeValidator("ibm_cd_toolchain_tool_draservicebroker", "toolchain_id"), + Description: "ID of the toolchain to bind the tool to.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.InvokeValidator("ibm_cd_toolchain_tool_draservicebroker", "name"), + Description: "Name of the tool.", + }, + "parameters": &schema.Schema{ + Type: schema.TypeList, + MinItems: 1, + MaxItems: 1, + Required: true, + Description: "Parameters to be used to create the tool.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "dashboard_url": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The URL that you want to navigate to when you click the tool integration tile.", + }, + "broker_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The ID of your service broker.", + }, + "api_key_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The API key ID associated with the IBM Cloud service.", + }, + "api_key_secret": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The API key secret associated with the IBM Cloud service. This secret is never returned in an API response.", + }, + }, + }, + }, + "resource_group_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Resource group where the tool can be found.", + }, + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Tool CRN.", + }, + "toolchain_crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "CRN of toolchain which the tool is bound to.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "URI representing the tool.", + }, + "referent": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "Information on URIs to access this resource through the UI or API.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ui_href": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "URI representing the this resource through the UI.", + }, + "api_href": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "URI representing the this resource through an API.", + }, + }, + }, + }, + "updated_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Latest tool update timestamp.", + }, + "state": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Current configuration state of the tool.", + }, + "tool_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Tool ID.", + }, + }, + } +} + +func ResourceIBMCdToolchainToolDRAServiceBrokerValidator() *validate.ResourceValidator { + validateSchema := make([]validate.ValidateSchema, 0) + validateSchema = append(validateSchema, + validate.ValidateSchema{ + Identifier: "toolchain_id", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Required: true, + Regexp: `^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[89abAB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$`, + MinValueLength: 36, + MaxValueLength: 36, + }, + validate.ValidateSchema{ + Identifier: "name", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Optional: true, + Regexp: `^([^\\x00-\\x7F]|[a-zA-Z0-9-._ ])+$`, + MinValueLength: 0, + MaxValueLength: 128, + }, + ) + + resourceValidator := validate.ResourceValidator{ResourceName: "ibm_cd_toolchain_tool_draservicebroker", Schema: validateSchema} + return &resourceValidator +} + +func resourceIBMCdToolchainToolDRAServiceBrokerCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + cdToolchainClient, err := meta.(conns.ClientSession).CdToolchainV2() + if err != nil { + return diag.FromErr(err) + } + + createToolOptions := &cdtoolchainv2.CreateToolOptions{} + + createToolOptions.SetToolchainID(d.Get("toolchain_id").(string)) + createToolOptions.SetToolTypeID("draservicebroker") + parametersModel := GetParametersForCreate(d, ResourceIBMCdToolchainToolDRAServiceBroker(), nil) + createToolOptions.SetParameters(parametersModel) + if _, ok := d.GetOk("name"); ok { + createToolOptions.SetName(d.Get("name").(string)) + } + + postToolResponse, response, err := cdToolchainClient.CreateToolWithContext(context, createToolOptions) + if err != nil { + log.Printf("[DEBUG] CreateToolWithContext failed %s\n%s", err, response) + return diag.FromErr(fmt.Errorf("CreateToolWithContext failed %s\n%s", err, response)) + } + d.SetId(fmt.Sprintf("%s/%s", *createToolOptions.ToolchainID, *postToolResponse.ID)) + + return resourceIBMCdToolchainToolDRAServiceBrokerRead(context, d, meta) +} + +func resourceIBMCdToolchainToolDRAServiceBrokerRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + cdToolchainClient, err := meta.(conns.ClientSession).CdToolchainV2() + if err != nil { + return diag.FromErr(err) + } + + getToolByIDOptions := &cdtoolchainv2.GetToolByIDOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return diag.FromErr(err) + } + + getToolByIDOptions.SetToolchainID(parts[0]) + getToolByIDOptions.SetToolID(parts[1]) + + getToolByIDResponse, response, err := cdToolchainClient.GetToolByIDWithContext(context, getToolByIDOptions) + if err != nil { + if response != nil && response.StatusCode == 404 { + d.SetId("") + return nil + } + log.Printf("[DEBUG] GetToolByIDWithContext failed %s\n%s", err, response) + return diag.FromErr(fmt.Errorf("GetToolByIDWithContext failed %s\n%s", err, response)) + } + + if err = d.Set("toolchain_id", getToolByIDResponse.ToolchainID); err != nil { + return diag.FromErr(fmt.Errorf("Error setting toolchain_id: %s", err)) + } + parametersMap := GetParametersFromRead(getToolByIDResponse.Parameters, ResourceIBMCdToolchainToolDRAServiceBroker(), nil) + if err = d.Set("parameters", []map[string]interface{}{parametersMap}); err != nil { + return diag.FromErr(fmt.Errorf("Error setting parameters: %s", err)) + } + if err = d.Set("name", getToolByIDResponse.Name); err != nil { + return diag.FromErr(fmt.Errorf("Error setting name: %s", err)) + } + if err = d.Set("resource_group_id", getToolByIDResponse.ResourceGroupID); err != nil { + return diag.FromErr(fmt.Errorf("Error setting resource_group_id: %s", err)) + } + if err = d.Set("crn", getToolByIDResponse.CRN); err != nil { + return diag.FromErr(fmt.Errorf("Error setting crn: %s", err)) + } + if err = d.Set("toolchain_crn", getToolByIDResponse.ToolchainCRN); err != nil { + return diag.FromErr(fmt.Errorf("Error setting toolchain_crn: %s", err)) + } + if err = d.Set("href", getToolByIDResponse.Href); err != nil { + return diag.FromErr(fmt.Errorf("Error setting href: %s", err)) + } + referentMap, err := ResourceIBMCdToolchainToolDRAServiceBrokerToolReferentToMap(getToolByIDResponse.Referent) + if err != nil { + return diag.FromErr(err) + } + if err = d.Set("referent", []map[string]interface{}{referentMap}); err != nil { + return diag.FromErr(fmt.Errorf("Error setting referent: %s", err)) + } + if err = d.Set("updated_at", flex.DateTimeToString(getToolByIDResponse.UpdatedAt)); err != nil { + return diag.FromErr(fmt.Errorf("Error setting updated_at: %s", err)) + } + if err = d.Set("state", getToolByIDResponse.State); err != nil { + return diag.FromErr(fmt.Errorf("Error setting state: %s", err)) + } + if err = d.Set("tool_id", getToolByIDResponse.ID); err != nil { + return diag.FromErr(fmt.Errorf("Error setting tool_id: %s", err)) + } + + return nil +} + +func resourceIBMCdToolchainToolDRAServiceBrokerUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + cdToolchainClient, err := meta.(conns.ClientSession).CdToolchainV2() + if err != nil { + return diag.FromErr(err) + } + + updateToolOptions := &cdtoolchainv2.UpdateToolOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return diag.FromErr(err) + } + + updateToolOptions.SetToolchainID(parts[0]) + updateToolOptions.SetToolID(parts[1]) + + hasChange := false + patchVals := &cdtoolchainv2.ToolchainToolPrototypePatch{} + + if d.HasChange("toolchain_id") { + return diag.FromErr(fmt.Errorf("Cannot update resource property \"%s\" with the ForceNew annotation."+ + " The resource must be re-created to update this property.", "toolchain_id")) + } + if d.HasChange("parameters") { + parameters := GetParametersForUpdate(d, ResourceIBMCdToolchainToolDRAServiceBroker(), nil) + patchVals.Parameters = parameters + hasChange = true + } + if d.HasChange("name") { + newName := d.Get("name").(string) + patchVals.Name = &newName + hasChange = true + } + + if hasChange { + updateToolOptions.ToolchainToolPrototypePatch, _ = patchVals.AsPatch() + _, response, err := cdToolchainClient.UpdateToolWithContext(context, updateToolOptions) + if err != nil { + log.Printf("[DEBUG] UpdateToolWithContext failed %s\n%s", err, response) + return diag.FromErr(fmt.Errorf("UpdateToolWithContext failed %s\n%s", err, response)) + } + } + + return resourceIBMCdToolchainToolDRAServiceBrokerRead(context, d, meta) +} + +func resourceIBMCdToolchainToolDRAServiceBrokerDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + cdToolchainClient, err := meta.(conns.ClientSession).CdToolchainV2() + if err != nil { + return diag.FromErr(err) + } + + deleteToolOptions := &cdtoolchainv2.DeleteToolOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return diag.FromErr(err) + } + + deleteToolOptions.SetToolchainID(parts[0]) + deleteToolOptions.SetToolID(parts[1]) + + response, err := cdToolchainClient.DeleteToolWithContext(context, deleteToolOptions) + if err != nil { + log.Printf("[DEBUG] DeleteToolWithContext failed %s\n%s", err, response) + return diag.FromErr(fmt.Errorf("DeleteToolWithContext failed %s\n%s", err, response)) + } + + d.SetId("") + + return nil +} + +func ResourceIBMCdToolchainToolDRAServiceBrokerToolReferentToMap(model *cdtoolchainv2.ToolModelReferent) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.UIHref != nil { + modelMap["ui_href"] = model.UIHref + } + if model.APIHref != nil { + modelMap["api_href"] = model.APIHref + } + return modelMap, nil +} + +//func ResourceIBMCdToolchainToolDRAServiceBrokerToolParametersToMap(model *cdtoolchainv2.DRAServiceBrokerParameters) (map[string]interface{}, error) { +// modelMap := make(map[string]interface{}) +// if model.DashboardURL != nil { +// modelMap["dashboard_url"] = model.DashboardURL +// } +// if model.BrokerID != nil { +// modelMap["broker_id"] = model.BrokerID +// } +// if model.APIKeyID != nil { +// modelMap["api_key_id"] = model.APIKeyID +// } +// if model.APIKeySecret != nil { +// modelMap["api_key_secret"] = model.APIKeySecret +// } +// return modelMap, nil +//} +// +//func ResourceIBMCdToolchainToolDRAServiceBrokerMapToToolParameters(modelMap map[string]interface{}) (*cdtoolchainv2.DRAServiceBrokerParameters, error) { +// model := &cdtoolchainv2.DRAServiceBrokerParameters{} +// if dashboardURL, ok := modelMap["dashboard_url"].(string); ok { +// model.DashboardURL = &dashboardURL +// } +// if brokerID, ok := modelMap["broker_id"].(string); ok { +// model.BrokerID = &brokerID +// } +// if apiKeyID, ok := modelMap["api_key_id"].(string); ok { +// model.APIKeyID = &apiKeyID +// } +// if apiKeySecret, ok := modelMap["api_key_secret"].(string); ok { +// model.APIKeySecret = &apiKeySecret +// } +// return model, nil +//} diff --git a/ibm/service/cdtoolchain/resource_ibm_cd_toolchain_tool_draservicebroker_test.go b/ibm/service/cdtoolchain/resource_ibm_cd_toolchain_tool_draservicebroker_test.go new file mode 100644 index 00000000000..dc96abdb18c --- /dev/null +++ b/ibm/service/cdtoolchain/resource_ibm_cd_toolchain_tool_draservicebroker_test.go @@ -0,0 +1,112 @@ +package cdtoolchain_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/continuous-delivery-go-sdk/cdtoolchainv2" +) + +func TestAccIBMCdToolchainToolDRAServiceBroker_Basic(t *testing.T) { + var conf cdtoolchainv2.GetToolByIDResponse + toolchainID := fmt.Sprintf("tf_toolchain_%d", acctest.RandIntRange(10, 100)) + toolName := fmt.Sprintf("tf_tool_%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckIBMCdToolchainToolDRAServiceBrokerDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMCdToolchainToolDRAServiceBrokerBasic(toolchainID, toolName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMCdToolchainToolDRAServiceBrokerExists("ibm_cd_toolchain_tool_draservicebroker.tool_draservicebroker", conf), + resource.TestCheckResourceAttr("ibm_cd_toolchain_tool_draservicebroker.tool_draservicebroker", "name", toolName), + ), + }, + }, + }) +} + +func testAccCheckIBMCdToolchainToolDRAServiceBrokerExists(n string, obj cdtoolchainv2.GetToolByIDResponse) resource.TestCheckFunc { + + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + cdToolchainClient, err := testAccProvider.Meta().(ClientSession).CdToolchainV2() + if err != nil { + return err + } + + getToolByIDOptions := &cdtoolchainv2.GetToolByIDOptions{} + + parts, err := flex.SepIdParts(rs.Primary.ID, "/") + if err != nil { + return err + } + + getToolByIDOptions.SetToolchainID(parts[0]) + getToolByIDOptions.SetToolID(parts[1]) + + getToolByIDResponse, _, err := cdToolchainClient.GetToolByIDWithContext(context.TODO(), getToolByIDOptions) + if err != nil { + return err + } + + obj = *getToolByIDResponse + return nil + } +} + +func testAccCheckIBMCdToolchainToolDRAServiceBrokerDestroy(s *terraform.State) error { + cdToolchainClient, err := testAccProvider.Meta().(ClientSession).CdToolchainV2() + if err != nil { + return err + } + for _, rs := range s.RootModule().Resources { + if rs.Type != "ibm_cd_toolchain_tool_draservicebroker" { + continue + } + + getToolByIDOptions := &cdtoolchainv2.GetToolByIDOptions{} + + parts, err := flex.SepIdParts(rs.Primary.ID, "/") + if err != nil { + return err + } + + getToolByIDOptions.SetToolchainID(parts[0]) + getToolByIDOptions.SetToolID(parts[1]) + + _, _, err = cdToolchainClient.GetToolByIDWithContext(context.TODO(), getToolByIDOptions) + if err == nil { + return fmt.Errorf("DRA service broker tool still exists: %s", rs.Primary.ID) + } + } + return nil +} + +func testAccCheckIBMCdToolchainToolDRAServiceBrokerBasic(toolchainID string, toolName string) string { + return fmt.Sprintf(` +resource "ibm_cd_toolchain_tool_draservicebroker" "tool_draservicebroker" { + toolchain_id = "%s" + name = "%s" + parameters { + dashboard_url = "https://draservicebroker.example.com/dashboard" + broker_id = "broker-id" + api_key_id = "api-key-id" + api_key_secret = "api-key-secret" + } +} +`, toolchainID, toolName) +}