Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate Whitelist for IBM-cloud-databases. Introduce allowlisting #3852

Merged
merged 20 commits into from
Nov 3, 2022

Conversation

omaraibrahim
Copy link
Collaborator

@omaraibrahim omaraibrahim commented Jun 17, 2022

In the api version 5 whitelist was deprecated and allowlist was introduced. In our strive for feature parity, in the following PR I deprecated whitelist and introduced allowlist.

This involved:

  • Deprecating whitelist in our data_source_ibm_database and introducing allowlist
  • Deprecating whitelist in our database resource and introducing allowlist
  • Updating tests

Community Note

  • Please vote on this pull request by adding a 👍 reaction to the original pull request comment to help the community and maintainers prioritize this request
  • Please do not leave "+1" or other comments that do not add relevant new information or questions, they generate extra noise for pull request followers and do not help prioritize the request

Relates OR Closes #0000

Output from acceptance testing:

$ make testacc TEST=./ibm/service/database TESTARGS='-run=TestAccIBMDatabaseDataSource_basic'
--- PASS: TestAccIBMDatabaseDataSource_basic (597.39s)
PASS
ok  	github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/database	598.703s
...
$ make testacc TEST=./ibm/service/database TESTARGS='-run=TestAccIBMEDBDatabaseInstanceBasic'
--- PASS: TestAccIBMEDBDatabaseInstanceBasic (1836.72s)
PASS
ok  	github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/database	1837.595s
$ make testacc TEST=./ibm/service/database TESTARGS='-run=TestAccIBMDatabaseInstancePostgresBasic'
--- PASS: TestAccIBMDatabaseInstancePostgresBasic (1493.88s)
PASS
ok  	github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/database	1494.758s
$ make testacc TEST=./ibm/service/database TESTARGS='-run=TestAccIBMDatabaseInstancePostgresAllowlistMigration'
--- PASS: TestAccIBMDatabaseInstancePostgresAllowlistMigration (665.06s)
PASS
ok      github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/database        668.257s

whitelist, err := icdClient.Whitelists().GetWhitelist(icdId)
if err != nil {
return fmt.Errorf("[ERROR] Error getting database whitelist: %s", err)
if _, ok := d.GetOk("whitelist"); ok {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whitelist and allowlist are computed variables you can't do d.GetOk...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we use cloud v5 API and flatten the result back to both whitelist and allowlist

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hkantare unfortunately we can't. Whitelist does not exist in v5 and was replaced by allowlist. So whitelist is using v4 while allowlist uses v5.
v5 API: https://cloud.ibm.com/apidocs/cloud-databases-api/cloud-databases-api-v5#getallowlist
v4 API: https://cloud.ibm.com/apidocs/cloud-databases-api/cloud-databases-api-v4#getwhitelist-permissions

Thank you for catching the previous mistake though! I really appreciate it!

Deprecated: "Whitelist is deprecated please use allowlist",
ConflictsWith: []string{"allowlist"},
},
"allowlist": {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we set the v5 API response of allowlist to whitelist (because the schema looks same for both) it just flatten and setting the same

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @hkantare!

They're two different apis endpoints, and despite them being very similar, I think it's safer to keep them separate. Whitelist is depreciated and will be removed soon as well. Hence, I think a separation of concerns is better. Here are the api docs for both. #3852 (comment)

Thanks!
Omar

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes ...v4/v5 API are two different endpoint with same model structure and functionality ...cant we just handle in the backend (i mean resource/datasource) to migrate to V5 AP's without any change to schema.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hkantare so the responses are the same yes :D But the supporting functionality is not. Meaning, the autogenerated allowlist functions utilize allowlist structs the use pointers. For example, https://github.com/IBM/cloud-databases-go-sdk/blob/de91b81e136fd4c53c0000e87932aaf150658a33/clouddatabasesv5/cloud_databases_v5.go#L1848

In contrast the whitelist functions utilizes a whitelist struct that does not use pointers. An example of the functions that consume structs that are shaped differently can be found here: https://github.com/IBM-Cloud/bluemix-go/blob/d538cb4fd9bece50f7b012496df63b3f62d58662/api/icd/icdv4/whitelist.go#L38

So despite achieving the same result, the code is structured very differently and the structs that allowlist relies on are different than whitelist. For example, AllowlistEntry is written as follows: https://github.com/IBM/cloud-databases-go-sdk/blob/de91b81e136fd4c53c0000e87932aaf150658a33/clouddatabasesv5/cloud_databases_v5.go#L2046
While WhitelistEntry is written as follows https://github.com/IBM-Cloud/bluemix-go/blob/d538cb4fd9bece50f7b012496df63b3f62d58662/api/icd/icdv4/whitelist.go#L13

My concern of just setting the v5 response of allowlist to whitelist is we'll have to do lots of downstream changes that will break things or cause unexpected bugs.

Copy link
Collaborator Author

@omaraibrahim omaraibrahim Sep 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I also tested the instances using import and it works :)

whitelist, err := icdClient.Whitelists().GetWhitelist(icdId)
if err != nil {
return diag.FromErr(fmt.Errorf("[ERROR] Error getting database whitelist: %s", err))
if _, ok := d.GetOk("whitelist"); ok {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Resource Read also don't use d.Get operations because the import functionality doesn't work

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @hkantare!

Thanks for taking a look at the PR. I really appreciate it! After spending a few days trying to incorporate this requested change, I am not convinced that it is a good idea. Removing the operation actually causes bugs as seen below:

test_working_directory=/var/folders/zl/1pk63bj95xx56m3vvm0yn35m0000gn/T/plugintest824757667
  error=
  | After applying this test step and performing a `terraform refresh`, the plan was not empty.
  | stdout
  | 
  | 
  | Terraform used the selected providers to generate the following execution
  | plan. Resource actions are indicated with the following symbols:
  |   ~ update in-place
  | 
  | Terraform will perform the following actions:
  | 
  |   # ibm_database.tf-edb-58 will be updated in-place
  |   ~ resource "ibm_database" "tf-edb-58" {
  |         id                           = "crn:v1:bluemix:public:databases-for-enterprisedb:eu-gb:a/40ddc34a953a8c02f10987b59085b60e:c1ff0800-8682-4b6b-a8b7-5fa8df912a31::"
  |         name                         = "tf-edb-58"
  |         tags                         = [
  |             "one:two",
  |         ]
  |         # (25 unchanged attributes hidden)
  | 
  | 
  | 
  | 
  | 
  |       - whitelist {
  |           - address     = "172.168.1.2/32" -> null
  |           - description = "desc1" -> null
  |         }
  |         # (4 unchanged blocks hidden)
  |     }
  | 
  | Plan: 0 to add, 1 to change, 0 to destroy.
  
    resource_ibm_database_edb_test.go:25: Step 1/4 error: After applying this test step and performing a `terraform refresh`, the plan was not empty.
        stdout
        
        
        Terraform used the selected providers to generate the following execution
        plan. Resource actions are indicated with the following symbols:
          ~ update in-place
        
        Terraform will perform the following actions:
        
          # ibm_database.tf-edb-58 will be updated in-place
          ~ resource "ibm_database" "tf-edb-58" {
                id                           = "crn:v1:bluemix:public:databases-for-enterprisedb:eu-gb:a/40ddc34a953a8c02f10987b59085b60e:c1ff0800-8682-4b6b-a8b7-5fa8df912a31::"
                name                         = "tf-edb-58"
                tags                         = [
                    "one:two",
                ]
                # (25 unchanged attributes hidden)
        
        
        
        
        
              - whitelist {
                  - address     = "172.168.1.2/32" -> null
                  - description = "desc1" -> null
                }
                # (4 unchanged blocks hidden)
            }
        
        Plan: 0 to add, 1 to change, 0 to destroy.

Here's my explanation as to why d.GetOK is actually vital:

  1. getOK does work in resource read (I've confirmed this). In general we use many operations associated with the resourceDataStructure throughout the function and this isn't any different really.
  2. By taking it away, we end up setting whitelist to a value. The reason begin is the api commands for allowlist and whitelist update the same source. We do not want to set our whitelist to anything if allowlist is used, and vice versa.
  3. By not doing the above we end up setting whitelist to some value. This value then gets updated to null down the line. This is bad and can cause unintended bugs like overwriting data.
  4. Also note, whitelist and allowlist are special cases where both apis do the same exact thing. This is highly unusual, but it is what it is.

Hence, the best was to approach this is the original way which is check if allowlist or whitelist is used. Then proceed to do the api calls depending on which one is used. Both can never be set at the same time due to the conflict code, and we’ve established that d.getOK does work perfectly fine.

Thanks!
Omar

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for explanation
getOK does work in resource read but it fails during the import scenario. Let say you have created a database outside Terraform and want to import and manage in future using Terraform. We need to import the resource. (https://learn.hashicorp.com/tutorials/terraform/state-import?in=terraform/state&utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS)
For import we first create a empty resource block
resource "ibm_database" "mydb" {
}
Run terraform import ibm_database.mydb
Import also calls the same resource read since the block is empty d.GetOk fails for both whitelist and allowlist

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hkantare thank you very very much for the explanation :D I've gone ahead and update the code so that if whitelist isn't there we always use allowlist. I follow the terraform docs here: https://www.terraform.io/plugin/sdkv2/best-practices/deprecations#renaming-an-optional-attribute

So if d.getOK("whitelist") fails we'll always use allowlist. lmk what you think :D

@hkantare hkantare force-pushed the master branch 2 times, most recently from e07c2f7 to 17b24e9 Compare July 21, 2022 06:34
@omaraibrahim omaraibrahim reopened this Sep 9, 2022
@hkantare
Copy link
Collaborator

@omaraibrahim Can you add a migration testcase from whitelist to allowlist

@omaraibrahim
Copy link
Collaborator Author

omaraibrahim commented Nov 2, 2022

@hkantare I've gone ahead and added migration tests. I've also modified the code to address some concerns and ensure a seemless migration to allowlist - while retaining full functionality for whitelist.

Migration tests can be found here:

func TestAccIBMDatabaseInstancePostgresGroupMigration(t *testing.T) {

@hkantare hkantare merged commit ccf0ae0 into IBM-Cloud:master Nov 3, 2022
hkantare pushed a commit that referenced this pull request Nov 8, 2022
…3852)

* works with local vendor changes.

* working using cloud databases v5 now

* updated deprecation message

* data_source_ibm_database and some tests

* modified the rest of the resource tests

* fixed calling d.getOK for computed variable

* potential import issue fix

* added migration test

* fixed migration bug

* fixed allowlist removal bug

* setting import state verify to false due to terraform bug

* removed extra logs

* updated docs
@omaraibrahim omaraibrahim mentioned this pull request Jul 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants