Платформа ЦРНП "Мирокод" для разработки проектов
https://git.mirocod.ru
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
5.2 KiB
129 lines
5.2 KiB
// Package libdns defines core interfaces that should be implemented by DNS |
|
// provider clients. They are small and idiomatic Go interfaces with |
|
// well-defined semantics. |
|
// |
|
// Records are described independently of any particular zone, a convention |
|
// that grants Record structs portability across zones. As such, record names |
|
// are partially qualified, i.e. relative to the zone. For example, an A |
|
// record called "sub" in zone "example.com." represents a fully-qualified |
|
// domain name (FQDN) of "sub.example.com.". Implementations should expect |
|
// that input records conform to this standard, while also ensuring that |
|
// output records do; adjustments to record names may need to be made before |
|
// or after provider API calls, for example, to maintain consistency with |
|
// all other libdns provider implementations. Helper functions are available |
|
// in this package to convert between relative and absolute names. |
|
// |
|
// Although zone names are a required input, libdns does not coerce any |
|
// particular representation of DNS zones; only records. Since zone name and |
|
// records are separate inputs in libdns interfaces, it is up to the caller |
|
// to pair a zone's name with its records in a way that works for them. |
|
// |
|
// All interface implementations must be safe for concurrent/parallel use. |
|
// For example, if AppendRecords() is called at the same time and two API |
|
// requests are made to the provider at the same time, the result of both |
|
// requests must be visible after they both complete; if the provider does |
|
// not synchronize the writing of the zone file and one request overwrites |
|
// the other, then the client implementation must take care to synchronize |
|
// on behalf of the incompetent provider. This synchronization need not be |
|
// global; for example: the scope of synchronization might only need to be |
|
// within the same zone, allowing multiple requests at once as long as all |
|
// of them are for different zones. (Exact logic depends on the provider.) |
|
package libdns |
|
|
|
import ( |
|
"context" |
|
"strings" |
|
"time" |
|
) |
|
|
|
// RecordGetter can get records from a DNS zone. |
|
type RecordGetter interface { |
|
// GetRecords returns all the records in the DNS zone. |
|
// |
|
// Implementations must honor context cancellation and be safe for |
|
// concurrent use. |
|
GetRecords(ctx context.Context, zone string) ([]Record, error) |
|
} |
|
|
|
// RecordAppender can non-destructively add new records to a DNS zone. |
|
type RecordAppender interface { |
|
// AppendRecords creates the requested records in the given zone |
|
// and returns the populated records that were created. It never |
|
// changes existing records. |
|
// |
|
// Implementations must honor context cancellation and be safe for |
|
// concurrent use. |
|
AppendRecords(ctx context.Context, zone string, recs []Record) ([]Record, error) |
|
} |
|
|
|
// RecordSetter can set new or update existing records in a DNS zone. |
|
type RecordSetter interface { |
|
// SetRecords updates the zone so that the records described in the |
|
// input are reflected in the output. It may create or overwrite |
|
// records or -- depending on the record type -- delete records to |
|
// maintain parity with the input. No other records are affected. |
|
// It returns the records which were set. |
|
// |
|
// Records that have an ID associating it with a particular resource |
|
// on the provider will be directly replaced. If no ID is given, this |
|
// method may use what information is given to do lookups and will |
|
// ensure that only necessary changes are made to the zone. |
|
// |
|
// Implementations must honor context cancellation and be safe for |
|
// concurrent use. |
|
SetRecords(ctx context.Context, zone string, recs []Record) ([]Record, error) |
|
} |
|
|
|
// RecordDeleter can delete records from a DNS zone. |
|
type RecordDeleter interface { |
|
// DeleteRecords deletes the given records from the zone if they exist. |
|
// It returns the records that were deleted. |
|
// |
|
// Records that have an ID to associate it with a particular resource on |
|
// the provider will be directly deleted. If no ID is given, this method |
|
// may use what information is given to do lookups and delete only |
|
// matching records. |
|
// |
|
// Implementations must honor context cancellation and be safe for |
|
// concurrent use. |
|
DeleteRecords(ctx context.Context, zone string, recs []Record) ([]Record, error) |
|
} |
|
|
|
// Record is a generalized representation of a DNS record. |
|
type Record struct { |
|
// provider-specific metadata |
|
ID string |
|
|
|
// general record fields |
|
Type string |
|
Name string // partially-qualified (relative to zone) |
|
Value string |
|
TTL time.Duration |
|
|
|
// type-dependent record fields |
|
Priority int // used by MX, SRV, and URI records |
|
} |
|
|
|
// RelativeName makes fqdn relative to zone. For example, for a FQDN of |
|
// "sub.example.com" and a zone of "example.com", it outputs "sub". |
|
// |
|
// If fqdn cannot be expressed relative to zone, the input fqdn is returned. |
|
func RelativeName(fqdn, zone string) string { |
|
return strings.TrimSuffix(strings.TrimSuffix(fqdn, zone), ".") |
|
} |
|
|
|
// AbsoluteName makes name into a fully-qualified domain name (FQDN) by |
|
// prepending it to zone and tidying up the dots. For example, an input |
|
// of name "sub" and zone "example.com." will return "sub.example.com.". |
|
func AbsoluteName(name, zone string) string { |
|
if zone == "" { |
|
return strings.Trim(name, ".") |
|
} |
|
if name == "" || name == "@" { |
|
return zone |
|
} |
|
if !strings.HasSuffix(name, ".") { |
|
name += "." |
|
} |
|
return name + zone |
|
}
|
|
|