Skip to content

Commit

Permalink
Added tested OTC DNS implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
marhode committed Apr 15, 2024
1 parent b02e4ae commit ad1f17a
Show file tree
Hide file tree
Showing 2 changed files with 167 additions and 75 deletions.
124 changes: 49 additions & 75 deletions providers/telekom.go
Original file line number Diff line number Diff line change
@@ -1,61 +1,39 @@
//Telekom Cloud OTC DNS management for the BBB autoscaler implementation
//Creation of a new OTC DNS record
//Deletion of a existing OTC DNS record
//Updating of the IP in a OTC DNS record
package otcdns
// Telekom Cloud OTC DNS management for the BBB autoscaler implementation
// Config of Telekom Cloud
// Creation of a new OTC DNS record
// Deletion of a existing OTC DNS record
// Updating of the IP in a OTC DNS record
package providers

import (
"fmt"

otc "github.com/opentelekomcloud/gophertelekomcloud"
otcos "github.com/opentelekomcloud/gophertelekomcloud/openstack"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/dns/v2/recordsets"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/dns/v2/zones"
)

const (
dnsRecordTypeA string = "A"
dnsRecordTypeA string = "A"
dnsRecordDescription string = "BBB Autoscaler"
)

//
type Telekom struct {
Config ProviderConfig `yaml:"-"`
}

// The DNS client we use to trigger our DNS actions.
//
type OtcDnsClient struct {
Sc *otc.ServiceClient
}

func NewDNSV2Client() (*OtcDnsClient, error) {
cloudsConfig, err := getCloud()
if err != nil {
return nil, err
}
endpointOpts := otc.EndpointOpts{
Region: cloudsConfig.RegionName,
}

providerClient, err := getProviderClient()
if err != nil {
return nil, err
}

serviceClient, err := otcos.NewDNSV2(providerClient, endpointOpts)
if err != nil {
return nil, err
}

return &OtcDnsClient{Sc: serviceClient}, nil
}

// ===========================================================================
// Zones
// ===========================================================================

//
// Retrieves a Zone data structure by its name.
// https://pkg.go.dev/github.com/opentelekomcloud/[email protected]/openstack/dns/v2/zones
// github.com/opentelekomcloud/gophertelekomcloud/openstack/dns/v2/zones
//
func (dnsClient *OtcDnsClient) GetHostedZone(zoneName string) (*zones.Zone, error) {

listOpts := zones.ListOpts{
Expand Down Expand Up @@ -89,21 +67,23 @@ func (dnsClient *OtcDnsClient) GetHostedZone(zoneName string) (*zones.Zone, erro
// RecordSets
// ===========================================================================

//Get Recordset by DNS Name
func (dnsClient *OtcDnsClient) GetARecordSet(zone *zones.Zone, dnsName string) (*recordsets.RecordSet, error) {
// Get Recordset by DNS Name
func (dnsClient *OtcDnsClient) GetARecordSet(zone *zones.Zone, dnsName string) *recordsets.RecordSet {
listOpts := recordsets.ListOpts{
Type: dnsRecordTypeA,
Name: dnsName,
}

allPages, err := recordsets.ListByZone(dnsClient.Sc, zone.ID, listOpts).AllPages()
if err != nil {
return nil, fmt.Errorf("list records failed for dns entry %s: %s", dnsName, err)
fmt.Printf("list records failed for dns entry %s: %s", dnsName, err)
return nil
}

allRRs, err := recordsets.ExtractRecordSets(allPages)
if err != nil {
return nil, fmt.Errorf("extract recordset failed for dns entry %s: %s", dnsName, err)
fmt.Printf("extract recordset failed for dns entry %s: %s", dnsName, err)
return nil
}

// Debug
Expand All @@ -113,69 +93,63 @@ func (dnsClient *OtcDnsClient) GetARecordSet(zone *zones.Zone, dnsName string) (

if len(allRRs) == 1 {
// We need exactly 1 recordset to operate on
return &allRRs[0], nil
return &allRRs[0]
} else if len(allRRs) == 0 {
// Query was successful, but no results
return nil, nil
return nil
} else {
// More than 1 result.
return nil, fmt.Errorf("query with %s returned %d recordsets. Expected: 1", dnsName, len(allRRs))
fmt.Printf("query with %s returned %d recordsets. Expected: 1", dnsName, len(allRRs))
return nil
}
}

//
//Create new A DNS RecordSet with DNS Name and IP
//
func (dnsClient *OtcDnsClient) CreateRecordSet (zone *zones.Zone, dnsName string, ipValue string) (*recordsets.RecordSet, error) {
// Create new A DNS RecordSet with DNS Name and IP
func (dnsClient *OtcDnsClient) CreateRecordSet(zone *zones.Zone, dnsName string, ipValue string) (*recordsets.RecordSet, error) {

createOpts := recordsets.CreateOpts{
Name: dnsName,
Name: dnsName,
Description: dnsRecordDescription,
Type: dnsRecordTypeA,
Records: []string{ipValue},
TTL: 300,
Type: dnsRecordTypeA,
Records: []string{ipValue},
TTL: 300,
}

var pCreatedRecordset *recordsets.RecordSet
pCreatedRecordset, err := recordsets.Create(dnsClient.Sc, zone.ID, createOpts).Extract()
if err != nil {
fmt.Printf("Error creating DNS record: %v\n", err)
return
}
if err != nil {
fmt.Printf("Error creating DNS record: %v\n", err)
return nil, err
}
return pCreatedRecordset, nil
}

//
//Delete a RecordSet by DNS Name
//
func (dnsClient *OtcDnsClient) DeleteRecordSet (zone *zones.Zone, dnsName string) {
// Delete a RecordSet by DNS Name
func (dnsClient *OtcDnsClient) DeleteRecordSet(zone *zones.Zone, dnsName string) error {
//get DNS details
recordSet, err := dnsClient.GetARecordSet(zone.ID, dnsName)

recordSet := dnsClient.GetARecordSet(zone, dnsName)
//Call delete function
err := recordsets.Delete(dnsClient.Sc, zone.ID, recordSet.ID).ExtractErr()
if err != nil {
return fmt.Errorf("deletion of record with zoneId %s and recordsetId %s failed: %s", zone.ID, recordset.ID, err)
fmt.Printf("deletion of record with zoneId %s and recordsetId %s failed: %s", zone.ID, recordSet.ID, err)
return err
}

return nil
}

//
//Updating a RecordSet IP by DNS Name
//
// Updating a RecordSet IP by DNS Name TODO cant use the same client?
func (dnsClient *OtcDnsClient) UpdateRecordSet(zone *zones.Zone, dnsName string, newIPValue string) (*recordsets.RecordSet, error) {
//get DNS details
recordSet, err := dnsClient.GetARecordSet(zone.ID, dnsName)
//get DNS details
recordSet := dnsClient.GetARecordSet(zone, dnsName)

updateOpts := recordsets.UpdateOpts{
Records: []string{newIPValue},
}

updatedRecordSet, err := recordsets.Update(dnsClient, zone.ID, recordSet.ID, updateOpts).Extract()
if err != nil {
fmt.Printf("Error updating DNS record: %v\n", err)
return nil, err
}
return updatedRecordSet, nil
}
Records: []string{newIPValue},
}

updatedRecordSet, err := recordsets.Update(dnsClient.Sc, zone.ID, recordSet.ID, updateOpts).Extract()
if err != nil {
fmt.Printf("Error updating DNS record: %v\n", err)
return nil, err
}
return updatedRecordSet, nil
}
118 changes: 118 additions & 0 deletions providers/telekom_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// Config of Telekom Cloud
package providers

import (
"encoding/json"
"fmt"

otc "github.com/opentelekomcloud/gophertelekomcloud"
otcos "github.com/opentelekomcloud/gophertelekomcloud/openstack"
)

const (
envPrefix string = "OS_"
OtcProfileNameUser string = "otcuser"
OtcProfileNameAkSk string = "otcaksk"
)

var EnvOS = otcos.NewEnv(envPrefix)

// ===========================================================================
// Configs
// ===========================================================================

// Creates a new DNSv2 ServiceClient.
// See also gophertelekomcloud/acceptance/clients/clients.go
func NewDNSV2ClientWithAuth(authOpts otc.AuthOptionsProvider, endpointOpts otc.EndpointOpts) (*OtcDnsClient, error) {

providerClient, err := getProviderClientWithAccessKeyAuth(authOpts)
if err != nil {
return nil, fmt.Errorf("cannot create providerClient. %s", err)
}

serviceClient, err := otcos.NewDNSV2(providerClient, endpointOpts)
if err != nil {
return nil, fmt.Errorf("cannot create serviceClient. %s", err)
}

return &OtcDnsClient{Sc: serviceClient}, nil
}

func getProviderClientWithAccessKeyAuth(authOpts otc.AuthOptionsProvider) (*otc.ProviderClient, error) {
provider, err := otcos.AuthenticatedClient(authOpts)
if err != nil {
return nil, fmt.Errorf("provider creation has failed: %s", err)
}
return provider, nil
}

func getCloud() (*otcos.Cloud, error) {
return getCloudProfile(OtcProfileNameUser)
}

func copyCloud(src *otcos.Cloud) (*otcos.Cloud, error) {
srcJson, err := json.Marshal(src)
if err != nil {
return nil, fmt.Errorf("error marshalling cloud: %s", err)
}

res := new(otcos.Cloud)
if err := json.Unmarshal(srcJson, res); err != nil {
return nil, fmt.Errorf("error unmarshalling cloud: %s", err)
}

return res, nil
}

func getCloudProfile(otcProfileName string) (*otcos.Cloud, error) {

cloud, err := EnvOS.Cloud(otcProfileName)
if err != nil {
return nil, fmt.Errorf("error constructing cloud configuration: %s", err)
}

cloud, err = copyCloud(cloud)
if err != nil {
return nil, fmt.Errorf("error copying cloud: %s", err)
}

return cloud, nil
}

func getProviderClient() (*otc.ProviderClient, error) {
return getProviderClientProfile(OtcProfileNameUser)
}

func getProviderClientProfile(otcProfileName string) (*otc.ProviderClient, error) {

client, err := EnvOS.AuthenticatedClient(otcProfileName)
if err != nil {
return nil, fmt.Errorf("cloud and provider creation has failed: %s", err)
}

return client, nil
}

// Creates a new DNSv2 ServiceClient.
// See also gophertelekomcloud/acceptance/clients/clients.go
func NewDNSV2Client() (*OtcDnsClient, error) {
cloudsConfig, err := getCloud()
if err != nil {
return nil, err
}
endpointOpts := otc.EndpointOpts{
Region: cloudsConfig.RegionName,
}

providerClient, err := getProviderClient()
if err != nil {
return nil, err
}

serviceClient, err := otcos.NewDNSV2(providerClient, endpointOpts)
if err != nil {
return nil, err
}

return &OtcDnsClient{Sc: serviceClient}, nil
}

0 comments on commit ad1f17a

Please sign in to comment.