Skip to content

Commit

Permalink
Merge pull request #121 from dikhan/feature/upgrade-example-configs-t…
Browse files Browse the repository at this point in the history
…o-0.12upgrade

Feature/upgrade example configs to 0.12upgrade
  • Loading branch information
dikhan committed May 31, 2019
2 parents 1161ea1 + e230c45 commit 48c0460
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 33 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ Additionally, the following documents provide deep insight regarding OpenAPI and

- [How to](docs/how_to.md) document contains information about how to define a swagger file following good practises that
make it work seamlessly with this terraform provider. Additionally, learn more about what is currently supported.
- [Migrating to Terraform 0.12](./docs/terraform_version_upgrades/upgrading_to_terraform_0.12.md). This document describes
how to update configuration created using Terraform v0.11 to v0.12.
- [FAQ](./docs/faq.md) document answers for the most frequently asked questions.

## Contributing
Expand Down
164 changes: 164 additions & 0 deletions docs/terraform_version_upgrades/upgrading_to_terraform_0.12.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
# Upgrading to Terraform 0.12

The best way to proceed here is to download the latest version of the OpenAPI Terraform provider plugin that has support for
the Terraform 0.12 SDK, at the time of writing it's v0.14.0.

## What if I already have infrastructure managed via Terraform using OpenAPI plugin version < v0.14.0

In that case, you should be able to upgrade the terraform binary to 0.12 and also the OpenAPI Terraform provider plugin (>=v0.14.0)

### What should I expect?

Once provisioned with the latest binary versions, run ```terraform plan``` on your configuration. One of the following
use cases will apply:

#### No brainier, your config is already compatible

The plan will show:

````
No changes. Infrastructure is up-to-date.
````

In this case you don't have to do anything else.

#### Your configuration is not compatible with Terraform 0.12.

Terraform will present you the different config that is not compatible. For instance:

````
$ terraform plan
Error: Unsupported argument
on main.tf line 60, in resource "swaggercodegen_cdn_v1" "my_cdn2":
60: array_of_objects_example = [
An argument named "array_of_objects_example" is not expected here. Did you
mean to define a block of type "array_of_objects_example"?
````

In the case above, Terraform is notifying us that there is a property that is not compatible with Terraform 0.12.

Luckily, Terraform 0.12 supports a new command that updates your current non compatible configuration into a compatible
Terraform 0.12 configuration. The command is called [0.12upgrade](https://www.terraform.io/docs/commands/0.12upgrade.html). Below
is an example of an output:

````
$ terraform 0.12upgrade
This command will rewrite the configuration files in the given directory so
that they use the new syntax features from Terraform v0.12, and will identify
any constructs that may need to be adjusted for correct operation with
Terraform v0.12.
We recommend using this command in a clean version control work tree, so that
you can easily see the proposed changes as a diff against the latest commit.
If you have uncommited changes already present, we recommend aborting this
command and dealing with them before running this command again.
Would you like to upgrade the module in the current directory?
Only 'yes' will be accepted to confirm.
Enter a value: yes
-----------------------------------------------------------------------------
Warning: Approximate migration of invalid block type assignment
on main.tf line 61, in resource "swaggercodegen_cdn_v1" "my_cdn2":
61: "${swaggercodegen_cdn_v1.my_cdn.array_of_objects_example[0]}",
In swaggercodegen_cdn_v1.my_cdn2 the name "array_of_objects_example" is a
nested block type, but this configuration is exploiting some missing
validation rules from Terraform v0.11 and prior to trick Terraform into
creating blocks dynamically.
This has been upgraded to use the new Terraform v0.12 dynamic blocks feature,
but since the upgrade tool cannot predict which map keys will be present a
fully-comprehensive set has been generated.
Warning: Approximate migration of invalid block type assignment
on main.tf line 62, in resource "swaggercodegen_cdn_v1" "my_cdn2":
62: "${swaggercodegen_cdn_v1.my_cdn.array_of_objects_example[1]}",
In swaggercodegen_cdn_v1.my_cdn2 the name "array_of_objects_example" is a
nested block type, but this configuration is exploiting some missing
validation rules from Terraform v0.11 and prior to trick Terraform into
creating blocks dynamically.
This has been upgraded to use the new Terraform v0.12 dynamic blocks feature,
but since the upgrade tool cannot predict which map keys will be present a
fully-comprehensive set has been generated.
-----------------------------------------------------------------------------
Upgrade complete!
The configuration files were upgraded successfully. Use your version control
system to review the proposed changes, make any necessary adjustments, and
then commit.
Some warnings were generated during the upgrade, as shown above. These
indicate situations where Terraform could not decide on an appropriate course
of action without further human input.
Where possible, these have also been marked with TF-UPGRADE-TODO comments to
mark the locations where a decision must be made. After reviewing and adjusting
these, manually remove the TF-UPGRADE-TODO comment before continuing.
````

After executing the above command, you should expect some changes in your terraform configuration file. In the case above,
these changes where related to how arrays ob objects are represented in Terraform 0.12. The snipped of code
updated can be seen below:

````
dynamic "array_of_objects_example" {
for_each = [swaggercodegen_cdn_v1.my_cdn.array_of_objects_example[0]]
content {
# TF-UPGRADE-TODO: The automatic upgrade tool can't predict
# which keys might be set in maps assigned here, so it has
# produced a comprehensive set here. Consider simplifying
# this after confirming which keys can be set in practice.
origin_port = lookup(array_of_objects_example.value, "origin_port", null)
protocol = lookup(array_of_objects_example.value, "protocol", null)
}
}
dynamic "array_of_objects_example" {
for_each = [swaggercodegen_cdn_v1.my_cdn.array_of_objects_example[1]]
content {
# TF-UPGRADE-TODO: The automatic upgrade tool can't predict
# which keys might be set in maps assigned here, so it has
# produced a comprehensive set here. Consider simplifying
# this after confirming which keys can be set in practice.
origin_port = lookup(array_of_objects_example.value, "origin_port", null)
protocol = lookup(array_of_objects_example.value, "protocol", null)
}
}
````

And Voilà! We now have a fully Terraform 0.12 configuration file. The expectation at this point, is that only the configuration
should have changed. Executing terraform plan should not see any diffs at all.

````
$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.
swaggercodegen_lbs_v1.my_lb: Refreshing state... [id=c438fc1b-a85a-48eb-afc6-2e6d719d3c82]
swaggercodegen_cdn_v1.my_cdn: Refreshing state... [id=403cd232-89cd-4586-9f22-1b37786e698f]
swaggercodegen_cdn_v1.my_cdn2: Refreshing state... [id=846c997b-ba02-4e1c-984c-e8ff465fa76b]
------------------------------------------------------------------------
No changes. Infrastructure is up-to-date.
This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, no
actions need to be performed.
````
85 changes: 52 additions & 33 deletions examples/swaggercodegen/main.tf
Original file line number Diff line number Diff line change
@@ -1,72 +1,91 @@
provider "swaggercodegen" {
## the example server is expecting the api key to have 'apiKeyValue' (it's hard coded)
## auth testing can be done by tweaking this value to be something else
apikey_auth = "${var.apikey_auth}"
apikey_auth = var.apikey_auth
x_request_id = "request header value for POST /v1/cdns"
}

resource "swaggercodegen_cdn_v1" "my_cdn" {
label = "label" ## This is an immutable property (refer to swagger file)
ips = ["127.0.0.1"] ## This is a force-new property (refer to swagger file)
label = "label" ## This is an immutable property (refer to swagger file)
ips = ["127.0.0.1"] ## This is a force-new property (refer to swagger file)
hostnames = ["origin.com"]

example_int = 25
example_int = 25
better_example_number_field_name = 15.78
example_boolean = true
example_boolean = true

optional_property = "optional_property value"
optional_computed = "optional_computed value"
optional_property = "optional_property value"
optional_computed = "optional_computed value"
optional_computed_with_default = "optional_computed_with_default value"

object_property = {
message = "some message news2"
message = "some message news2"
detailed_message = "some message news with details"
example_int = 11
example_number = 12.23
example_boolean = true
example_int = 11
example_number = 12.23
example_boolean = true
}

array_of_objects_example {
protocol = "http"
protocol = "http"
origin_port = 81
}

array_of_objects_example {
protocol = "http"
origin_port = 81
protocol = "https"
origin_port = 443
}
}

# This is an example on how to use interpolation for 'object' types like the object_property and be able to pass
# along to other resources property values from objects
resource "swaggercodegen_cdn_v1" "my_cdn2" {
label = "label" ## This is an immutable property (refer to swagger file)
ips = ["127.0.0.2"] ## This is a force-new property (refer to swagger file)
label = "label" ## This is an immutable property (refer to swagger file)
ips = ["127.0.0.2"] ## This is a force-new property (refer to swagger file)
hostnames = ["origin.com"]

example_int = "${swaggercodegen_cdn_v1.my_cdn.object_property.example_int}"
better_example_number_field_name = "${swaggercodegen_cdn_v1.my_cdn.object_property.example_number}"
example_boolean = "${swaggercodegen_cdn_v1.my_cdn.object_property.example_boolean}"
example_int = swaggercodegen_cdn_v1.my_cdn.object_property.example_int
better_example_number_field_name = swaggercodegen_cdn_v1.my_cdn.object_property.example_number
example_boolean = swaggercodegen_cdn_v1.my_cdn.object_property.example_boolean

object_property = {
message = "some message news2"
message = "some message news2"
detailed_message = "some message news with details"
example_int = "${swaggercodegen_cdn_v1.my_cdn.object_property.example_int}"
example_number = "${swaggercodegen_cdn_v1.my_cdn.object_property.example_number}"
example_boolean = "${swaggercodegen_cdn_v1.my_cdn.object_property.example_boolean}"
example_int = swaggercodegen_cdn_v1.my_cdn.object_property.example_int
example_number = swaggercodegen_cdn_v1.my_cdn.object_property.example_number
example_boolean = swaggercodegen_cdn_v1.my_cdn.object_property.example_boolean
}

# TODO: This needs to be fixed to match 0.12 new syntax
array_of_objects_example = [
"${swaggercodegen_cdn_v1.my_cdn.array_of_objects_example[0]}",
"${swaggercodegen_cdn_v1.my_cdn.array_of_objects_example[1]}",
]
}
dynamic "array_of_objects_example" {
for_each = [swaggercodegen_cdn_v1.my_cdn.array_of_objects_example[0]]
content {
# TF-UPGRADE-TODO: The automatic upgrade tool can't predict
# which keys might be set in maps assigned here, so it has
# produced a comprehensive set here. Consider simplifying
# this after confirming which keys can be set in practice.

origin_port = lookup(array_of_objects_example.value, "origin_port", null)
protocol = lookup(array_of_objects_example.value, "protocol", null)
}
}
dynamic "array_of_objects_example" {
for_each = [swaggercodegen_cdn_v1.my_cdn.array_of_objects_example[1]]
content {
# TF-UPGRADE-TODO: The automatic upgrade tool can't predict
# which keys might be set in maps assigned here, so it has
# produced a comprehensive set here. Consider simplifying
# this after confirming which keys can be set in practice.

origin_port = lookup(array_of_objects_example.value, "origin_port", null)
protocol = lookup(array_of_objects_example.value, "protocol", null)
}
}
}

resource "swaggercodegen_lbs_v1" "my_lb" {
name = "some_name"
backends = ["backend.com"]
time_to_process = 1 # the operation (post,update,delete) will take 15s in the API to complete
name = "some_name"
backends = ["backend.com"]
time_to_process = 1 # the operation (post,update,delete) will take 15s in the API to complete
simulate_failure = false # no failures wished now ;) (post,update,delete)
}
}

4 changes: 4 additions & 0 deletions examples/swaggercodegen/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

terraform {
required_version = ">= 0.12"
}

0 comments on commit 48c0460

Please sign in to comment.