oracle/oci-typescript-sdk

getZone returns 'only absolute urls are supported'

Closed this issue · 5 comments

I've encountered a problem with the getZone function that I could use some input on. Here's a quick and dirty example from the OCI Cloud Shell:

james_hart@cloudshell:~ (us-ashburn-1)$ node
> const oci = require("oci-sdk");
undefined
> const authenticationProvider = new oci.common.ConfigFileAuthenticationDetailsProvider();
undefined
> const client = new oci.dns.DnsClient({authenticationProvider});
undefined
> var getZoneRequest = {
... zoneNameOrId: "elcaro.io"
... }
undefined
> const getZoneResponse = client.getZone(getZoneRequest);
undefined
> (node:885) UnhandledPromiseRejectionWarning: Error: only absolute urls are supported

I've tried passing an OCID instead of the name with the same result. This payload works fine with the OCI CLI or the Python SDK. Any thoughts?

Hi @JauntyJames, I was not able to reproduce this error on the Cloud Shell with the same API. Can you try console logging the error message? If you wrap it with a try / catch block, you might see a more detailed error. client.getZone() is an asynchronous call that needs to be resolved, you can wrap this in an async function and await for the response in order to see the proper response.

Here's my actual code and response:

async function zoneExists(zoneNameOrId, compartmentId) {
  try {
    if (!compartmentId) {
      compartmentId = await getCompartmentId()
    }
    const authenticationProvider = new common.InstancePrincipalsAuthenticationDetailsProviderBuilder().build();
    const client = new dns.DnsClient({ authenticationProvider })

    const getZoneRequestBody = {
      zoneNameOrId: "ocid1.dns-zone.oc1..2418d88272f344228593260422638a72",
      compartmentId: compartmentId
    }
    const getZoneRequest = await client.getZone(getZoneRequestBody)
    return true
  } catch (error) {
    console.log(error)
    return false
  }
}

And here's the console error:

OciError: only absolute urls are supported
    at GenericRetrier.<anonymous> (/home/opc/oci-ddns/node_modules/oci-common/lib/retrier.js:82:38) 
    at Generator.throw (<anonymous>)
    at rejected (/home/opc/oci-ddns/node_modules/oci-common/lib/retrier.js:10:65) 
    at processTicksAndRejections (internal/process/task_queues.js:93:5) {                               
  statusCode: undefined,                                 
  serviceCode: 'unknown code',                                                                       
  opcRequestId: 'unknown'
}

In contrast, this function is working just fine in my code:

async function updateDNS(domain, ip, compartmentId) {
  try {
    // Break out zone from domain and validate
    let urlSegments = domain.split(".")
    if (urlSegments.length != 3) {
      return "notfqdn"
    }
 
    let zoneName = urlSegments[1] + "." + urlSegments[2]
 
    // If not passed in the function, get compartment ID from metadata url
    if (!compartmentId) {
    compartmentId = await getCompartmentId()
    }
 
    // Create instance principal auth
    const authenticationProvider = await new common.InstancePrincipalsAuthenticationDetailsProviderBuilder().build();
 
    // Create a service client
    const client = new dns.DnsClient({ authenticationDetailsProvider: authenticationProvider });
 
    // Create a request and dependent object(s).
    const patchZoneRecordsDetails = {
      items: [
        {
          domain: domain,
          rtype: "A",
          operation: dns.models.RecordOperation.Operation.Remove
        },
        {
          domain: domain,
          rdata: ip,
          rtype: "A",
          ttl: 300,
          operation: dns.models.RecordOperation.Operation.Add
        }
      ]
    };
 
    const patchZoneRecordsRequest = {
      zoneNameOrId: zoneName,
      patchZoneRecordsDetails: patchZoneRecordsDetails,
      compartmentId: compartmentId
    };
 
    const getZoneRecordsRequest = {
      zoneNameOrId: zoneName,
      compartmentId: compartmentId
    };
 
    // Check for existing records
    const ZoneRecordsResponse = await client.getZoneRecords(getZoneRecordsRequest);
    if (ZoneRecordsResponse.recordCollection.items.filter(record => (record.rdata === ip && record.domain === domain)).length > 0) {
      return "nochg"
    };
 
    // Send request to the Client.
    const patchZoneRecordsResponse = await client.patchZoneRecords(patchZoneRecordsRequest);
    return "good"
 
  } catch (error) {
    console.log("updateZoneRecords Failed with error " + error);
    return error
  }
};

Are both of these code ran in the Cloud shell environment? Do both code work when you run them locally on your machine?

No, those are from the server where I actually want it to run, but I just tested again from the cloud shell swapping out instance principal auth for config file auth, same result.

Debugging session with @waruwaruwaru showed that because my code didn't use await when composing the instance principal auth provider, the base URL for the API wasn't being composed properly. Adding await fixed the problem in my function. Thanks for the help/attention!