Skip to content

Commit

Permalink
Deprecate multi-region support on resource name level
Browse files Browse the repository at this point in the history
This feature was introduced in early days of the provider to support multi-region. However,
this model was not compatible with Terraform modules since the region was attached to the resource name.
Later, multiregion support was added on the provider level as expected by Terraform enabling
the provider to be used in modules and enabling users to specify the regions on the provider level.

The multi-region support on the resource name level has been still supported till now but it's time
to say goodbye to features that had some value in the past but now don't make sense and makes the code
more difficult to read and maintain.
  • Loading branch information
dikhan committed Oct 29, 2021
1 parent 1e6a832 commit 07fcfcc
Show file tree
Hide file tree
Showing 7 changed files with 12 additions and 698 deletions.
56 changes: 0 additions & 56 deletions docs/how_to.md
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,6 @@ Extension Name | Type | Description
[x-terraform-resource-poll-enabled](#xTerraformResourcePollEnabled) | bool | Only supported in operation responses (e,g: 202). Defines that if the API responds with the given HTTP Status code (e,g: 202), the polling mechanism will be enabled. This allows the OpenAPI Terraform provider to perform read calls to the remote API and check the resource state. The polling mechanism finalises if the remote resource state arrives at completion, failure state or times-out (60s)
[x-terraform-resource-name](#xTerraformResourceName) | string | Only supported in resource root level. Defines the name that will be used for the resource in the Terraform configuration. If the extension is not preset, default value will be the name of the resource in the path. For instance, a path such as /v1/users will translate into a terraform resource name users_v1
[x-terraform-resource-host](#xTerraformResourceHost) | string | Only supported in resource root's POST operation. Defines the host that should be used when managing this specific resource. The value of this extension effectively overrides the global host configuration, making the OpenAPI Terraform provider client make thje API calls against the host specified in this extension value instead of the global host configuration. The protocols (HTTP/HTTPS) and base path (if anything other than "/") used when performing the API calls will still come from the global configuration.
[x-terraform-resource-regions-%s](#xTerraformResourceRegions) | string | Only supported in the root level. Defines the regions supported by a given resource identified by the %s variable. This extension only works if the ```x-terraform-resource-host``` extension contains a value that is parametrized and identifies the matching ```x-terraform-resource-regions-%s``` extension. The values of this extension must be comma separated strings.
###### <a name="xTerraformExcludeResource">x-terraform-exclude-resource</a>
Expand Down Expand Up @@ -793,61 +792,6 @@ the overridden host instead, in this case ```cdn.api.otherdomain.com```.
*Note: This extension is only supported at the operation's POST operation level. The other operations available for the
resource such as GET/PUT/DELETE will used the overridden host value too.*
###### <a name="xTerraformResourceRegions">Multi-region resources</a>
Additionally, if the resource is using multi region domains, meaning there's one sub-domain for each region where the resource
can be created into (similar to how aws resources are created per region), this can be configured as follows:
````
swagger: "2.0"
host: "some.domain.com"
x-terraform-resource-regions-cdn: "dub1,sea1"
paths:
/v1/cdns:
post:
x-terraform-resource-host: cdn.${cdn}.api.otherdomain.com
````
If the ``x-terraform-resource-host`` extension has a value parameterised in the form where the following pattern ```${identifier}```
is found (identifier being any string with no whitspaces - spaces,tabs, line breaks, etc) AND there is a matching
extension 'x-terraform-resource-regions-**identifier**' defined in the root level that refers to the same identifier
then the resource will be considered multi region.
For instance, in the above example, the ```x-terraform-resource-host``` value is parameterised as the ```${identifier}``` pattern
is found, and the identifier in this case is ```cdn```. Moreover, there is a matching ```x-terraform-resource-regions-cdn```
extension containing a list of regions where this resource can be created in.
The regions found in the ```x-terraform-resource-regions-cdn``` will be used as follows:
- The OpenAPI Terraform provider will expose one resource per region enlisted in the extension. In the case above, the
following resources will become available in the Terraform configuration (the provider name chosen here is 'swaggercodegen'):
````
resource "swaggercodegen_cdn_v1_dub1" "my_cdn" {
label = "label"
ips = ["127.0.0.1"]
hostnames = ["origin.com"]
}
resource "swaggercodegen_cdn_v1_sea1" "my_cdn" {
label = "label"
ips = ["127.0.0.1"]
hostnames = ["origin.com"]
}
````
As shown above, the resources that are multi-region will have extra information in their name that identifies the region
where tha resource should be managed.
- The OpenAPI Terraform provider client will make the API call against the specific resource region when the resource
is configured with multi-region support.
- As far as the resource configuration is concerned, the swagger configuration remains the same for that specific resource
(parameters, operations, polling support, etc) and the same configuration will be applicable to all the regions that resource
supports.
*Note: This extension is only supported at the root level and can be used exclusively along with the 'x-terraform-resource-host'
extension*
#### <a name="swaggerDefinitions">Definitions</a>
- **Field Name:** definitions
Expand Down
57 changes: 0 additions & 57 deletions examples/swaggercodegen/api/resources/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@ security:
x-terraform-provider-multiregion-fqdn: "some.api.${region}.nonexistingrandomdomain.io" # Making it a bit more random to avoid resolving to an actual existing domain
x-terraform-provider-regions: "rst1,dub1"

# This is legacy configuration that will be deprecated soon
x-terraform-resource-regions-monitor: "rst1,dub1"

paths:
/swagger.json:
get:
Expand Down Expand Up @@ -334,60 +331,6 @@ paths:
404:
$ref: "#/responses/NotFound"


############################
##### Monitors Multiregion Resource name based ####
############################

# The monitor resource is not implemented in the backed, it only serves as an example on how the global host can be overridden
# and how the resource can be configured with multi region setup

/v1/monitors:
post:
tags:
- "monitor"
summary: "Create monitor v1"
operationId: "CreateMonitorV1"
x-terraform-resource-host: "some.api.${monitor}.nonexistingrandomdomain.io" # Making it a bit more random to avoid resolving to an actual existing domain
parameters:
- in: "body"
name: "body"
description: "Monitor v1 payload object to be posted as part of the POST request"
required: true
schema:
$ref: "#/definitions/MonitorV1"
responses:
200:
description: "this operation is asynchronous, to check the status of the deployment call GET operation and check the status field returned in the payload"
schema:
$ref: "#/definitions/MonitorV1"
default:
description: "generic error response"
schema:
$ref: "#/definitions/Error"
/v1/monitors/{id}:
get:
tags:
- "monitor"
summary: "Get monitor by id"
description: ""
operationId: "GetMonitorV1"
parameters:
- name: "id"
in: "path"
description: "The monitor v1 id that needs to be fetched."
required: true
type: "string"
responses:
200:
description: "successful operation"
schema:
$ref: "#/definitions/MonitorV1"
400:
description: "Invalid monitor id supplied"
404:
description: "Monitor not found"

############################
##### Monitors MultiRegion Resource ####
############################
Expand Down
27 changes: 3 additions & 24 deletions openapi/openapi_v2_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@ const extTfResourceURL = "x-terraform-resource-host"

// SpecV2Resource defines a struct that implements the SpecResource interface and it's based on OpenAPI v2 specification
type SpecV2Resource struct {
Name string
Region string
Name string
// Path contains the full relative path to the resource e,g: /v1/resource
Path string
// SpecSchemaDefinition definition represents the representational state (aka model) of the resource
Expand Down Expand Up @@ -100,13 +99,12 @@ type SpecV2Resource struct {

// newSpecV2Resource creates a SpecV2Resource with no region and default host
func newSpecV2Resource(path string, schemaDefinition spec.Schema, rootPathItem, instancePathItem spec.PathItem, schemaDefinitions map[string]spec.Schema, paths map[string]spec.PathItem) (*SpecV2Resource, error) {
return newSpecV2ResourceWithConfig("", path, schemaDefinition, rootPathItem, instancePathItem, schemaDefinitions, paths)
return newSpecV2ResourceWithConfig(path, schemaDefinition, rootPathItem, instancePathItem, schemaDefinitions, paths)
}

func newSpecV2DataSource(path string, schemaDefinition spec.Schema, rootPathItem spec.PathItem, paths map[string]spec.PathItem) (*SpecV2Resource, error) {
resource := &SpecV2Resource{
Path: path,
Region: "",
SchemaDefinition: schemaDefinition,
RootPathItem: rootPathItem,
InstancePathItem: spec.PathItem{},
Expand All @@ -121,15 +119,7 @@ func newSpecV2DataSource(path string, schemaDefinition spec.Schema, rootPathItem
return resource, nil
}

// newSpecV2ResourceWithRegion creates a SpecV2Resource with the region configured making the returned SpecV2Resource region based.
func newSpecV2ResourceWithRegion(region, path string, schemaDefinition spec.Schema, rootPathItem, instancePathItem spec.PathItem, schemaDefinitions map[string]spec.Schema, paths map[string]spec.PathItem) (*SpecV2Resource, error) {
if region == "" {
return nil, fmt.Errorf("region must not be empty")
}
return newSpecV2ResourceWithConfig(region, path, schemaDefinition, rootPathItem, instancePathItem, schemaDefinitions, paths)
}

func newSpecV2ResourceWithConfig(region, path string, schemaDefinition spec.Schema, rootPathItem, instancePathItem spec.PathItem, schemaDefinitions map[string]spec.Schema, paths map[string]spec.PathItem) (*SpecV2Resource, error) {
func newSpecV2ResourceWithConfig(path string, schemaDefinition spec.Schema, rootPathItem, instancePathItem spec.PathItem, schemaDefinitions map[string]spec.Schema, paths map[string]spec.PathItem) (*SpecV2Resource, error) {
if path == "" {
return nil, fmt.Errorf("path must not be empty")
}
Expand All @@ -138,7 +128,6 @@ func newSpecV2ResourceWithConfig(region, path string, schemaDefinition spec.Sche
}
resource := &SpecV2Resource{
Path: path,
Region: region,
SchemaDefinition: schemaDefinition,
RootPathItem: rootPathItem,
InstancePathItem: instancePathItem,
Expand All @@ -155,9 +144,6 @@ func newSpecV2ResourceWithConfig(region, path string, schemaDefinition spec.Sche

// GetResourceName returns the resource name including the region at the end of the resource name if applicable
func (o *SpecV2Resource) GetResourceName() string {
if o.Region != "" {
return fmt.Sprintf("%s_%s", o.Name, o.Region)
}
return o.Name
}

Expand Down Expand Up @@ -262,13 +248,6 @@ func (o *SpecV2Resource) getHost() (string, error) {
if overrideHost == "" {
return "", nil
}
multiRegionHost, err := openapiutils.GetMultiRegionHost(overrideHost, o.Region)
if err != nil {
return "", err
}
if multiRegionHost != "" {
return multiRegionHost, nil
}
return overrideHost, nil
}

Expand Down
Loading

0 comments on commit 07fcfcc

Please sign in to comment.