github.com/openshift/installer@v1.4.17/pkg/asset/installconfig/azure/dns.go (about)

     1  package azure
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"time"
     8  
     9  	survey "github.com/AlecAivazis/survey/v2"
    10  	azdns "github.com/Azure/azure-sdk-for-go/profiles/2018-03-01/dns/mgmt/dns"
    11  	"github.com/Azure/go-autorest/autorest/to"
    12  )
    13  
    14  // DNSConfig exposes functions to choose the DNS settings
    15  type DNSConfig struct {
    16  	session *Session
    17  }
    18  
    19  // ZonesGetter fetches the DNS zones available for the installer
    20  type ZonesGetter interface {
    21  	GetAllPublicZones() (map[string]string, error)
    22  }
    23  
    24  // ZonesClient wraps the azure ZonesClient internal
    25  type ZonesClient struct {
    26  	azureClient azdns.ZonesClient
    27  }
    28  
    29  // RecordSetsClient wraps the azure RecordSetsClient internal
    30  type RecordSetsClient struct {
    31  	azureClient azdns.RecordSetsClient
    32  }
    33  
    34  // Zone represents an Azure DNS Zone
    35  type Zone struct {
    36  	ID   string
    37  	Name string
    38  }
    39  
    40  func (z Zone) String() string {
    41  	return z.Name
    42  }
    43  
    44  // GetDNSZoneID returns the Azure DNS zone resourceID
    45  // by interpolating the subscriptionID, the resource group and the zone name
    46  func (config DNSConfig) GetDNSZoneID(rgName string, zoneName string) string {
    47  	return fmt.Sprintf(
    48  		"/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/dnszones/%s",
    49  		config.session.Credentials.SubscriptionID,
    50  		rgName,
    51  		zoneName)
    52  }
    53  
    54  // GetPrivateDNSZoneID returns the Azure Private DNS zone resourceID
    55  // by interpolating the subscriptionID, the resource group and the zone name
    56  func (config DNSConfig) GetPrivateDNSZoneID(rgName string, zoneName string) string {
    57  	return fmt.Sprintf(
    58  		"/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/privateDnsZones/%s",
    59  		config.session.Credentials.SubscriptionID,
    60  		rgName,
    61  		zoneName)
    62  }
    63  
    64  // GetDNSZone returns a DNS zone selected by survey
    65  func (config DNSConfig) GetDNSZone() (*Zone, error) {
    66  	//call azure api using the session to retrieve available base domain
    67  	zonesClient := newZonesClient(config.session)
    68  	allZones, _ := zonesClient.GetAllPublicZones()
    69  	if len(allZones) == 0 {
    70  		return nil, errors.New("no public dns zone found in your subscription")
    71  	}
    72  	zoneNames := []string{}
    73  	for zoneName := range allZones {
    74  		zoneNames = append(zoneNames, zoneName)
    75  	}
    76  
    77  	var zoneName string
    78  	err := survey.Ask([]*survey.Question{
    79  		{
    80  			Prompt: &survey.Select{
    81  				Message: "Base Domain",
    82  				Help:    "The base domain of the cluster. All DNS records will be sub-domains of this base and will also include the cluster name.\n\nIf you don't see you intended base-domain listed, create a new Azure DNS Zone and rerun the installer.",
    83  				Options: zoneNames,
    84  			},
    85  		},
    86  	}, &zoneName)
    87  	if err != nil {
    88  		return nil, fmt.Errorf("failed UserInput: %w", err)
    89  	}
    90  
    91  	return &Zone{
    92  		ID:   allZones[zoneName],
    93  		Name: zoneName,
    94  	}, nil
    95  
    96  }
    97  
    98  // GetDNSRecordSet gets a record set for the zone identified by publicZoneID
    99  func (config DNSConfig) GetDNSRecordSet(rgName string, zoneName string, relativeRecordSetName string, recordType azdns.RecordType) (*azdns.RecordSet, error) {
   100  	recordsetsClient := newRecordSetsClient(config.session)
   101  	return recordsetsClient.GetRecordSet(rgName, zoneName, relativeRecordSetName, recordType)
   102  }
   103  
   104  // NewDNSConfig returns a new DNSConfig struct that helps configuring the DNS
   105  // by querying your subscription and letting you choose
   106  // which domain you wish to use for the cluster
   107  func NewDNSConfig(ssn *Session) *DNSConfig {
   108  	return &DNSConfig{session: ssn}
   109  }
   110  
   111  func newZonesClient(session *Session) ZonesGetter {
   112  	azureClient := azdns.NewZonesClientWithBaseURI(session.Environment.ResourceManagerEndpoint, session.Credentials.SubscriptionID)
   113  	azureClient.Authorizer = session.Authorizer
   114  	return &ZonesClient{azureClient: azureClient}
   115  }
   116  
   117  func newRecordSetsClient(session *Session) *RecordSetsClient {
   118  	azureClient := azdns.NewRecordSetsClientWithBaseURI(session.Environment.ResourceManagerEndpoint, session.Credentials.SubscriptionID)
   119  	azureClient.Authorizer = session.Authorizer
   120  	return &RecordSetsClient{azureClient: azureClient}
   121  }
   122  
   123  // GetAllPublicZones get all public zones from the current subscription
   124  func (client *ZonesClient) GetAllPublicZones() (map[string]string, error) {
   125  	ctx, cancel := context.WithTimeout(context.TODO(), 30*time.Second)
   126  	defer cancel()
   127  	allZones := map[string]string{}
   128  	for zonesPage, err := client.azureClient.List(ctx, to.Int32Ptr(100)); zonesPage.NotDone(); err = zonesPage.NextWithContext(ctx) {
   129  		if err != nil {
   130  			return nil, err
   131  		}
   132  		//TODO: filter out private zone and show only public zones.
   133  		//the property is present in the REST api response, but not mapped yet in the stable SDK (present in preview)
   134  		//https://github.com/Azure/azure-sdk-for-go/blob/07f918ba2d513bbc5b75bc4caac845e10f27449e/services/preview/dns/mgmt/2018-03-01-preview/dns/models.go#L857
   135  		for _, zone := range zonesPage.Values() {
   136  			allZones[to.String(zone.Name)] = to.String(zone.ID)
   137  		}
   138  	}
   139  	return allZones, nil
   140  }
   141  
   142  // GetRecordSet gets an Azure DNS recordset by zone, name and recordset type
   143  func (client *RecordSetsClient) GetRecordSet(rgName string, zoneName string, relativeRecordSetName string, recordType azdns.RecordType) (*azdns.RecordSet, error) {
   144  	ctx, cancel := context.WithTimeout(context.TODO(), 30*time.Second)
   145  	defer cancel()
   146  
   147  	recordset, err := client.azureClient.Get(ctx, rgName, zoneName, relativeRecordSetName, recordType)
   148  	if err != nil {
   149  		return nil, err
   150  	}
   151  
   152  	return &recordset, nil
   153  }