diff --git a/docs/resources/telephony_providers_edges_site_outbound_route.md b/docs/resources/telephony_providers_edges_site_outbound_route.md index e0cc26eeb..1043fa043 100644 --- a/docs/resources/telephony_providers_edges_site_outbound_route.md +++ b/docs/resources/telephony_providers_edges_site_outbound_route.md @@ -11,9 +11,36 @@ Outbound Routes for a Genesys Cloud Site ## API Usage The following Genesys Cloud APIs are used by this resource. Ensure your OAuth Client has been granted the necessary scopes and permissions to perform these operations: -**No APIs** +* [GET /api/v2/telephony/providers/edges/sites](https://developer.genesys.cloud/api/rest/v2/telephonyprovidersedge/#get-api-v2-telephony-providers-edges-sites) +* [GET /api/v2/telephony/providers/edges/sites/{siteId}/outboundroutes](https://developer.genesys.cloud/api/rest/v2/telephonyprovidersedge/#get-api-v2-telephony-providers-edges-sites--siteId--outboundroutes) +* [POST /api/v2/telephony/providers/edges/sites/{siteId}/outboundroutes](https://developer.genesys.cloud/api/rest/v2/telephonyprovidersedge/#post-api-v2-telephony-providers-edges-sites--siteId--outboundroutes) +* [DELETE /api/v2/telephony/providers/edges/sites/{siteId}/outboundroutes/{outboundRouteId}](https://developer.genesys.cloud/api/rest/v2/telephonyprovidersedge/#delete-api-v2-telephony-providers-edges-sites--siteId--outboundroutes--outboundRouteId-) +* [PUT /api/v2/telephony/providers/edges/sites/{siteId}/outboundroutes/{outboundRouteId}](https://developer.genesys.cloud/api/rest/v2/telephonyprovidersedge/#put-api-v2-telephony-providers-edges-sites--siteId--outboundroutes--outboundRouteId-) +## Example Usage +```terraform +// To enable this resource, set ENABLE_STANDALONE_OUTBOUND_ROUTES as an environment variable +resource "genesyscloud_telephony_providers_edges_site_outbound_routes" "site1-routes" { + site_id = genesyscloud_telephony_providers_edges_site.site1.id + outbound_routes { + name = "outboundRoute 1" + description = "outboundRoute description" + classification_types = ["International", "National"] + external_trunk_base_ids = [genesyscloud_telephony_providers_edges_trunkbasesettings.trunk-base-settings1.id] + distribution = "RANDOM" + enabled = false + } + outbound_routes { + name = "outboundRoute 2" + description = "outboundRoute description" + classification_types = ["Network"] + external_trunk_base_ids = [genesyscloud_telephony_providers_edges_trunkbasesettings.trunk-base-settings2.id] + distribution = "SEQUENTIAL" + enabled = true + } +} +``` ## Schema diff --git a/examples/resources/genesyscloud_telephony_providers_edges_site_outbound_routes/apis.md b/examples/resources/genesyscloud_telephony_providers_edges_site_outbound_route/apis.md similarity index 100% rename from examples/resources/genesyscloud_telephony_providers_edges_site_outbound_routes/apis.md rename to examples/resources/genesyscloud_telephony_providers_edges_site_outbound_route/apis.md diff --git a/examples/resources/genesyscloud_telephony_providers_edges_site_outbound_routes/resource.tf b/examples/resources/genesyscloud_telephony_providers_edges_site_outbound_route/resource.tf similarity index 100% rename from examples/resources/genesyscloud_telephony_providers_edges_site_outbound_routes/resource.tf rename to examples/resources/genesyscloud_telephony_providers_edges_site_outbound_route/resource.tf diff --git a/genesyscloud/telephony_providers_edges_site/resource_genesyscloud_telephony_providers_edges_site.go b/genesyscloud/telephony_providers_edges_site/resource_genesyscloud_telephony_providers_edges_site.go index 42db344bf..521e5f289 100644 --- a/genesyscloud/telephony_providers_edges_site/resource_genesyscloud_telephony_providers_edges_site.go +++ b/genesyscloud/telephony_providers_edges_site/resource_genesyscloud_telephony_providers_edges_site.go @@ -23,7 +23,7 @@ import ( "github.com/mypurecloud/platform-client-sdk-go/v129/platformclientv2" ) -func getSites(ctx context.Context, sdkConfig *platformclientv2.Configuration) (resourceExporter.ResourceIDMetaMap, diag.Diagnostics) { +func getAllSites(ctx context.Context, sdkConfig *platformclientv2.Configuration) (resourceExporter.ResourceIDMetaMap, diag.Diagnostics) { resources := make(resourceExporter.ResourceIDMetaMap) sp := GetSiteProxy(sdkConfig) @@ -115,7 +115,7 @@ func createSite(ctx context.Context, d *schema.ResourceData, meta interface{}) d diagErr = util.WithRetries(ctx, 60*time.Second, func() *retry.RetryError { diagErr = updateSiteOutboundRoutes(ctx, sp, d) if diagErr != nil { - return retry.RetryableError(fmt.Errorf(fmt.Sprintf("%v", diagErr), d.Id())) + return retry.RetryableError(util.BuildWithRetriesApiDiagnosticError(resourceName, fmt.Sprintf("failed to create site %s | error: %v", d.Id(), diagErr), nil)) } return nil }) diff --git a/genesyscloud/telephony_providers_edges_site/resource_genesyscloud_telephony_providers_edges_site_schema.go b/genesyscloud/telephony_providers_edges_site/resource_genesyscloud_telephony_providers_edges_site_schema.go index 8c0bf6b8c..750df7937 100644 --- a/genesyscloud/telephony_providers_edges_site/resource_genesyscloud_telephony_providers_edges_site_schema.go +++ b/genesyscloud/telephony_providers_edges_site/resource_genesyscloud_telephony_providers_edges_site_schema.go @@ -249,7 +249,7 @@ func ResourceSite() *schema.Resource { Computed: true, ConfigMode: schema.SchemaConfigModeAttr, Elem: outboundRouteSchema, - Deprecated: fmt.Sprintf("The outbound routes property is deprecated in %s, please use independent outbound routes resource instead", resourceName), + Deprecated: fmt.Sprintf("The outbound routes property is deprecated in %s, please use independent outbound routes resource instead, genesyscloud_telephony_providers_edges_site_outbound_route", resourceName), }, "primary_sites": { Description: `Used for primary phone edge assignment on physical edges only. List of primary sites the phones can be assigned to. If no primary_sites are defined, the site id for this site will be used as the primary site id.`, @@ -279,7 +279,7 @@ func ResourceSite() *schema.Resource { // SiteExporter returns the resourceExporter object used to hold the genesyscloud_telephony_providers_edges_site exporter's config func SiteExporter() *resourceExporter.ResourceExporter { return &resourceExporter.ResourceExporter{ - GetResourcesFunc: provider.GetAllWithPooledClient(getSites), + GetResourcesFunc: provider.GetAllWithPooledClient(getAllSites), RefAttrs: map[string]*resourceExporter.RefAttrSettings{ "location_id": {RefType: "genesyscloud_location"}, "outbound_routes.external_trunk_base_ids": {RefType: "genesyscloud_telephony_providers_edges_trunkbasesettings"}, diff --git a/genesyscloud/telephony_providers_edges_site/resource_genesyscloud_telephony_providers_edges_site_test.go b/genesyscloud/telephony_providers_edges_site/resource_genesyscloud_telephony_providers_edges_site_test.go index 51fbfc810..e9dbaae83 100644 --- a/genesyscloud/telephony_providers_edges_site/resource_genesyscloud_telephony_providers_edges_site_test.go +++ b/genesyscloud/telephony_providers_edges_site/resource_genesyscloud_telephony_providers_edges_site_test.go @@ -3,10 +3,12 @@ package telephony_providers_edges_site import ( "fmt" "log" + "os" "strconv" "strings" "terraform-provider-genesyscloud/genesyscloud/provider" "terraform-provider-genesyscloud/genesyscloud/util" + featureToggles "terraform-provider-genesyscloud/genesyscloud/util/feature_toggles" "testing" "time" @@ -21,6 +23,7 @@ import ( func TestAccResourceSite(t *testing.T) { t.Parallel() + var ( // site siteRes = "site" @@ -355,7 +358,14 @@ func TestAccResourceSiteNumberPlans(t *testing.T) { } func TestAccResourceSiteOutboundRoutes(t *testing.T) { - t.Skipf("outbound routes are being deprecated for this resource and moved to independent resource") + if exists := featureToggles.OutboundRoutesToggleExists(); exists { + // Unset outbound routes feature toggle so outbound routes will be managed by the site resource for this test + err := os.Unsetenv(featureToggles.OutboundRoutesToggleName()) + if err != nil { + t.Skipf("%v is set and unable to unset, skipping test", featureToggles.OutboundRoutesToggleName()) + } + } + t.Parallel() var ( // site diff --git a/genesyscloud/telephony_providers_edges_site_outbound_route/resource_genesyscloud_telephony_providers_edges_site_outbound_route.go b/genesyscloud/telephony_providers_edges_site_outbound_route/resource_genesyscloud_telephony_providers_edges_site_outbound_route.go index 2b83c7d02..43dd677d8 100644 --- a/genesyscloud/telephony_providers_edges_site_outbound_route/resource_genesyscloud_telephony_providers_edges_site_outbound_route.go +++ b/genesyscloud/telephony_providers_edges_site_outbound_route/resource_genesyscloud_telephony_providers_edges_site_outbound_route.go @@ -19,7 +19,7 @@ import ( "time" ) -func getSitesOutboundRoutes(ctx context.Context, sdkConfig *platformclientv2.Configuration) (resourceExporter.ResourceIDMetaMap, diag.Diagnostics) { +func getAllSitesOutboundRoutes(ctx context.Context, sdkConfig *platformclientv2.Configuration) (resourceExporter.ResourceIDMetaMap, diag.Diagnostics) { if exists := featureToggles.OutboundRoutesToggleExists(); !exists { return nil, util.BuildDiagnosticError(resourceName, fmt.Sprintf("Environment variable %s not set", featureToggles.OutboundRoutesToggleName()), fmt.Errorf("environment variable %s not set", featureToggles.OutboundRoutesToggleName())) } @@ -136,59 +136,66 @@ func updateSiteOutboundRoutes(ctx context.Context, d *schema.ResourceData, meta sdkConfig := meta.(*provider.ProviderMeta).ClientConfig proxy := getSiteOutboundRouteProxy(sdkConfig) - outboundRoutes := buildOutboundRoutes(d.Get("outbound_routes").(*schema.Set)) - // Get the current outbound routes outboundRoutesAPI, resp, err := proxy.getSiteOutboundRoutes(ctx, d.Id()) if err != nil { return util.BuildAPIDiagnosticError(resourceName, fmt.Sprintf("Failed to get outbound routes for site %s error: %s", d.Id(), err), resp) } + createRoutes, updateRoutes, deleteRoutes := splitRoutes(buildOutboundRoutes(d.Get("outbound_routes").(*schema.Set)), outboundRoutesAPI) + // Delete unwanted outbound routes first to free up classifications assigned to them - for _, outboundRouteFromAPI := range *outboundRoutesAPI { - // Delete route if no reference to it - if _, ok := nameInOutboundRoutes(*outboundRouteFromAPI.Name, *outboundRoutes); !ok { - resp, err := proxy.deleteSiteOutboundRoute(ctx, d.Id(), *outboundRouteFromAPI.Id) - if err != nil { - if util.IsStatus404(resp) { - return nil - } - return util.BuildAPIDiagnosticError(resourceName, fmt.Sprintf("Failed to delete outbound route from site %s error: %s", d.Id(), err), resp) + for _, route := range deleteRoutes { + resp, err := proxy.deleteSiteOutboundRoute(ctx, d.Id(), *route.Id) + if err != nil { + if util.IsStatus404(resp) { + return nil } + return util.BuildAPIDiagnosticError(resourceName, fmt.Sprintf("Failed to delete outbound route from site %s error: %s", d.Id(), err), resp) } } time.Sleep(2 * time.Second) - // Update the outbound routes - for _, outboundRoute := range *outboundRoutes { - if outboundRouteUpdate, ok := nameInOutboundRoutes(*outboundRoute.Name, *outboundRoutesAPI); ok { - // Update the outbound route - outboundRouteUpdate.Name = outboundRoute.Name - outboundRouteUpdate.Description = outboundRoute.Description - outboundRouteUpdate.ClassificationTypes = outboundRoute.ClassificationTypes - outboundRouteUpdate.Enabled = outboundRoute.Enabled - outboundRouteUpdate.Distribution = outboundRoute.Distribution - outboundRouteUpdate.ExternalTrunkBases = outboundRoute.ExternalTrunkBases - - _, resp, err := proxy.updateSiteOutboundRoute(ctx, d.Id(), *outboundRouteUpdate.Id, outboundRouteUpdate) - if err != nil { - return util.BuildAPIDiagnosticError(resourceName, fmt.Sprintf("Failed to update outbound route with id %s for site %s error: %s", *outboundRouteUpdate.Id, d.Id(), err), resp) - } - } else { - // Add the outbound route if not already present - _, resp, err := proxy.createSiteOutboundRoute(ctx, d.Id(), &outboundRoute) - if err != nil { - return util.BuildAPIDiagnosticError(resourceName, fmt.Sprintf("Failed to add outbound route to site %s error: %s", d.Id(), err), resp) - } + for _, route := range createRoutes { + _, resp, err := proxy.createSiteOutboundRoute(ctx, d.Id(), &route) + if err != nil { + return util.BuildAPIDiagnosticError(resourceName, fmt.Sprintf("Failed to add outbound route to site %s error: %s", d.Id(), err), resp) } } + time.Sleep(2 * time.Second) + for _, route := range updateRoutes { + _, resp, err := proxy.updateSiteOutboundRoute(ctx, d.Id(), *route.Id, &route) + if err != nil { + return util.BuildAPIDiagnosticError(resourceName, fmt.Sprintf("Failed to update outbound route with id %s for site %s error: %s", *route.Id, d.Id(), err), resp) + } + } // Wait for the update before reading time.Sleep(5 * time.Second) return readSiteOutboundRoutes(ctx, d, meta) } +// splitRoutes will take a list of exists routes and a new list of routes and decide what routes need to be created, updated and deleted +func splitRoutes(definedRoutes, apiRoutes *[]platformclientv2.Outboundroutebase) (createRoutes, updateRoutes, deleteRoutes []platformclientv2.Outboundroutebase) { + for _, apiRoute := range *apiRoutes { + if _, present := nameInOutboundRoutes(*apiRoute.Name, *definedRoutes); !present { + deleteRoutes = append(deleteRoutes, apiRoute) + } + } + + for _, definedRoute := range *definedRoutes { + if apiRoute, present := nameInOutboundRoutes(*definedRoute.Name, *apiRoutes); present { + definedRoute.Id = apiRoute.Id + updateRoutes = append(updateRoutes, definedRoute) + } else { + createRoutes = append(createRoutes, definedRoute) + } + } + + return createRoutes, updateRoutes, deleteRoutes +} + func deleteSiteOutboundRoutes(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { sdkConfig := meta.(*provider.ProviderMeta).ClientConfig proxy := getSiteOutboundRouteProxy(sdkConfig) diff --git a/genesyscloud/telephony_providers_edges_site_outbound_route/resource_genesyscloud_telephony_providers_edges_site_outbound_route_schema.go b/genesyscloud/telephony_providers_edges_site_outbound_route/resource_genesyscloud_telephony_providers_edges_site_outbound_route_schema.go index fa7703af9..0e424c08c 100644 --- a/genesyscloud/telephony_providers_edges_site_outbound_route/resource_genesyscloud_telephony_providers_edges_site_outbound_route_schema.go +++ b/genesyscloud/telephony_providers_edges_site_outbound_route/resource_genesyscloud_telephony_providers_edges_site_outbound_route_schema.go @@ -102,7 +102,7 @@ func ResourceSiteOutboundRoute() *schema.Resource { // SiteExporterOutboundRoute returns the resourceExporter object used to hold the genesyscloud_telephony_providers_edges_site_outbound_route exporter's config func SiteExporterOutboundRoute() *resourceExporter.ResourceExporter { return &resourceExporter.ResourceExporter{ - GetResourcesFunc: provider.GetAllWithPooledClient(getSitesOutboundRoutes), + GetResourcesFunc: provider.GetAllWithPooledClient(getAllSitesOutboundRoutes), RefAttrs: map[string]*resourceExporter.RefAttrSettings{ "site_id": {RefType: "genesyscloud_telephony_providers_edges_site"}, "outbound_routes.external_trunk_base_ids": {RefType: "genesyscloud_telephony_providers_edges_trunkbasesettings"}, diff --git a/genesyscloud/telephony_providers_edges_site_outbound_route/resource_genesyscloud_telephony_providers_edges_site_outbound_route_test.go b/genesyscloud/telephony_providers_edges_site_outbound_route/resource_genesyscloud_telephony_providers_edges_site_outbound_route_test.go index 9c867c823..a110231d8 100644 --- a/genesyscloud/telephony_providers_edges_site_outbound_route/resource_genesyscloud_telephony_providers_edges_site_outbound_route_test.go +++ b/genesyscloud/telephony_providers_edges_site_outbound_route/resource_genesyscloud_telephony_providers_edges_site_outbound_route_test.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/google/uuid" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "log" "os" "strconv" "strings" @@ -17,7 +18,13 @@ import ( ) func TestAccResourceSiteOutboundRoutes(t *testing.T) { - t.Parallel() + defer func() { + err := os.Unsetenv(featureToggles.OutboundRoutesToggleName()) + if err != nil { + log.Printf("%s", err) + } + }() + err := os.Setenv(featureToggles.OutboundRoutesToggleName(), "enabled") if err != nil { t.Errorf("%s is not set", featureToggles.OutboundRoutesToggleName())