Refactors some of domain service with fetch records and add record

This commit is contained in:
Akshay Nair
2020-10-11 16:27:47 +05:30
parent 79b46ef8b5
commit 28c0f7301a
6 changed files with 39 additions and 50 deletions
+1 -1
View File
@@ -16,9 +16,9 @@
"author": "Akshay Nair <phenax5@gmail.com>",
"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"
}
}
+19 -20
View File
@@ -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' },
+1
View File
@@ -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' } },
+7 -23
View File
@@ -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,
+6 -1
View File
@@ -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,
+5 -5
View File
@@ -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"