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

LoadBalancer Rules support #1016

Merged
merged 3 commits into from
Apr 14, 2021

Conversation

tpolich
Copy link

@tpolich tpolich commented Apr 8, 2021

Support for new LoadBalancing Rules feature (currently in beta)

@Nmishin
Copy link
Contributor

Nmishin commented Apr 8, 2021

Hi, @tpolich I found a strange behavior with 'session_affinity_ttl' - when I don't set it at all, it should be '<nil>' but It converts to "0" somehow and I always have one more Override rule with 'session_affinity_ttl' = "0".

From apply logs I see:
2021-04-08T18:33:27.443+0300 [DEBUG] plugin.terraform-provider-cloudflare_v2.19.2: 2021/04/08 18:33:27 [INFO] Creating Cloudflare Load Balancer from struct: {ID: CreatedOn:<nil> ModifiedOn:<nil> Description:test_load_balancer Name:test_lb1 TTL:0 FallbackPool:8c09a534a46a02134f6ae65a9e8af7cc DefaultPools:[8c09a534a46a02134f6ae65a9e8af8cc] RegionPools:map[] PopPools:map[] Proxied:true Enabled:0xc0003c5058 Persistence:none PersistenceTTL:82800 SessionAffinityAttributes:<nil> Rules:[0xc0000d2790] SteeringPolicy:}

(yes, I built your change with version v2.19.2 for testing purpose)

Also, plan logs shows me nothing:

          + rules {
          + condition  = "dns.qry.type == 28"
          + disabled   = false
          + name       = "test rule 1"
          + priority   = (known after apply)
          + terminates = false

          + overrides_tf {
              + default_pools   = (known after apply)
              + steering_policy = (known after apply)
            }
        }

but

2021-04-08T18:33:27.444+0300 [DEBUG] plugin.terraform-provider-cloudflare_v2.19.2:   {
2021-04-08T18:33:27.444+0300 [DEBUG] plugin.terraform-provider-cloudflare_v2.19.2:    "name": "test rule 1",
2021-04-08T18:33:27.444+0300 [DEBUG] plugin.terraform-provider-cloudflare_v2.19.2:    "priority": 0,
2021-04-08T18:33:27.444+0300 [DEBUG] plugin.terraform-provider-cloudflare_v2.19.2:    "disabled": false,
2021-04-08T18:33:27.444+0300 [DEBUG] plugin.terraform-provider-cloudflare_v2.19.2:    "condition": "dns.qry.type == 28",
2021-04-08T18:33:27.444+0300 [DEBUG] plugin.terraform-provider-cloudflare_v2.19.2:    "overrides": {
2021-04-08T18:33:27.444+0300 [DEBUG] plugin.terraform-provider-cloudflare_v2.19.2:     "session_affinity_ttl": 0,
2021-04-08T18:33:27.444+0300 [DEBUG] plugin.terraform-provider-cloudflare_v2.19.2:     "default_pools": [
2021-04-08T18:33:27.444+0300 [DEBUG] plugin.terraform-provider-cloudflare_v2.19.2:      "8c09a534a46a02134f6ae65a9e8af8cc"
2021-04-08T18:33:27.444+0300 [DEBUG] plugin.terraform-provider-cloudflare_v2.19.2:     ]
2021-04-08T18:33:27.444+0300 [DEBUG] plugin.terraform-provider-cloudflare_v2.19.2:    }
2021-04-08T18:33:27.444+0300 [DEBUG] plugin.terraform-provider-cloudflare_v2.19.2:   }
2021-04-08T18:33:27.444+0300 [DEBUG] plugin.terraform-provider-cloudflare_v2.19.2:  ]```


@tpolich
Copy link
Author

tpolich commented Apr 8, 2021

Ahh thank you @Nmishin yeah that is not the correct behavior let me see about fixing that

@tpolich tpolich force-pushed the lb-rules-terraform-support branch from 4734196 to 52da873 Compare April 8, 2021 20:05
Type: schema.TypeInt,
Optional: true,
Computed: true,
Default: nil,
Copy link
Member

Choose a reason for hiding this comment

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

are these Defaults all necessary? this one in particular might be problematic as the zero value for int is 0, notnil.

"condition": {
Type: schema.TypeString,
Optional: true,
Default: "",
Copy link
Member

Choose a reason for hiding this comment

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

we don't need to be explicit about empty strings here; it will also throw off d.GetOkExists checks if we use them as we're setting a value.

Suggested change
Default: "",

Default: false,
},

"overrides_tf": {
Copy link
Member

Choose a reason for hiding this comment

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

any reason for naming this differently to the API response? not having a 1:1 mapping with the API will make more work in the cf-terraforming tool.

"steering_policy": {
Type: schema.TypeString,
Optional: true,
Default: nil,
Copy link
Member

Choose a reason for hiding this comment

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

again, you probably don't want a nil here given that you're expecting a string and you already have a validator defined.

Type: schema.TypeString,
Optional: true,
Default: nil,
ValidateFunc: validation.StringLenBetween(1, 32),
Copy link
Member

Choose a reason for hiding this comment

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

i'm not sure i'd bother with validating this is an ID but if you do, you would want it to be validation.StringLenBetween(32, 32) otherwise "abcd1234" will be valid anyway.

if err != nil {
return fmt.Errorf("failed to flatten rules: %s", err)
}
if err := d.Set("rules", fr); err != nil {
Copy link
Member

Choose a reason for hiding this comment

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

✅ nice check! ensuring the complex type can't fail to write out

Comment on lines 620 to 628
bb, err := json.Marshal(rules)
if err != nil {
return nil, err
}

var rout []interface{}
if err := json.Unmarshal(bb, &rout); err != nil {
return nil, err
}
Copy link
Member

Choose a reason for hiding this comment

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

i don't quite understand why we are marshaling and unmarshaling here; can't we just iterate over the rules and add them to the return value? similar to something like https://github.com/cloudflare/terraform-provider-cloudflare/blob/master/cloudflare/resource_cloudflare_api_token.go#L179 or another existing resource?

@@ -434,6 +611,158 @@ func resourceCloudflareLoadBalancerImport(d *schema.ResourceData, meta interface
return []*schema.ResourceData{d}, nil
}

func flattenRules(rules []*cloudflare.LoadBalancerRule) (interface{}, error) {

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change

return nil, err
}

// terraform doesn't support maps of maps so lets
Copy link
Member

Choose a reason for hiding this comment

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

generally, if you want a map of maps, you probably really want a list of maps instead 😃

}

func expandRules(rdata interface{}) ([]*cloudflare.LoadBalancerRule, error) {

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change

Copy link
Member

@jacobbednarz jacobbednarz left a comment

Choose a reason for hiding this comment

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

Thanks for putting this together @tpolich 🙇‍♂️ It's appreciated!

I have some inline comments mainly targetting the schema as there are some conditions (such as Default and Computed) which I think we may be using unnecessarily and will cause problems later down the track with things like d.GetOkExists and checking whether or not a value has been set by the operator.

The other concern I raised was around the schema attribute naming. Ideally, this is a 1:1 mapping to the API response to avoid any manual mapping in tools like cf-terraforming however we have at least one that violates this and I can't quite see why we'd need to be doing that from what we have. Perhaps I'm missing some context?

I didn't run the tests yet as I'll save those for after we discuss any changes just in case something changes following those 😃

@tpolich tpolich force-pushed the lb-rules-terraform-support branch 2 times, most recently from 20d8dc1 to 8261ce5 Compare April 8, 2021 23:21
@tpolich tpolich force-pushed the lb-rules-terraform-support branch from 8261ce5 to d4f5a96 Compare April 9, 2021 00:08
@jacobbednarz
Copy link
Member

integration CI is also happy

=== RUN   TestAccCloudflareLoadBalancerMonitor_Import
=== PAUSE TestAccCloudflareLoadBalancerMonitor_Import
=== RUN   TestAccCloudflareLoadBalancerPool_Import
=== PAUSE TestAccCloudflareLoadBalancerPool_Import
=== RUN   TestAccCloudflareLoadBalancer_Import
=== PAUSE TestAccCloudflareLoadBalancer_Import
=== RUN   TestAccCloudflareLoadBalancerMonitor_Basic
=== PAUSE TestAccCloudflareLoadBalancerMonitor_Basic
=== RUN   TestAccCloudflareLoadBalancerMonitor_FullySpecified
=== PAUSE TestAccCloudflareLoadBalancerMonitor_FullySpecified
=== RUN   TestAccCloudflareLoadBalancerMonitor_EmptyExpectedBody
=== PAUSE TestAccCloudflareLoadBalancerMonitor_EmptyExpectedBody
=== RUN   TestAccCloudflareLoadBalancerMonitor_TcpFullySpecified
=== PAUSE TestAccCloudflareLoadBalancerMonitor_TcpFullySpecified
=== RUN   TestAccCloudflareLoadBalancerMonitor_NoRequired
=== PAUSE TestAccCloudflareLoadBalancerMonitor_NoRequired
=== RUN   TestAccCloudflareLoadBalancerMonitor_Update
=== PAUSE TestAccCloudflareLoadBalancerMonitor_Update
=== RUN   TestAccCloudflareLoadBalancerMonitor_CreateAfterManualDestroy
=== PAUSE TestAccCloudflareLoadBalancerMonitor_CreateAfterManualDestroy
=== RUN   TestAccCloudflareLoadBalancerPool_Basic
=== PAUSE TestAccCloudflareLoadBalancerPool_Basic
=== RUN   TestAccCloudflareLoadBalancerPool_FullySpecified
=== PAUSE TestAccCloudflareLoadBalancerPool_FullySpecified
=== RUN   TestAccCloudflareLoadBalancerPool_CreateAfterManualDestroy
=== PAUSE TestAccCloudflareLoadBalancerPool_CreateAfterManualDestroy
=== RUN   TestAccCloudflareLoadBalancer_Basic
=== PAUSE TestAccCloudflareLoadBalancer_Basic
=== RUN   TestAccCloudflareLoadBalancer_SessionAffinity
=== PAUSE TestAccCloudflareLoadBalancer_SessionAffinity
=== RUN   TestAccCloudflareLoadBalancer_GeoBalanced
=== PAUSE TestAccCloudflareLoadBalancer_GeoBalanced
=== RUN   TestAccCloudflareLoadBalancer_Rules
=== PAUSE TestAccCloudflareLoadBalancer_Rules
=== RUN   TestAccCloudflareLoadBalancer_DuplicatePool
=== PAUSE TestAccCloudflareLoadBalancer_DuplicatePool
=== RUN   TestAccCloudflareLoadBalancer_Update
=== PAUSE TestAccCloudflareLoadBalancer_Update
=== RUN   TestAccCloudflareLoadBalancer_CreateAfterManualDestroy
=== PAUSE TestAccCloudflareLoadBalancer_CreateAfterManualDestroy
=== CONT  TestAccCloudflareLoadBalancerMonitor_Import
--- PASS: TestAccCloudflareLoadBalancerMonitor_Import (4.47s)
=== CONT  TestAccCloudflareLoadBalancerPool_FullySpecified
--- PASS: TestAccCloudflareLoadBalancerPool_FullySpecified (4.94s)
=== CONT  TestAccCloudflareLoadBalancer_CreateAfterManualDestroy
--- PASS: TestAccCloudflareLoadBalancer_CreateAfterManualDestroy (18.90s)
=== CONT  TestAccCloudflareLoadBalancer_SessionAffinity
--- PASS: TestAccCloudflareLoadBalancer_SessionAffinity (17.60s)
=== CONT  TestAccCloudflareLoadBalancer_Basic
--- PASS: TestAccCloudflareLoadBalancer_Basic (7.65s)
=== CONT  TestAccCloudflareLoadBalancerPool_CreateAfterManualDestroy
--- PASS: TestAccCloudflareLoadBalancerPool_CreateAfterManualDestroy (8.00s)
=== CONT  TestAccCloudflareLoadBalancer_DuplicatePool
--- PASS: TestAccCloudflareLoadBalancer_DuplicatePool (2.95s)
=== CONT  TestAccCloudflareLoadBalancer_Update
--- PASS: TestAccCloudflareLoadBalancer_Update (10.55s)
=== CONT  TestAccCloudflareLoadBalancerMonitor_TcpFullySpecified
--- PASS: TestAccCloudflareLoadBalancerMonitor_TcpFullySpecified (3.70s)
=== CONT  TestAccCloudflareLoadBalancerPool_Basic
--- PASS: TestAccCloudflareLoadBalancerPool_Basic (3.90s)
=== CONT  TestAccCloudflareLoadBalancerMonitor_CreateAfterManualDestroy
--- PASS: TestAccCloudflareLoadBalancerMonitor_CreateAfterManualDestroy (6.85s)
=== CONT  TestAccCloudflareLoadBalancerMonitor_Update
--- PASS: TestAccCloudflareLoadBalancerMonitor_Update (6.55s)
=== CONT  TestAccCloudflareLoadBalancerMonitor_NoRequired
--- PASS: TestAccCloudflareLoadBalancerMonitor_NoRequired (0.06s)
=== CONT  TestAccCloudflareLoadBalancer_GeoBalanced
--- PASS: TestAccCloudflareLoadBalancer_GeoBalanced (6.79s)
=== CONT  TestAccCloudflareLoadBalancer_Rules
--- PASS: TestAccCloudflareLoadBalancer_Rules (6.95s)
=== CONT  TestAccCloudflareLoadBalancerMonitor_Basic
--- PASS: TestAccCloudflareLoadBalancerMonitor_Basic (4.60s)
=== CONT  TestAccCloudflareLoadBalancer_Import
--- PASS: TestAccCloudflareLoadBalancer_Import (6.96s)
=== CONT  TestAccCloudflareLoadBalancerMonitor_EmptyExpectedBody
--- PASS: TestAccCloudflareLoadBalancerMonitor_EmptyExpectedBody (3.54s)
=== CONT  TestAccCloudflareLoadBalancerMonitor_FullySpecified
--- PASS: TestAccCloudflareLoadBalancerMonitor_FullySpecified (3.80s)
=== CONT  TestAccCloudflareLoadBalancerPool_Import
--- PASS: TestAccCloudflareLoadBalancerPool_Import (4.30s)
PASS
ok  	github.com/cloudflare/terraform-provider-cloudflare/cloudflare	133.531s
?   	github.com/cloudflare/terraform-provider-cloudflare/version	[no test files]

@Nmishin
Copy link
Contributor

Nmishin commented Apr 9, 2021

@tpolich, @jacobbednarz guys, one more question - for rule only one field "name" marked as "Required: true" but this is not true, we must have overrides or terminate as well:
Error: error creating load balancer for zone: HTTP status 400: rule "test rule 1": must contain overrides or terminate: validation failed (1002)

Do we want to add logic for checking this scenario?

@jacobbednarz
Copy link
Member

jacobbednarz commented Apr 9, 2021 via email

@casertap
Copy link

@tpolich you are a legend, thank you! @jacobbednarz do you have an idea of when this can be released, please?

@jacobbednarz
Copy link
Member

@casertap @tpolich is still working on the documentation so once that is ready, we can merge. It will be released within our usual monthly-ish release cycle.

Copy link
Member

@jacobbednarz jacobbednarz left a comment

Choose a reason for hiding this comment

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

awesome @tpolich! i'm happy to 🚢 when you are.

@tpolich
Copy link
Author

tpolich commented Apr 14, 2021

awesome @tpolich! i'm happy to 🚢 when you are.

Awesome lets merge it then! Thank you for fixing the doc issue for me too you've been a really big help.

@jacobbednarz jacobbednarz merged commit d16d548 into cloudflare:master Apr 14, 2021
@jacobbednarz
Copy link
Member

congrats! this looks great ⭐

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.

4 participants