Skip to content

Conversation

@SukkaW
Copy link
Contributor

@SukkaW SukkaW commented Apr 20, 2025

#3379

The PR is still WIP. The PR is now ready for review.

Also, I am not familiar with Go at all. All kinds of reviews are welcome.


Please create the GitHub label 'provider-VERCEL'

@SukkaW SukkaW marked this pull request as draft April 20, 2025 23:21
@SukkaW SukkaW force-pushed the vercel-provider branch 3 times, most recently from 3b730b1 to ca579b7 Compare November 20, 2025 18:47
@SukkaW
Copy link
Contributor Author

SukkaW commented Nov 20, 2025

Just an update, I have finished implementing the provider. I will create an intergration test case later.

Copy link
Contributor Author

@SukkaW SukkaW left a comment

Choose a reason for hiding this comment

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

So, Vercel has some automatically created records (like immutable NS, automatically created CAA records, etc.) that can not be deleted. How do I implement this?

Also, Vercel enforces a minimum TTL of 60, how do I incorporate that? Done in GetZoneRecordsCorrections.

@SukkaW SukkaW changed the title feat(#3379): implement Vercel DNS Provider VERCEL: implement Vercel DNS Provider (#3379) Nov 20, 2025
@tlimoncelli
Copy link
Collaborator

So, Vercel has some automatically created records (like immutable NS, automatically created CAA records, etc.) that can not be deleted. How do I implement this?

That's an interesting problem. Luckily we've seen this before.

It should be a simple matter of "pretend those records don't exist". GetZoneRecords() can skip over them rather than convert them (line 122 for _, r := range records {).

Then everything else should "just work" because you are using diff2.ByRecord() and future add/change/deletes will not affect the existing records.

Hope that helps!

Copy link
Collaborator

@tlimoncelli tlimoncelli left a comment

Choose a reason for hiding this comment

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

For someone "not familiar with Go at all" this is quite excellent! I only had a couple minor suggestions!

@SukkaW SukkaW requested a review from tlimoncelli November 21, 2025 09:59
@SukkaW
Copy link
Contributor Author

SukkaW commented Nov 21, 2025

That's an interesting problem. Luckily we've seen this before.

It should be a simple matter of "pretend those records don't exist". GetZoneRecords() can skip over them rather than convert them (line 122 for _, r := range records {).

Then everything else should "just work" because you are using diff2.ByRecord() and future add/change/deletes will not affect the existing records.

Hope that helps!

@tlimoncelli Thanks! I have implemented this in 8f017ea (#3542).

I do notice that when running the intergration tests, there is a CREATE dnscontrol-intergration.test NS ns1.vercel-dns.com. ttl=300. It appears that DNSControl is trying to update NS record at the apex (which the operation is not permitted by the Vercel API, and those apex NS records are not listed in the API response).

Maybe I should return nil, nil or []*models.Nameserver{}, nil in GetNameservers to prevent DNSControl from creating apex NS records at all? Update: done in 96ffaa5 (#3542)

@SukkaW
Copy link
Contributor Author

SukkaW commented Nov 21, 2025

Also, I noticed that the Vercel API has somewhat strict API rate limiting, something like 50 modifications/deletions per minute, 100 creations per minute, and 500 records retrieval per minute. That would be enough for small/personal domains (Vercel's DNS is not meant for serious deployment anyway), but how would I finish intergration tests though?

@tlimoncelli
Copy link
Collaborator

Also, I noticed that the Vercel API has somewhat strict API rate limiting, something like 50 modifications/deletions per minute, 100 creations per minute, and 500 records retrieval per minute. That would be enough for small/personal domains (Vercel's DNS is not meant for serious deployment anyway), but how would I finish intergration tests though?

That's an interesting problem.

In the short term, we can just run the integration tests a few at a time using the -start and -end flags. If the code fails at test 30, you can do the next group by running -start 30 -end 60, etc.

In the long term, we should detect the error that Vercel gives when we hit the limit, sleep, then try again. There are some modules that can help with that. Some providers code their own, others use github.com/failsafe-go/failsafe-go

@SukkaW
Copy link
Contributor Author

SukkaW commented Nov 21, 2025

That's an interesting problem.

In the short term, we can just run the integration tests a few at a time using the -start and -end flags. If the code fails at test 30, you can do the next group by running -start 30 -end 60, etc.

In the long term, we should detect the error that Vercel gives when we hit the limit, sleep, then try again. There are some modules that can help with that. Some providers code their own, others use github.com/failsafe-go/failsafe-go

I ended up skipping the pager test, as the preparation (creating 101 records) needs an hour, which is way too much. Vercel, in the end, is not a serious DNS provider, and I have already ensured that I have handled the pagination.

On the other hand, I copied and modified the rate limit implementation from Hetnezer's provider, as it behaves mostly the same as Vercel's API, and can easily be ported.

@tlimoncelli
Copy link
Collaborator

That's an interesting problem.
In the short term, we can just run the integration tests a few at a time using the -start and -end flags. If the code fails at test 30, you can do the next group by running -start 30 -end 60, etc.
In the long term, we should detect the error that Vercel gives when we hit the limit, sleep, then try again. There are some modules that can help with that. Some providers code their own, others use github.com/failsafe-go/failsafe-go

I ended up skipping the pager test, as the preparation (creating 101 records) needs an hour, which is way too much. Vercel, in the end, is not a serious DNS provider, and I have already ensured that I have handled the pagination.

On the other hand, I copied and modified the rate limit implementation from Hetnezer's provider, as it behaves mostly the same as Vercel's API, and can easily be ported.

Sounds good! (Many providers skip the "pager" tests for similar reasons)

Tom

@SukkaW
Copy link
Contributor Author

SukkaW commented Nov 22, 2025

@tlimoncelli

Currently, I am failing CAA:CAA_many_records integration test, but it is because Vercel doesn't believe CAA @ issue ; contains a valid FQDN. Which rejectif should I use here in my audit record?

Update: I implemented a custom rejectif for this. A unit test is also created.

@SukkaW SukkaW force-pushed the vercel-provider branch 2 times, most recently from c9ca0eb to 26c8aed Compare November 22, 2025 08:29
@SukkaW
Copy link
Contributor Author

SukkaW commented Nov 22, 2025

@tlimoncelli

Also, it turns out that vercel limits CAA with extra fields. They only allow cansignhttpexchanges and forbid validationmethods or accounturi. Most likely, it is a bug on their side, because their API throws:

invalid_value - Unexpected "cansignhttpexchanges" value.

I don't want to deal with this for now, so I have implemented a custom rejectif rejectifCaaTargetContainsUnsupportedFields, and I have written the unit test in auditrecords_test.go. I have also added a Vercel vendor-specific integration test case to validate that Vercel does accept cansignhttpexchanges.

Also, all integration tests are now passed on my machine locally.

@SukkaW SukkaW marked this pull request as ready for review November 22, 2025 10:12
@SukkaW
Copy link
Contributor Author

SukkaW commented Nov 22, 2025

The PR should be ready for review now. Thanks @tlimoncelli for the massive help!

Also, all integration tests are now passed on my machine locally.

Also, having been playing around with my provider with my production domain already, it works so far:

image image

retry, err := rl.handleResponse(resp)

if err != nil {
resp.Body.Close()

Choose a reason for hiding this comment

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

you could use defer resp.Body.Close() if suitable, optional suggestion.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did update to use defer, not sure if it is ok though. cc @tlimoncelli what do you think?

@SukkaW SukkaW requested a review from nekomeowww November 24, 2025 09:34
Copy link

@nekomeowww nekomeowww left a comment

Choose a reason for hiding this comment

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

Generally LGTM.

Copy link
Collaborator

@tlimoncelli tlimoncelli left a comment

Choose a reason for hiding this comment

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

Please run bin/generate.sh to fix the formatting of integrationTest/profiles.json.

@SukkaW
Copy link
Contributor Author

SukkaW commented Nov 24, 2025

Please run bin/generate.sh to fix the formatting of integrationTest/profiles.json.

Done in 6cf861a (#3542). cc @tlimoncelli

@SukkaW SukkaW requested a review from tlimoncelli November 24, 2025 16:11
@SukkaW SukkaW changed the title VERCEL: implement Vercel DNS Provider (#3379) VERCEL: Implement Vercel DNS Provider (#3379) Nov 24, 2025
@SukkaW
Copy link
Contributor Author

SukkaW commented Dec 1, 2025

@tlimoncelli Hi, I have just rebased my PR against the latest main branch and resolved all the conflicts.

@tlimoncelli
Copy link
Collaborator

Thank you for contributing this provider! I'll merge it shortly.

I'd love to have Vercel part of the automated testing that we do. If you can arrange for a test account, I'd gladly add it. Instructions are here: https://docs.dnscontrol.org/developer-info/byo-secrets#donate-secrets-to-the-project

@tlimoncelli tlimoncelli merged commit daf5a7a into StackExchange:main Dec 1, 2025
2 checks passed
@SukkaW
Copy link
Contributor Author

SukkaW commented Dec 2, 2025

Thank you for contributing this provider! I'll merge it shortly.

I'd love to have Vercel part of the automated testing that we do. If you can arrange for a test account, I'd gladly add it. Instructions are here: https://docs.dnscontrol.org/developer-info/byo-secrets#donate-secrets-to-the-project

Sure! I would like to create a new draft PR to see if the intergration tests pass from my forked repo first, and I can donate those credentials after that.

@SukkaW SukkaW deleted the vercel-provider branch December 2, 2025 08:54
@tlimoncelli
Copy link
Collaborator

Sure! I would like to create a new draft PR to see if the intergration tests pass from my forked repo first, and I can donate those credentials after that.

perfect!

tlimoncelli added a commit that referenced this pull request Dec 3, 2025
Made a few mistakes when creating the initial version of the docs back
in #3542

Fix typos, adjust a few wordings, descriptions, etc.

Co-authored-by: Tom Limoncelli <6293917+tlimoncelli@users.noreply.github.com>
@SukkaW SukkaW mentioned this pull request Dec 4, 2025
tlimoncelli pushed a commit that referenced this pull request Dec 4, 2025
The PR follows #3542

Found some bugs when running intergration tests locally again, and the
PR is an attempt to fix them:

- When updating/creating HTTPS/SRV records, Vercel API only reads from
the corresponding struct (either `srv` or `https`). If we provide a
`value`, the Vercel API will reject with an error.
- The PR makes `Value` "nil-able", and sets `Value` to nil when dealing
with `SRV` or `HTTPS` records.
- When updating a record, currently, we treat the empty SVC param as
omitting the field. But with Vercel's API, omitting a field means not
updating the field. We need to explicitly make the field an empty string
to create/update an empty SVC param, and the PR does that.
- Vercel implements an unknown `ech=` parameter validation process for
HTTPS records. The validation process is unknown, undocumented, thus I
can't implement a `rejectif` for `AuditRecord`.
- Let's make this a known caveat, describe it in the provider docs, skip
these intergration tests, and move on.

Please tag this PR w/ `provider-VERCEL`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants