pulumi / pulumi-azure-native

Azure Native Provider
Apache License 2.0
126 stars 34 forks source link

Migration from nextgen fails on DNS recordsets #621

Closed alastairs closed 3 years ago

alastairs commented 3 years ago

Following the announcement of the renaming of azure-nextgen to azure-native, I followed the migration steps outlined, and ran into two issues. I've attached a patchfile so you can see the changes involved in the migration.

Expected behavior

  1. Public DNS zones continue to be supported with the "versionless" resources;
  2. DNS zones can still be retrieved successfully.

Current behavior

  1. The API version used for Microsoft.Network is 2020-06-01, which, as far as I can tell, only supports Private DNS Zones for creating Recordset resources. I have had to manually specific v20180501 to continue using that API.
  2. I now receive a "transport is closing" error message when retrieving my DNS zone with azure-native@0.7.1 which I did not receive with azure-nextgen@0.6.1. This turned out to be a config problem

Steps to reproduce

I have a CustomHostname ComponentResource for creating all the necessary resources for an SSL-enabled custom hostname binding in Azure AppService, where the certificate lives in Azure Key Vault and the DNS zone is managed by Azure DNS:

import * as appservice from "@pulumi/azure-native/web";
import * as keyvault from "@pulumi/azure-native/keyvault";
import * as dns from "@pulumi/azure-native/network/v20180501"; // Issue 1: cannot use 'latest'

// Class for provisioning a new **AppService** certificate from an existing certificate stored in Key Vault,
// verifying ownership of the custom domain via DNS TXT records, provisioning the required DNS CNAME
// record, and the AppService hostname binding with the retrieved-and-provisioned certificate
export class CustomHostname extends pulumi.ComponentResource {
  hostname: string;
  constructor(name: string, args: CustomHostnameArgs, opts?: pulumi.ResourceOptions) {
    super("my:appservice:CustomHostname", name, args, opts);
    this.hostname = args.customHostname;

    const keyVault = pulumi.output(keyvault.getVault(args.certificatesStore));
    const certificate = new appservice.Certificate(
      `${this.hostname}-certificate`,
      {
        keyVaultId: keyVault.id,
        keyVaultSecretName: args.certificateName,
        password: "",
        serverFarmId: args.appServicePlanId,
        resourceGroupName: args.resourceGroupName,
        name: args.certificateName
      }, { deleteBeforeReplace: true });

      const verification = this.verifyCustomDomain(
        this.hostname,
        args.customDomainVerificationId,
        args.functionAppName);

      this.binding = new appservice.WebAppHostNameBinding("appservice-hostname-", {
        name: args.functionAppName,
        resourceGroupName: args.resourceGroupName,
        hostName: args.customHostname,
        hostNameType: appservice.HostNameType.Verified,
        customHostNameDnsRecordType: appservice.CustomHostNameDnsRecordType.CName,
        sslState: appservice.SslState.SniEnabled,
        thumbprint: certificate.thumbprint
      }, { parent: this, dependsOn: verification });
  }

  private verifyCustomDomain(
    customHostname: string,
    customDomainVerificationId: pulumi.Input<string>,
    functionAppName: pulumi.Input<string>
  ) {
    const tld = customHostname.split(".").reverse().slice(0, 2).reverse().join(".");
    const subdomain = customHostname.split(".").reverse().slice(2).reverse().join(".");

    const zone = pulumi.output(
      dns.getZone({
        zoneName: tld,
        resourceGroupName: "rg-dns"
      }));

    const verification = new dns.RecordSet(`asuid.${customHostname}`, {
      recordType: "TXT",
      relativeRecordSetName: `asuid.${subdomain}`,
      resourceGroupName: "rg-dns",
      zoneName: zone.name, // Issue 1: zoneName does not exist, is called `privateZoneName`
      txtRecords: [{
        value: [customDomainVerificationId]
      }],
      ttl: 60
    }, { deleteBeforeReplace: true });

    const cname = new dns.RecordSet(customHostname, {
      recordType: "CNAME",
      relativeRecordSetName: subdomain,
      resourceGroupName: "rg-dns",
      zoneName: zone.name,
      ttl: 60,
      cnameRecord: {
        cname: pulumi.interpolate`${functionAppName}.azurewebsites.net.`
      }
    }, { deleteBeforeReplace: true });

    return [verification, cname];
  }
}
mikhailshilkov commented 3 years ago

Hey @alastairs thank you for reporting this. Is this somewhat the same issue as https://github.com/pulumi/pulumi-azure-native/issues/583 ?

alastairs commented 3 years ago

Thanks for the swift response @mikhailshilkov. You're right I think, yes, it is the same - sorry for the duplicate ☺️

mikhailshilkov commented 3 years ago

No worries. To be sure - when you say "Public DNS zones" - do you mean dns.RecordSet or any other resource?

alastairs commented 3 years ago

I'm only using RecordSet from the network API at the moment, so just that one.

mikhailshilkov commented 3 years ago

Closed as dupe of https://github.com/pulumi/pulumi-azure-native/issues/583