Skip to content

Commit

Permalink
HUAWEICLOUD: add metadata to control Intelligent Resolution (#3013)
Browse files Browse the repository at this point in the history
  • Loading branch information
huihuimoe committed Jun 18, 2024
1 parent ce07c76 commit 2d15884
Show file tree
Hide file tree
Showing 6 changed files with 226 additions and 49 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/pr_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ jobs:
GCLOUD_DOMAIN: ${{ vars.GCLOUD_DOMAIN }}
HEDNS_DOMAIN: ${{ vars.HEDNS_DOMAIN }}
HEXONET_DOMAIN: ${{ vars.HEXONET_DOMAIN }}
HUAWEICLOUD_DOMAIN: ${{ vars.HUAWEICLOUD_DOMAIN }}
NAMEDOTCOM_DOMAIN: ${{ vars.NAMEDOTCOM_DOMAIN }}
NS1_DOMAIN: ${{ vars.NS1_DOMAIN }}
POWERDNS_DOMAIN: ${{ vars.POWERDNS_DOMAIN }}
Expand Down Expand Up @@ -161,6 +162,10 @@ jobs:
HEXONET_PW: ${{ secrets.HEXONET_PW }}
HEXONET_UID: ${{ secrets.HEXONET_UID }}

HUAWEICLOUD_REGION: ${{ secrets.HUAWEICLOUD_REGION }}
HUAWEICLOUD_KEY_ID: ${{ secrets.HUAWEICLOUD_KEY_ID }}
HUAWEICLOUD_KEY: ${{ secrets.HUAWEICLOUD_KEY }}

NAMEDOTCOM_KEY: ${{ secrets.NAMEDOTCOM_KEY }}
NAMEDOTCOM_URL: ${{ secrets.NAMEDOTCOM_URL }}
NAMEDOTCOM_USER: ${{ secrets.NAMEDOTCOM_USER }}
Expand Down
36 changes: 31 additions & 5 deletions documentation/provider/huaweicloud.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,37 @@ Example:
{% endcode %}

## Metadata
This provider does not recognize any special metadata fields unique to Huawei Cloud DNS.
There are some record level metadata available for this provider:
* `hw_line` (Line ID, default "default_view") Refer to the [Intelligent Resolution](https://support.huaweicloud.com/intl/en-us/usermanual-dns/dns_usermanual_0041.html) for more information.
* Available Line ID refer to [Resolution Lines](https://support.huaweicloud.com/intl/en-us/api-dns/en-us_topic_0085546214.html). Custom Line ID can also be used.
* `hw_weight` (0-1000, default "1") Refer to the [Configuring Weighted Routing](https://support.huaweicloud.com/intl/en-us/usermanual-dns/dns_usermanual_0705.html) for more information.
* `hw_rrset_key` (default "") User defined key for RRset load balance. This value would be stored in the description field of the RRset.

The following example shows how to use the metadata:

{% code title="dnsconfig.js" %}
```javascript
var REG_NONE = NewRegistrar("none");
var DSP_HWCLOUD = NewDnsProvider("huaweicloud");

D("example.com", REG_NONE, DnsProvider(DSP_HWCLOUD),
// this example will create 4 rrsets with the same name "test"
A("test", "8.8.8.8"),
A("test", "8.8.4.4"),
A("test", "9.9.9.9", {hw_weight: "10"}), // Weighted Routing
A("test", "149.112.112.112", {hw_weight: "10"}), // Weighted Routing
A("test", "223.5.5.5", {hw_line: "CN"}), // GEODNS
A("test", "223.6.6.6", {hw_line: "CN", hw_weight: "10"}), // GEODNS with weight

// this example will create 3 rrsets with the same name "lb"
A("rr-lb", "10.0.0.1", {hw_weight: "10", hw_rrset_key: "lb-zone-a"}),
A("rr-lb", "10.0.0.2", {hw_weight: "10", hw_rrset_key: "lb-zone-a"}),
A("rr-lb", "10.0.1.1", {hw_weight: "10", hw_rrset_key: "lb-zone-b"}),
A("rr-lb", "10.0.1.2", {hw_weight: "10", hw_rrset_key: "lb-zone-b"}),
A("rr-lb", "10.0.2.2", {hw_weight: "0", hw_rrset_key: "lb-zone-c"}),
END);
```
{% endcode %}

## Usage
An example configuration:
Expand Down Expand Up @@ -71,7 +101,3 @@ If that doesn't work, log into Huaweicloud's website and open the [API Explorer]

## New domains
If a domain does not exist in your Huawei Cloud account, DNSControl will automatically add it with the `push` command.

## GeoDNS
Managing GeoDNS RRSet on Huawei Cloud (also called **Line** in Huawei Cloud DNS) is not supported in DNSControl.
If your Zone needs to use GeoDNS, please create it manually in the console and use [IGNORE](../language-reference/domain-modifiers/IGNORE.md) modifiers in DNSControl to prevent changing it.
14 changes: 7 additions & 7 deletions integrationTest/providers.json
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,13 @@
"authToken": "$HOSTINGDE_AUTHTOKEN",
"domain": "$HOSTINGDE_DOMAIN"
},
"HUAWEICLOUD": {
"TYPE": "HUAWEICLOUD",
"domain": "$HUAWEICLOUD_DOMAIN",
"Region": "$HUAWEICLOUD_REGION",
"KeyId": "$HUAWEICLOUD_KEY_ID",
"SecretKey": "$HUAWEICLOUD_KEY"
},
"INWX": {
"TYPE": "INWX",
"domain": "$INWX_DOMAIN",
Expand Down Expand Up @@ -288,12 +295,5 @@
"TYPE": "VULTR",
"domain": "$VULTR_DOMAIN",
"token": "$VULTR_TOKEN"
},
"HUAWEICLOUD": {
"TYPE": "HUAWEICLOUD",
"domain": "$HUAWEICLOUD_DOMAIN",
"Region": "$HUAWEICLOUD_REGION",
"KeyId": "$HUAWEICLOUD_KEY_ID",
"SecretKey": "$HUAWEICLOUD_KEY"
}
}
58 changes: 52 additions & 6 deletions providers/huaweicloud/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package huaweicloud
import (
"fmt"
"slices"
"strconv"

"github.com/StackExchange/dnscontrol/v4/models"
"github.com/StackExchange/dnscontrol/v4/pkg/printer"
Expand All @@ -15,16 +16,16 @@ func getRRSetIDFromRecords(rcs models.Records) []string {
if r.Original == nil {
continue
}
if r.Original.(*model.ListRecordSets).Id == nil {
if r.Original.(*model.ShowRecordSetByZoneResp).Id == nil {
printer.Warnf("RecordSet ID is nil for record %+v\n", r)
continue
}
ids = append(ids, *r.Original.(*model.ListRecordSets).Id)
ids = append(ids, *r.Original.(*model.ShowRecordSetByZoneResp).Id)
}
return slices.Compact(ids)
}

func nativeToRecords(n *model.ListRecordSets, zoneName string) (models.Records, error) {
func nativeToRecords(n *model.ShowRecordSetByZoneResp, zoneName string) (models.Records, error) {
if n.Name == nil || n.Type == nil || n.Records == nil || n.Ttl == nil {
return nil, fmt.Errorf("missing required fields in Huaweicloud's RRset: %+v", n)
}
Expand All @@ -37,26 +38,71 @@ func nativeToRecords(n *model.ListRecordSets, zoneName string) (models.Records,
rc := &models.RecordConfig{
TTL: uint32(*n.Ttl),
Original: n,
Metadata: map[string]string{},
}
rc.SetLabelFromFQDN(recName, zoneName)
if err := rc.PopulateFromString(recType, value, zoneName); err != nil {
return nil, fmt.Errorf("unparsable record received from Huaweicloud: %w", err)
}
if n.Line != nil {
rc.Metadata[metaLine] = *n.Line
}
if n.Weight != nil {
rc.Metadata[metaWeight] = fmt.Sprintf("%d", *n.Weight)
}
if n.Description != nil {
rc.Metadata[metaKey] = *n.Description
}
rcs = append(rcs, rc)
}

return rcs, nil
}

func recordsToNative(rcs models.Records, expectedKey models.RecordKey) *model.ListRecordSets {
func recordsToNative(rcs models.Records, expectedKey models.RecordKey) (*model.ShowRecordSetByZoneResp, error) {
// rcs length is guaranteed to be > 0
if len(rcs) == 0 {
return nil, fmt.Errorf("empty record set")
}
// line and weight should be the same for all records in the rrset
line := rcs[0].Metadata[metaLine]
weightStr := rcs[0].Metadata[metaWeight]
for _, r := range rcs {
if r.Metadata[metaLine] != line {
return nil, fmt.Errorf("all records in the rrset must have the same line %s", line)
}
if r.Metadata[metaWeight] != weightStr {
return nil, fmt.Errorf("all records in the rrset must have the same weight %s", weightStr)
}
}

// parse weight to int32
var weight *int32
if weightStr != "" {
weightInt, err := strconv.ParseInt(weightStr, 10, 32)
if err != nil {
return nil, fmt.Errorf("failed to parse weight %s to int32", weightStr)
}
weightInt32 := int32(weightInt)
// weight should be 0-1000
if weightInt32 < 0 || weightInt32 > 1000 {
return nil, fmt.Errorf("weight must be between 0 and 1000")
}
weight = &weightInt32
}

resultTTL := int32(0)
resultVal := []string{}
name := expectedKey.NameFQDN + "."
result := &model.ListRecordSets{
key := rcs[0].Metadata[metaKey]
result := &model.ShowRecordSetByZoneResp{
Name: &name,
Type: &expectedKey.Type,
Ttl: &resultTTL,
Records: &resultVal,
Line: &line,
Weight: weight,
Description: &key,
}

for _, r := range rcs {
Expand Down Expand Up @@ -84,5 +130,5 @@ func recordsToNative(rcs models.Records, expectedKey models.RecordKey) *model.Li
}
}

return result
return result, nil
}
16 changes: 16 additions & 0 deletions providers/huaweicloud/huaweicloudProvider.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,18 @@ import (

/*
Huaweicloud API DNS provider:
Info required in `creds.json`:
- KeyId
- SecretKey
- Region
Record level metadata available:
- hw_line (refer below Huawei Cloud DNS API documentation for available lines, default "default_view")
(https://support.huaweicloud.com/intl/en-us/api-dns/en-us_topic_0085546214.html)
- hw_weight (0-1000, default "1")
- hw_rrset_key (default "")
*/

type huaweicloudProvider struct {
Expand All @@ -33,6 +41,14 @@ type huaweicloudProvider struct {
region *region.Region
}

const (
metaWeight = "hw_weight"
metaLine = "hw_line"
metaKey = "hw_rrset_key"
defaultWeight = "1"
defaultLine = "default_view"
)

// newHuaweicloud creates the provider.
func newHuaweicloud(m map[string]string, metadata json.RawMessage) (providers.DNSServiceProvider, error) {
auth, err := basic.NewCredentialsBuilder().
Expand Down
Loading

0 comments on commit 2d15884

Please sign in to comment.