-
-
Notifications
You must be signed in to change notification settings - Fork 180
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
Feat/scaleway.com #899
base: master
Are you sure you want to change the base?
Feat/scaleway.com #899
Conversation
Regarding the change in the markdown tables: I use the VSCode formatter https://marketplace.visualstudio.com/items?itemName=fcrespo82.markdown-table-formatter Do you want me to reverse the markdown table back to the original state? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks 👍 !
Two important things are to remove the field_type and field_name, unless there is reason I'm not aware of 😉
README.md
Outdated
| Version | Readme link | Docs link | | ||
|---------|-----------------------------------------------------------------------|-----------------------------------------------------------------| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah let's revert this otherwise the git history is going to look all weird; Note you can open the vscode command palette and hit "save without formatting" 😉
I would however be okay with a separate PR to auto-format this + perhaps enforce this in the CI 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done 😄
I am happy to do this in a separate PR. I am not sure of a way to enforce this in CI, but I guess there must be a way.
docs/scaleway.md
Outdated
"domain": "munchkin-academia.eu", // corresponds to the `dns-zone` in the API documentation | ||
"secret_key": "<SECRET_KEY>", | ||
"ip_version": "ipv4", | ||
"ipv6_suffix": "", | ||
"field_type": "A", // optional, it will default to "A" | ||
"field_name": "www", // optional, it will default to "" (equivalent to "@") | ||
"ttl": 450 // optional, it will default to 3600 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move the comments to the sections below, otherwise it's invalid JSON and it will fail to parse it (people will forget to remove comments)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fair enough, changed - gonna push in a sec
- `"ip_version"` can be `"ipv4"` or `"ipv6"`. It defaults to `"ipv4"`. | ||
- `"ipv6_suffix"` is the suffix to append to the IPv6 address. It defaults to `""`. | ||
- `"field_type"` is the type of DNS record to update. It can be `"A"` or `"AAAA"`. It defaults to `"A"`. | ||
- `"field_name"` is the name of the DNS record to update. For example, it could be `"www"`, `"@"` or `"*"` for the wildcard. It defaults to to `""` (equivalent to `"@"`). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should not need this, it should be deducted from the "domain" field
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please help me out here. How should I extract this? The only way I can imagine is to count how many .
are in the domain string, and if there are two take the first part of the domain string before the first .
as name
(according to the scaleway API). Is that correct?
|
||
- `"ip_version"` can be `"ipv4"` or `"ipv6"`. It defaults to `"ipv4"`. | ||
- `"ipv6_suffix"` is the suffix to append to the IPv6 address. It defaults to `""`. | ||
- `"field_type"` is the type of DNS record to update. It can be `"A"` or `"AAAA"`. It defaults to `"A"`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should not need this, it should be deducted from the public IP address obtained and "ip_version"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uhm... again can you help me here? Do you have already a function that is able to distinguish between the two?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just found it in one of your comment below. Will change this in a moment!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
SecretKey string `json:"secret_key"` | ||
FieldType string `json:"field_type"` | ||
FieldName string `json:"field_name"` | ||
TTL int `json:"ttl"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to enforce it's positive and not too big:
TTL int `json:"ttl"` | |
TTL uint16 `json:"ttl"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good point! changed (also in the Provider strct)
requestBody := map[string]interface{}{ | ||
"changes": []map[string]interface{}{ | ||
{ | ||
"set": map[string]interface{}{ | ||
"id_fields": map[string]interface{}{ | ||
"name": p.field_name, | ||
"type": p.field_type, | ||
}, | ||
"records": []map[string]interface{}{ | ||
{ | ||
"data": ip.String(), | ||
"ttl": p.ttl, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
although this is a bit more concise, prefer using strongly typed structs:
requestBody := map[string]interface{}{ | |
"changes": []map[string]interface{}{ | |
{ | |
"set": map[string]interface{}{ | |
"id_fields": map[string]interface{}{ | |
"name": p.field_name, | |
"type": p.field_type, | |
}, | |
"records": []map[string]interface{}{ | |
{ | |
"data": ip.String(), | |
"ttl": p.ttl, | |
}, | |
}, | |
}, | |
}, | |
}, | |
} | |
type recordJSON struct { | |
Data string `json:"data"` | |
TTL uint16 `json:"ttl"` | |
} | |
type changeJSON struct{ | |
Set struct { | |
IDFields struct { | |
Name string `json:"name"` | |
Type string `json:"type"` | |
} `json:"id_fields"` | |
Records []recordJSON `json:"records"` | |
} `json:"set"` | |
} | |
var change changeJSON | |
change.Set.IDFields.Name = p.field_name | |
change.Set.IDFields.Type = p.field_type | |
change.Set.Records = []recordJSON{{ | |
Data: ip.String(), | |
TTL: p.ttl, | |
}} | |
requestBody := struct { | |
Changes []changeJSON `json:"changes"` | |
}{ | |
Changes: []changeJSON{change}, | |
} |
you could also define those types at global scope if you prefer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I trust you. It's the first time I write code in go... in fact I heavily relied on github copilot for it (even though eventually I had to check again all the code and fix it by myself).
Changed following your suggestion
requestBodyBytes, err := json.Marshal(requestBody) | ||
if err != nil { | ||
return netip.Addr{}, fmt.Errorf("json marshal: %w", err) | ||
} | ||
|
||
// Create the HTTP request | ||
request, err := http.NewRequestWithContext(ctx, http.MethodPatch, u.String(), bytes.NewReader(requestBodyBytes)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit You can encode directly to a buffer with - feel free to disregard since your code is actually shorter 😉
requestBodyBytes, err := json.Marshal(requestBody) | |
if err != nil { | |
return netip.Addr{}, fmt.Errorf("json marshal: %w", err) | |
} | |
// Create the HTTP request | |
request, err := http.NewRequestWithContext(ctx, http.MethodPatch, u.String(), bytes.NewReader(requestBodyBytes)) | |
buffer := bytes.NewBuffer(nil) | |
encoder := json.NewEncoder(buffer) | |
err = encoder.Encode(requestBody) | |
if err != nil { | |
return netip.Addr{}, fmt.Errorf("json encoding request body: %w", err) | |
} | |
request, err := http.NewRequestWithContext(ctx, http.MethodPatch, u.String(), buffer) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, I just trust you 100% on this.
Changed
} | ||
request.Header.Set("Content-Type", "application/json") | ||
request.Header.Set("Accept", "application/json") | ||
request.Header.Set("X-Auth-Token", p.secretKey) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit maybe you could add a function headers.SetXAuthToken since there is already SetXAuthPassword and SetXAuthUsername - feel free to disregard as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
request.Header.Set("Content-Type", "application/json") | ||
request.Header.Set("Accept", "application/json") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
request.Header.Set("Content-Type", "application/json") | |
request.Header.Set("Accept", "application/json") | |
headers.SetContentType(request, "application/json") | |
headers.SetAccept(request, "application/json") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
s, err := utils.ReadAndCleanBody(response.Body) | ||
if err != nil { | ||
return netip.Addr{}, fmt.Errorf("reading response: %w", err) | ||
} | ||
|
||
if response.StatusCode != http.StatusOK { | ||
return netip.Addr{}, fmt.Errorf("%w: %d: %s", | ||
errors.ErrHTTPStatusNotValid, response.StatusCode, utils.ToSingleLine(s)) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there any useful information in the body? if it's just for the error case, let's use instead:
s, err := utils.ReadAndCleanBody(response.Body) | |
if err != nil { | |
return netip.Addr{}, fmt.Errorf("reading response: %w", err) | |
} | |
if response.StatusCode != http.StatusOK { | |
return netip.Addr{}, fmt.Errorf("%w: %d: %s", | |
errors.ErrHTTPStatusNotValid, response.StatusCode, utils.ToSingleLine(s)) | |
} | |
if response.StatusCode != http.StatusOK { | |
return netip.Addr{}, fmt.Errorf("%w: %d: %s", | |
errors.ErrHTTPStatusNotValid, response.StatusCode, utils.BodyToSingleLine(response.Body)) | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the body looks something like
{
"records": [
{
"id": "aa051759-72e6-4034-8af5-dafba3eebb79",
"data": "127.1.2.3",
"name": "",
"priority": 0,
"ttl": 300,
"type": "A",
"comment": null
}
]
}
I think there is nothing useful, let me know if you disagree. Otherwise I will apply your change.
Hi @qdm12 , any chance for a second round of review? |
Solves issue #660