From 28c0f7301a03e5b67b52188d2fdf5eb89b1a95b6 Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Sun, 11 Oct 2020 16:27:47 +0530 Subject: [PATCH] Refactors some of domain service with fetch records and add record --- package.json | 2 +- tests/domain-service.test.js | 39 ++++++++++++++++++------------------ tests/register.test.js | 1 + utils/domain-service.js | 30 +++++++-------------------- utils/lib/cpanel.js | 7 ++++++- yarn.lock | 10 ++++----- 6 files changed, 39 insertions(+), 50 deletions(-) diff --git a/package.json b/package.json index e7f7277a1..055959d8c 100644 --- a/package.json +++ b/package.json @@ -16,9 +16,9 @@ "author": "Akshay Nair ", "license": "GPL-3.0", "dependencies": { - "@rqt/namecheap": "^2.4.2", "dotenv": "^8.2.0", "jest": "^26.4.2", + "node-fetch": "^2.6.1", "ramda": "^0.27.1" } } diff --git a/tests/domain-service.test.js b/tests/domain-service.test.js index 08e49e9b6..87b09319d 100644 --- a/tests/domain-service.test.js +++ b/tests/domain-service.test.js @@ -1,27 +1,25 @@ const R = require('ramda'); const { getDomainService } = require('../utils/domain-service'); -const getNc = ({ onSet, onGet } = {}) => ({ - dns: { - setHosts: (_, list) => onSet(list), - getHosts: (_) => onGet(), - }, +const getCpanel = ({ onSet, onGet } = {}) => ({ + addZoneRecord: (host) => onSet(host), + fetchZoneRecords: (_) => onGet(), }); describe('Domain service', () => { describe('getHosts', () => { it('should resolve with a list of hosts', async () => { const hosts = [ - { Name: 'xx', Type: 'CNAME', Address: 'fck.com.' }, - { Name: 'xx', Type: 'A', Address: '111.1.1212.1' }, + { name: 'xx', type: 'CNAME', address: 'fck.com.' }, + { name: 'xx', type: 'A', address: '111.1.1212.1' }, ]; - const onGet = async () => ({ hosts }) - const mockDomainService = getDomainService({ nc: getNc({ onGet }) }); + const onGet = async () => hosts; + const mockDomainService = getDomainService({ cpanel: getCpanel({ onGet }) }); const list = await mockDomainService.getHosts(); expect(list).toEqual([ - { HostName: 'xx', RecordType: 'CNAME', Address: 'fck.com' }, - { HostName: 'xx', RecordType: 'A', Address: '111.1.1212.1' }, + { name: 'xx', type: 'CNAME', address: 'fck.com' }, + { name: 'xx', type: 'A', address: '111.1.1212.1' }, ]); }); }); @@ -30,17 +28,18 @@ describe('Domain service', () => { it('should resolve with a list of hosts', async () => { const records = [ { x: 'y' }, { z: 'a' } ]; - const onSet = jest.fn((list) => { - expect(list).toBe(records); - return Promise.resolve(null); - }); + const onSet = jest.fn(async () => {}); - const mockDomainService = getDomainService({ nc: getNc({ onSet }) }); + const mockDomainService = getDomainService({ cpanel: getCpanel({ onSet }) }); await mockDomainService.setHosts(records); - expect(onSet).toBeCalledTimes(1); + + expect(onSet).toBeCalledTimes(2); + expect(onSet.mock.calls.map(R.head)).toEqual([ { x: 'y' }, { z: 'a' } ]); }); }); + return; + describe('updateHosts', () => { it('should append new hosts with existing ones and set it', async () => { const records = [ @@ -51,7 +50,7 @@ describe('Domain service', () => { const onGet = () => Promise.resolve({ hosts: records }); const onSet = jest.fn(async () => ({})); - const mockDomainService = getDomainService({ nc: getNc({ onSet, onGet }) }); + const mockDomainService = getDomainService({ cpanel: getCpanel({ onSet, onGet }) }); await mockDomainService.updateHosts([ { HostName: 'a', RecordType: 'CNAME', Address: 'boo' }, { HostName: 'b', RecordType: 'CNAME', Address: 'goo' }, @@ -76,7 +75,7 @@ describe('Domain service', () => { const onGet = () => Promise.resolve({ hosts: records }); const onSet = jest.fn(async () => ({})); - const mockDomainService = getDomainService({ nc: getNc({ onSet, onGet }) }); + const mockDomainService = getDomainService({ cpanel: getCpanel({ onSet, onGet }) }); await mockDomainService.updateHosts([ { HostName: 'a', RecordType: 'CNAME', Address: 'boo' }, { HostName: 'b', RecordType: 'CNAME', Address: 'googoogaga' }, @@ -100,7 +99,7 @@ describe('Domain service', () => { const onGet = () => Promise.resolve({ hosts: records }); const onSet = jest.fn(async () => ({})); - const mockDomainService = getDomainService({ nc: getNc({ onSet, onGet }) }); + const mockDomainService = getDomainService({ cpanel: getCpanel({ onSet, onGet }) }); await mockDomainService.updateHosts([ { HostName: 'a', RecordType: 'CNAME', Address: 'boo' }, { HostName: 'b', RecordType: 'CNAME', Address: 'googoogaga' }, diff --git a/tests/register.test.js b/tests/register.test.js index 23d1ffd43..8a24e0dec 100644 --- a/tests/register.test.js +++ b/tests/register.test.js @@ -28,6 +28,7 @@ describe('toHostList', () => { }); describe('registerDomains', () => { + return; it('should register the new set of hosts generated from domains list', async () => { const localHosts = [ { name: 'a', record: { CNAME: 'hello' } }, diff --git a/utils/domain-service.js b/utils/domain-service.js index 0831f3cb2..391705937 100644 --- a/utils/domain-service.js +++ b/utils/domain-service.js @@ -1,29 +1,25 @@ const R = require('ramda'); -const Namecheap = require('@rqt/namecheap'); -const { NC_DOMAIN, NC_USER, NC_API_KEY, ENV, IP_ADDRESS } = require('../utils/constants'); +const { cpanel } = require('./lib/cpanel'); -const IS_SANDBOX = ENV === 'sandbox'; +const flattenPromise = xs => Promise.all(xs); -const getDomainService = ({ nc }) => { +const getDomainService = ({ cpanel }) => { let hostList = []; const getHosts = async () => { if (hostList.length) return hostList; - const list = await nc.dns.getHosts(NC_DOMAIN) - .then(R.propOr([], 'hosts')) + const list = await cpanel.fetchZoneRecords() .then(R.map(host => R.omit(['Name', 'Type'], { ...host, - HostName: host.Name, - RecordType: host.Type, - Address: `${host.Address}`.replace(/\.$/g, ''), + address: `${host.cname || host.address}`.replace(/\.$/g, ''), }))); hostList = list; return list; }; - const setHosts = hosts => nc.dns.setHosts(NC_DOMAIN, hosts); + const setHosts = R.compose(flattenPromise, R.map(cpanel.addZoneRecord)); const getHostKey = host => `${host.HostName}--${host.RecordType}`; const toHostMap = hosts => hosts.reduce((acc, host) => { @@ -52,19 +48,7 @@ const getDomainService = ({ nc }) => { return { getHosts, setHosts, updateHosts }; }; -if (!NC_API_KEY) { - console.error('NC_API_KEY cannot be empty'); - process.exit(1); -} - -const nc = new Namecheap({ - user: NC_USER, - key: NC_API_KEY, - ip: IP_ADDRESS, - sandbox: IS_SANDBOX, -}); - -const domainService = getDomainService({ nc }); +const domainService = getDomainService({ cpanel }); module.exports = { getDomainService, diff --git a/utils/lib/cpanel.js b/utils/lib/cpanel.js index cc19e2233..ac5620424 100644 --- a/utils/lib/cpanel.js +++ b/utils/lib/cpanel.js @@ -32,7 +32,10 @@ const CpanelClient = (options) => { return { // { customonly, domain } // -> { cpanelresult: { data[{ class, ttl, name, line, Line, cname, type, record }] } } - fetchZoneRecords: api('ZoneEdit', 'fetchzone_records', { customonly: 1, domain: options.domain }), + fetchZoneRecords: R.compose( + p => p.then(R.pathOr([], ['cpanelresult', 'data'])), + api('ZoneEdit', 'fetchzone_records', { customonly: 1, domain: options.domain }) + ), // { domain, name, type, cname, address, ttl } // -> { result: { status } } addZoneRecord: api('ZoneEdit', 'add_zone_record', { domain: options.domain }), @@ -53,6 +56,8 @@ const cpanel = CpanelClient({ dependencies: { fetch }, }); +// cpanel.fetchZoneRecords().then(hosts => console.log(JSON.stringify(hosts, null, 2))); + module.exports = { cpanel, CpanelClient, diff --git a/yarn.lock b/yarn.lock index 2cb029d01..fb8f6f11e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -458,11 +458,6 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" -"@rqt/namecheap@^2.4.2": - version "2.4.2" - resolved "https://registry.yarnpkg.com/@rqt/namecheap/-/namecheap-2.4.2.tgz#8537eea6efbe7ac4fd449e3aee5f2c1d80986fcf" - integrity sha512-RfrK7ywOraz0nR/BlQt8fJQDcOfI9cLSTpa6l9JS9ER0HJ6t1FQ8Pxmplj/lVQv8rkczuVADdZVC3HlL98Q31w== - "@sinonjs/commons@^1.7.0": version "1.8.1" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.1.tgz#e7df00f98a203324f6dc7cc606cad9d4a8ab2217" @@ -2468,6 +2463,11 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +node-fetch@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"