mirror of https://github.com/apache/cloudstack.git
continue UI component work, fix minor issue with apis
This commit is contained in:
parent
c74a579b86
commit
7f5e2a7d30
|
|
@ -63,7 +63,7 @@ public class CreateDnsZoneCmd extends BaseAsyncCreateCmd {
|
|||
description = "The type of zone (Public, Private). Defaults to Public.")
|
||||
private String type;
|
||||
|
||||
@Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "Display text for the zone")
|
||||
@Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "The description of the DNS zone")
|
||||
private String description;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import org.apache.cloudstack.api.BaseAsyncCmd;
|
|||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.DnsServerResponse;
|
||||
import org.apache.cloudstack.api.response.DnsZoneResponse;
|
||||
import org.apache.cloudstack.api.response.SuccessResponse;
|
||||
import org.apache.cloudstack.dns.DnsServer;
|
||||
|
||||
|
|
@ -51,6 +52,10 @@ public class DeleteDnsServerCmd extends BaseAsyncCmd {
|
|||
required = true, description = "the ID of the DNS server")
|
||||
private Long id;
|
||||
|
||||
@Parameter(name = ApiConstants.CLEANUP, type = CommandType.BOOLEAN,
|
||||
entityType = DnsZoneResponse.class, description = "True if all associated DNS zones have to be cleaned up with this server")
|
||||
private Boolean cleanup;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -93,4 +98,8 @@ public class DeleteDnsServerCmd extends BaseAsyncCmd {
|
|||
|
||||
@Override
|
||||
public String getEventDescription() { return "Deleting DNS server ID: " + getId(); }
|
||||
|
||||
public Boolean getCleanup() {
|
||||
return Boolean.TRUE.equals(cleanup);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ public class UpdateDnsZoneCmd extends BaseCmd {
|
|||
required = true, description = "The ID of the DNS zone")
|
||||
private Long id;
|
||||
|
||||
@Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "Display text for the zone")
|
||||
@Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "The description of the DNS zone to be updated")
|
||||
private String description;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ import org.apache.http.client.methods.HttpDelete;
|
|||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPatch;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.methods.HttpPut;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
|
|
@ -185,8 +186,8 @@ public class PowerDnsClient implements AutoCloseable {
|
|||
nsArray.add(ns.endsWith(".") ? ns : ns + ".");
|
||||
}
|
||||
}
|
||||
HttpPatch request = new HttpPatch(url);
|
||||
request.setEntity(new org.apache.http.entity.StringEntity(json.toString(), StandardCharsets.UTF_8));
|
||||
HttpPut request = new HttpPut(url);
|
||||
request.setEntity(new StringEntity(json.toString(), StandardCharsets.UTF_8));
|
||||
execute(request, apiKey, 204);
|
||||
}
|
||||
|
||||
|
|
@ -221,7 +222,7 @@ public class PowerDnsClient implements AutoCloseable {
|
|||
}
|
||||
String encodedZone = URLEncoder.encode(normalizedZone, StandardCharsets.UTF_8);
|
||||
HttpPatch request = new HttpPatch(buildUrl(baseUrl, port, "/servers/" + externalServerId + "/zones/" + encodedZone));
|
||||
request.setEntity(new org.apache.http.entity.StringEntity(root.toString(), StandardCharsets.UTF_8));
|
||||
request.setEntity(new StringEntity(root.toString(), StandardCharsets.UTF_8));
|
||||
execute(request, apiKey, 204);
|
||||
return normalizedRecord.endsWith(".") ? normalizedRecord.substring(0, normalizedRecord.length() - 1) : normalizedRecord;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,9 @@ import org.apache.cloudstack.dns.dao.DnsServerJoinDao;
|
|||
import org.apache.cloudstack.dns.dao.DnsZoneDao;
|
||||
import org.apache.cloudstack.dns.dao.DnsZoneJoinDao;
|
||||
import org.apache.cloudstack.dns.dao.DnsZoneNetworkMapDao;
|
||||
import org.apache.cloudstack.dns.exception.DnsConflictException;
|
||||
import org.apache.cloudstack.dns.exception.DnsNotFoundException;
|
||||
import org.apache.cloudstack.dns.exception.DnsTransportException;
|
||||
import org.apache.cloudstack.dns.vo.DnsServerJoinVO;
|
||||
import org.apache.cloudstack.dns.vo.DnsServerVO;
|
||||
import org.apache.cloudstack.dns.vo.DnsZoneJoinVO;
|
||||
|
|
@ -176,18 +178,10 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa
|
|||
}
|
||||
|
||||
private Pair<List<DnsServerVO>, Integer> searchForDnsServerInternal(ListDnsServersCmd cmd) {
|
||||
Long dnsServerId = cmd.getId();
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
if (dnsServerId != null) {
|
||||
DnsServerVO dnsServerVO = dnsServerDao.findById(dnsServerId);
|
||||
if (dnsServerVO == null) {
|
||||
return null;
|
||||
}
|
||||
return new Pair<>(Collections.singletonList(dnsServerVO), 1);
|
||||
}
|
||||
Set<Long> parentDomainIds = domainDao.getDomainParentIds(caller.getDomainId());
|
||||
Filter searchFilter = new Filter(DnsServerVO.class, ApiConstants.ID, true, cmd.getStartIndex(), cmd.getPageSizeVal());
|
||||
return dnsServerDao.searchDnsServer(dnsServerId, caller.getAccountId(), parentDomainIds, cmd.getProviderType(), cmd.getKeyword(), searchFilter);
|
||||
return dnsServerDao.searchDnsServer(cmd.getId(), caller.getAccountId(), parentDomainIds, cmd.getProviderType(), cmd.getKeyword(), searchFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -272,6 +266,9 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa
|
|||
}
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
accountMgr.checkAccess(caller, dnsServer);
|
||||
if (cmd.getCleanup()) {
|
||||
// ToDo cleanup associated dnsZones
|
||||
}
|
||||
return dnsServerDao.remove(dnsServerId);
|
||||
}
|
||||
|
||||
|
|
@ -322,6 +319,7 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa
|
|||
try {
|
||||
DnsProvider provider = getProviderByType(server.getProviderType());
|
||||
provider.updateZone(server, dnsZone);
|
||||
dnsZoneDao.update(dnsZone.getId(), dnsZone);
|
||||
} catch (Exception ex) {
|
||||
logger.error("Failed to update DNS zone: {} on DNS server: {}", dnsZone.getName(), server.getName(), ex);
|
||||
throw new CloudRuntimeException("Failed to update DNS zone: " + dnsZone.getName());
|
||||
|
|
@ -375,20 +373,23 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa
|
|||
if (StringUtils.isBlank(recordName)) {
|
||||
throw new InvalidParameterValueException("Empty DNS record name is not allowed");
|
||||
}
|
||||
DnsZoneVO zone = dnsZoneDao.findById(cmd.getDnsZoneId());
|
||||
if (zone == null) {
|
||||
DnsZoneVO dnsZone = dnsZoneDao.findById(cmd.getDnsZoneId());
|
||||
if (dnsZone == null) {
|
||||
throw new InvalidParameterValueException("DNS zone not found.");
|
||||
}
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
accountMgr.checkAccess(caller, null, true, zone);
|
||||
DnsServerVO server = dnsServerDao.findById(zone.getDnsServerId());
|
||||
accountMgr.checkAccess(caller, null, true, dnsZone);
|
||||
DnsServerVO server = dnsServerDao.findById(dnsZone.getDnsServerId());
|
||||
if (server == null) {
|
||||
throw new CloudRuntimeException("The underlying DNS server for this DNS zone is missing.");
|
||||
}
|
||||
try {
|
||||
DnsRecord.RecordType type = cmd.getType();
|
||||
List<String> normalizedContents = cmd.getContents().stream()
|
||||
.map(value -> DnsProviderUtil.normalizeDnsRecordValue(value, type)).collect(Collectors.toList());
|
||||
DnsRecord record = new DnsRecord(recordName, type, normalizedContents, cmd.getTtl());
|
||||
DnsProvider provider = getProviderByType(server.getProviderType());
|
||||
String normalizedRecordName = provider.addRecord(server, zone, record);
|
||||
String normalizedRecordName = provider.addRecord(server, dnsZone, record);
|
||||
record.setName(normalizedRecordName);
|
||||
return createDnsRecordResponse(record);
|
||||
} catch (Exception ex) {
|
||||
|
|
@ -507,7 +508,13 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa
|
|||
} catch (Exception ex) {
|
||||
dnsZoneDao.remove(dnsZoneId);
|
||||
logger.error("Failed to provision DNS zone: {} on DNS server: {}", dnsZone.getName(), server.getName(), ex);
|
||||
throw new CloudRuntimeException("Failed to provision DNS zone: " + dnsZone.getName());
|
||||
String errorMsg = "";
|
||||
if ( ex instanceof DnsConflictException) {
|
||||
errorMsg = String.format("DNS zone: %s already exists", dnsZone.getName());
|
||||
} else if (ex instanceof DnsTransportException){
|
||||
errorMsg = String.format("DNS server: %s not reachable", server.getName());
|
||||
}
|
||||
throw new CloudRuntimeException(errorMsg);
|
||||
}
|
||||
return dnsZone;
|
||||
}
|
||||
|
|
@ -562,6 +569,7 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa
|
|||
res.setName(record.getName());
|
||||
res.setType(record.getType());
|
||||
res.setContent(record.getContents());
|
||||
res.setTtl(record.getTtl());
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -716,6 +716,7 @@
|
|||
"label.create.webhook": "Create Webhook",
|
||||
"label.created": "Created",
|
||||
"label.creating": "Creating",
|
||||
"label.creating.dns.zone": "Creating DNS zone",
|
||||
"label.creating.iprange": "Creating IP ranges",
|
||||
"label.nameservers": "DNS Nameservers",
|
||||
"label.credit": "Credit",
|
||||
|
|
@ -941,12 +942,14 @@
|
|||
"label.dns": "DNS",
|
||||
"label.dns1": "DNS 1",
|
||||
"label.dns2": "DNS 2",
|
||||
"label.dns.add.record": "Add DNS Record",
|
||||
"label.dns.create.record": "Create DNS Record",
|
||||
"label.dns.add.server": "Add DNS Server",
|
||||
"label.dns.add.zone": "Add DNS Zone",
|
||||
"label.dns.create.zone": "Create DNS Zone",
|
||||
"label.dns.credentials": "DNS API key",
|
||||
"label.dns.delete.server": "Delete DNS Server",
|
||||
"label.dns.delete.zone": "Delete DNS Zone",
|
||||
"label.dns.externalserverid": "DNS server ID",
|
||||
"label.dns.publicdomainsuffix": "Public domain suffix",
|
||||
"label.dns.records": "DNS Records",
|
||||
"label.dns.record.name.tooltip": "The hostname or subdomain for this record (e.g. www)",
|
||||
"label.dns.record.type.tooltip": "The DNS record type",
|
||||
|
|
@ -954,6 +957,7 @@
|
|||
"label.dns.record.ttl.tooltip": "Time to live in seconds",
|
||||
"label.dns.record.url": "Instance URL",
|
||||
"label.dns.server": "DNS Server",
|
||||
"label.dnsserverid": "DNS Server ID",
|
||||
"label.dnsservername": "DNS Server name",
|
||||
"label.dns.servers": "DNS Servers",
|
||||
"label.dns.zone": "DNS Zone",
|
||||
|
|
@ -2252,6 +2256,7 @@
|
|||
"label.scope": "Scope",
|
||||
"label.scope.tooltip": "Primary Storage Pool Scope",
|
||||
"label.search": "Search",
|
||||
"label.seconds": "Seconds",
|
||||
"label.secondary.isolated.vlan.type.isolated": "Isolated",
|
||||
"label.secondary.isolated.vlan.type.promiscuous": "Promiscuous",
|
||||
"label.secondary.storage": "Secondary Storage",
|
||||
|
|
@ -3540,6 +3545,7 @@
|
|||
"message.error.remove.tungsten.routing.policy": "Removing Tungsten-Fabric Routing Policy from Network failed",
|
||||
"message.error.remove.vm.schedule": "Removing Instance Schedule failed",
|
||||
"message.error.required.input": "Please enter input",
|
||||
"message.error.required.publicdomainsuffix": "Please enter the public domain suffix if the public server is enabled",
|
||||
"message.error.reset.config": "Unable to reset config to default value",
|
||||
"message.error.retrieve.kubeconfig": "Unable to retrieve Kubernetes Cluster config",
|
||||
"message.error.routing.policy.term": "Community need to have the following format number:number",
|
||||
|
|
@ -3884,10 +3890,10 @@
|
|||
"message.success.add.egress.rule": "Successfully added new egress rule",
|
||||
"message.success.add.firewall.rule": "Successfully added new firewall rule",
|
||||
"message.success.add.dns.server": "Successfully added DNS server",
|
||||
"message.success.add.dns.zone": "Successfully added DNS zone",
|
||||
"message.success.create.dns.zone": "Successfully created DNS zone",
|
||||
"message.success.create.dns.record": "Successfully created DNS record",
|
||||
"message.success.update.dns.server": "Successfully updated DNS server",
|
||||
"message.success.update.dns.zone": "Successfully updated DNS zone",
|
||||
"message.success.add.dns.record": "Successfully added DNS record",
|
||||
"message.success.delete.dns.record": "Successfully deleted DNS record",
|
||||
"message.success.add.guest.network": "Successfully created guest Network",
|
||||
"message.success.add.gpu.device": "Successfully added GPU device",
|
||||
|
|
|
|||
|
|
@ -1522,8 +1522,7 @@ export default {
|
|||
label: 'label.dns.update.server',
|
||||
dataView: true,
|
||||
popup: true,
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/network/dns/UpdateDnsServer.vue'))),
|
||||
show: (record) => { return true }
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/network/dns/UpdateDnsServer.vue')))
|
||||
},
|
||||
{
|
||||
api: 'deleteDnsServer',
|
||||
|
|
@ -1531,8 +1530,8 @@ export default {
|
|||
label: 'label.dns.delete.server',
|
||||
message: 'message.action.delete.dns.server',
|
||||
dataView: true,
|
||||
groupAction: true,
|
||||
show: (record) => { return true },
|
||||
popup: true,
|
||||
groupAction: false,
|
||||
groupMap: (selection) => { return selection.map(x => { return { id: x } }) }
|
||||
}
|
||||
]
|
||||
|
|
@ -1542,8 +1541,8 @@ export default {
|
|||
title: 'label.dns.zones',
|
||||
icon: 'global-outlined',
|
||||
permission: ['listDnsZones'],
|
||||
columns: ['name', 'state', 'dnsservername', 'account'],
|
||||
details: ['name', 'id', 'state', 'dnsservername', 'dnsserverid', 'account', 'domainpath'],
|
||||
columns: ['name', 'state', 'dnsservername', 'account', 'description'],
|
||||
details: ['name', 'id', 'state', 'dnsservername', 'dnsserverid', 'account', 'domainpath', 'description'],
|
||||
tabs: [{
|
||||
name: 'details',
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue')))
|
||||
|
|
@ -1557,11 +1556,10 @@ export default {
|
|||
{
|
||||
api: 'createDnsZone',
|
||||
icon: 'plus-outlined',
|
||||
label: 'label.dns.add.zone',
|
||||
label: 'label.dns.create.zone',
|
||||
listView: true,
|
||||
popup: true,
|
||||
disabled: (record) => false,
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/network/dns/AddDnsZone.vue'))),
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/network/dns/CreateDnsZone.vue'))),
|
||||
show: () => {
|
||||
return true
|
||||
}
|
||||
|
|
@ -1572,7 +1570,6 @@ export default {
|
|||
label: 'label.dns.update.zone',
|
||||
dataView: true,
|
||||
popup: true,
|
||||
disabled: (record) => false,
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/network/dns/UpdateDnsZone.vue'))),
|
||||
show: (record) => { return true }
|
||||
},
|
||||
|
|
@ -1582,7 +1579,8 @@ export default {
|
|||
label: 'label.dns.delete.zone',
|
||||
message: 'message.action.delete.dns.zone',
|
||||
dataView: true,
|
||||
groupAction: true,
|
||||
popup: true,
|
||||
groupAction: false,
|
||||
disabled: (record) => false,
|
||||
show: (record) => { return true },
|
||||
groupMap: (selection) => { return selection.map(x => { return { id: x } }) }
|
||||
|
|
|
|||
|
|
@ -91,6 +91,28 @@
|
|||
:placeholder="apiParams.credentials?.description || 'Enter API Key'" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item name="externalserverid" ref="externalserverid">
|
||||
<template #label>
|
||||
<tooltip-label
|
||||
:title="$t('label.dns.externalserverid')"
|
||||
:tooltip="apiParams.externalserverid?.description" />
|
||||
</template>
|
||||
<a-input
|
||||
v-model:value="form.externalserverid"
|
||||
:placeholder="apiParams.externalserverid?.description || 'Enter Server ID of PowerDNS e.g. localhost'" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item name="publicdomainsuffix" ref="publicdomainsuffix">
|
||||
<template #label>
|
||||
<tooltip-label
|
||||
:title="$t('label.dns.publicdomainsuffix')"
|
||||
:tooltip="apiParams.publicdomainsuffix?.description" />
|
||||
</template>
|
||||
<a-input
|
||||
v-model:value="form.publicdomainsuffix"
|
||||
:placeholder="apiParams.publicdomainsuffix?.description || 'Enter Public Domain Suffix e.g. example.com'" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item name="nameservers" ref="nameservers">
|
||||
<template #label>
|
||||
<tooltip-label
|
||||
|
|
@ -103,7 +125,7 @@
|
|||
mode="tags"
|
||||
style="width: 100%"
|
||||
:token-separators="[',', ' ']"
|
||||
:placeholder="apiParams.nameservers?.description || 'ns1.example.com, ns2.example.com'" />
|
||||
:placeholder="apiParams.nameservers?.description" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item name="ispublic" ref="ispublic">
|
||||
|
|
@ -146,8 +168,10 @@ export default {
|
|||
url: '',
|
||||
provider: '',
|
||||
port: 8081,
|
||||
nameservers: '',
|
||||
ispublic: false
|
||||
nameservers: [],
|
||||
ispublic: false,
|
||||
publicdomainsuffix: '',
|
||||
externalserverid: 'localhost'
|
||||
},
|
||||
rules: {},
|
||||
fetchingProviders: false,
|
||||
|
|
@ -158,9 +182,22 @@ export default {
|
|||
this.apiParams = this.$getApiParams('addDnsServer') || {}
|
||||
this.rules = {
|
||||
name: [{ required: true, message: this.$t('message.error.required.input') }],
|
||||
url: [{ required: true, message: this.$t('message.error.required.input') }],
|
||||
url: [
|
||||
{ required: true, message: this.$t('message.error.required.input') },
|
||||
{ validator: this.validateUrl }
|
||||
],
|
||||
port: [
|
||||
{ required: true, message: this.$t('message.error.required.input') },
|
||||
{ validator: this.validatePort }
|
||||
],
|
||||
provider: [{ required: true, message: this.$t('message.error.required.input') }],
|
||||
credentials: [{ required: true, message: this.$t('message.error.required.input') }]
|
||||
credentials: [{ required: true, message: this.$t('message.error.required.input') }],
|
||||
externalserverid: [{ required: true, message: this.$t('message.error.required.input') }],
|
||||
nameservers: [
|
||||
{ required: true, type: 'array', min: 1, message: this.$t('message.error.required.input') },
|
||||
{ validator: this.validateNameservers }
|
||||
],
|
||||
publicdomainsuffix: [{ validator: this.validatePublicDomainSuffix }]
|
||||
}
|
||||
this.fetchProviders()
|
||||
},
|
||||
|
|
@ -177,9 +214,22 @@ export default {
|
|||
}
|
||||
this.loading = true
|
||||
try {
|
||||
await postAPI('addDnsServer', this.form)
|
||||
const params = {
|
||||
name: this.form.name.trim(),
|
||||
url: this.form.url?.trim().replace(/\/$/, ''),
|
||||
port: this.form.port,
|
||||
provider: this.form.provider,
|
||||
credentials: this.form.credentials,
|
||||
externalserverid: this.form.externalserverid.trim(),
|
||||
nameservers: this.form.nameservers?.map(ns => ns.toLowerCase().trim()).filter(Boolean),
|
||||
ispublic: this.form.ispublic
|
||||
}
|
||||
if (this.form.ispublic) {
|
||||
params.publicdomainsuffix = this.form.publicdomainsuffix?.trim().toLowerCase()
|
||||
}
|
||||
await postAPI('addDnsServer', params)
|
||||
this.$notification.success({
|
||||
message: this.$t('label.add.dns.server'),
|
||||
message: this.$t('label.dns.add.server'),
|
||||
description: this.$t('message.success.add.dns.server')
|
||||
})
|
||||
this.$emit('refresh-data')
|
||||
|
|
@ -213,6 +263,68 @@ export default {
|
|||
} finally {
|
||||
this.fetchingProviders = false
|
||||
}
|
||||
},
|
||||
validateUrl (rule, value) {
|
||||
if (!value) return Promise.resolve()
|
||||
try {
|
||||
const parsed = new URL(value)
|
||||
if (!['http:', 'https:'].includes(parsed.protocol)) {
|
||||
return Promise.reject(new Error('URL must start with http:// or https://'))
|
||||
}
|
||||
if (parsed.port) {
|
||||
return Promise.reject(new Error('Do not include port in URL. Use the port field instead.'))
|
||||
}
|
||||
} catch (e) {
|
||||
return Promise.reject(new Error('Invalid URL format'))
|
||||
}
|
||||
return Promise.resolve()
|
||||
},
|
||||
validatePort (rule, value) {
|
||||
if (value === undefined || value === null) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
if (value < 1 || value > 65535) {
|
||||
return Promise.reject(new Error('Port must be between 1 and 65535'))
|
||||
}
|
||||
|
||||
return Promise.resolve()
|
||||
},
|
||||
validateNameservers (rule, value) {
|
||||
if (!value || !value.length) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
const fqdnRegex = /^(?=.{1,253}$)(?!-)[A-Za-z0-9-]{1,63}(?<!-)(\.[A-Za-z]{2,})+$/
|
||||
|
||||
for (const ns of value) {
|
||||
if (!fqdnRegex.test(ns)) {
|
||||
return Promise.reject(new Error('Invalid nameserver'))
|
||||
}
|
||||
}
|
||||
|
||||
if (new Set(value).size !== value.length) {
|
||||
return Promise.reject(new Error('Nameservers must be unique'))
|
||||
}
|
||||
|
||||
return Promise.resolve()
|
||||
},
|
||||
validatePublicDomainSuffix (rule, value) {
|
||||
if (!this.form.ispublic) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
if (!value) {
|
||||
return Promise.reject(new Error(this.$t('message.error.required.publicdomainsuffix')))
|
||||
}
|
||||
|
||||
const fqdnRegex = /^(?=.{1,253}$)(?!-)[A-Za-z0-9-]{1,63}(?<!-)(\.[A-Za-z]{2,})+$/
|
||||
|
||||
if (!fqdnRegex.test(value)) {
|
||||
return Promise.reject(new Error('Invalid domain suffix'))
|
||||
}
|
||||
|
||||
return Promise.resolve()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ import { postAPI } from '@/api'
|
|||
import TooltipLabel from '@/components/widgets/TooltipLabel'
|
||||
|
||||
export default {
|
||||
name: 'AddDnsRecord',
|
||||
name: 'CreateDnsRecord',
|
||||
components: {
|
||||
TooltipLabel
|
||||
},
|
||||
|
|
@ -147,13 +147,35 @@ export default {
|
|||
}
|
||||
this.loading = true
|
||||
try {
|
||||
await postAPI('addDnsRecord', {
|
||||
const params = {
|
||||
dnszoneid: this.resource.id,
|
||||
...this.form
|
||||
})
|
||||
this.$notification.success({
|
||||
message: this.$t('label.dns.add.record'),
|
||||
description: this.$t('message.success.add.dns.record')
|
||||
name: this.form.name,
|
||||
type: this.form.type,
|
||||
contents: this.form.contents.join(','),
|
||||
ttl: this.form.ttl
|
||||
}
|
||||
const response = await postAPI('createDnsRecord', params)
|
||||
const jobId = response.creatednsrecordresponse.jobid
|
||||
if (!jobId) {
|
||||
this.$notification.error({
|
||||
message: this.$t('message.request.failed'),
|
||||
description: 'Failed to get jobid for createDnsRecord',
|
||||
duration: 0
|
||||
})
|
||||
}
|
||||
await this.$pollJob({
|
||||
jobId: jobId,
|
||||
title: this.$t('label.dns.create.record'),
|
||||
description: this.$t('label.creating.dns.record'),
|
||||
successMethod: () => {
|
||||
this.$notification.success({
|
||||
message: this.$t('label.dns.create.record'),
|
||||
description: this.$t('message.success.create.dns.record')
|
||||
})
|
||||
},
|
||||
loadingMessage: `${this.$t('label.dns.create.record')} ${this.$t('label.in.progress')}`,
|
||||
catchMessage: this.$t('error.fetching.async.job.result'),
|
||||
action: { isFetchData: false }
|
||||
})
|
||||
this.$emit('refresh-data')
|
||||
this.closeAction()
|
||||
|
|
@ -58,6 +58,15 @@
|
|||
</a-select>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item name="description" ref="description">
|
||||
<template #label>
|
||||
<tooltip-label :title="$t('label.description')" :tooltip="apiParams.description.description"/>
|
||||
</template>
|
||||
<a-input
|
||||
v-model:value="form.description"
|
||||
:placeholder="apiParams.description.description"/>
|
||||
</a-form-item>
|
||||
|
||||
<div class="action-button">
|
||||
<a-button @click="closeAction">
|
||||
{{ $t('label.cancel') }}
|
||||
|
|
@ -79,7 +88,7 @@ import { getAPI, postAPI } from '@/api'
|
|||
import TooltipLabel from '@/components/widgets/TooltipLabel'
|
||||
|
||||
export default {
|
||||
name: 'AddDnsZone',
|
||||
name: 'CreateDnsZone',
|
||||
components: {
|
||||
TooltipLabel
|
||||
},
|
||||
|
|
@ -89,7 +98,8 @@ export default {
|
|||
apiParams: {},
|
||||
form: {
|
||||
name: '',
|
||||
dnsserverid: undefined
|
||||
dnsserverid: undefined,
|
||||
description: ''
|
||||
},
|
||||
rules: {},
|
||||
fetchingServers: false,
|
||||
|
|
@ -121,10 +131,34 @@ export default {
|
|||
this.loading = true
|
||||
|
||||
try {
|
||||
await postAPI('createDnsZone', this.form)
|
||||
this.$notification.success({
|
||||
message: this.$t('label.dns.add.zone'),
|
||||
description: this.$t('message.success.add.dns.zone')
|
||||
const params = {
|
||||
name: this.form.name.trim(),
|
||||
dnsserverid: this.form.dnsserverid,
|
||||
description: this.form.description?.trim()
|
||||
}
|
||||
|
||||
const response = await postAPI('createDnsZone', params)
|
||||
const jobId = response.creatednszoneresponse.jobid
|
||||
if (!jobId) {
|
||||
this.$notification.error({
|
||||
message: this.$t('message.request.failed'),
|
||||
description: 'Failed to get jobid for CreateDnsZone',
|
||||
duration: 0
|
||||
})
|
||||
}
|
||||
await this.$pollJob({
|
||||
jobId: jobId,
|
||||
title: this.$t('label.dns.create.zone'),
|
||||
description: this.$t('label.creating.dns.zone'),
|
||||
successMethod: () => {
|
||||
this.$notification.success({
|
||||
message: this.$t('label.dns.create.zone'),
|
||||
description: this.$t('message.success.create.dns.zone')
|
||||
})
|
||||
},
|
||||
loadingMessage: `${this.$t('label.dns.create.zone')} ${this.$t('label.in.progress')}`,
|
||||
catchMessage: this.$t('error.fetching.async.job.result'),
|
||||
action: { isFetchData: false }
|
||||
})
|
||||
this.$emit('refresh-data')
|
||||
this.closeAction()
|
||||
|
|
@ -22,8 +22,9 @@
|
|||
shape="round"
|
||||
style="float: right;margin-bottom: 10px; z-index: 8"
|
||||
@click="() => { showAddForm = true }">
|
||||
<template #icon><plus-outlined /></template>
|
||||
{{ $t('label.dns.add.record') }}
|
||||
<!-- <template #icon><plus-outlined /></template> -->
|
||||
{{ $t('label.dns.create.record') }}
|
||||
<plus-outlined style="margin-left: 5px;" />
|
||||
</a-button>
|
||||
<br />
|
||||
<br />
|
||||
|
|
@ -40,7 +41,10 @@
|
|||
<template v-if="column.dataIndex === 'contents'">
|
||||
<a-tag v-for="item in record.contents" :key="item">{{ item }}</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === 'actions'">
|
||||
<template v-if="column.dataIndex === 'ttl'">
|
||||
{{ record.ttl }}
|
||||
</template>
|
||||
<template v-if="column.key === 'actions' && record.type !== 'NS'">
|
||||
<a-popconfirm
|
||||
:title="$t('message.confirm.delete.dns.record')"
|
||||
@confirm="handleDeleteRecord(record)"
|
||||
|
|
@ -79,14 +83,14 @@
|
|||
<a-modal
|
||||
v-if="showAddForm"
|
||||
:visible="showAddForm"
|
||||
:title="$t('label.dns.add.record')"
|
||||
:title="$t('label.dns.create.record')"
|
||||
:maskClosable="false"
|
||||
:closable="true"
|
||||
:footer="null"
|
||||
@cancel="() => { showAddForm = false }"
|
||||
centered
|
||||
width="auto">
|
||||
<AddDnsRecord
|
||||
<CreateDnsRecord
|
||||
:resource="resource"
|
||||
@refresh-data="fetchData"
|
||||
@close-action="showAddForm = false" />
|
||||
|
|
@ -97,13 +101,13 @@
|
|||
<script>
|
||||
import { getAPI, postAPI } from '@/api'
|
||||
import TooltipButton from '@/components/widgets/TooltipButton'
|
||||
import AddDnsRecord from '@/views/network/dns/AddDnsRecord'
|
||||
import CreateDnsRecord from '@/views/network/dns/CreateDnsRecord'
|
||||
|
||||
export default {
|
||||
name: 'DnsRecordsTab',
|
||||
components: {
|
||||
TooltipButton,
|
||||
AddDnsRecord
|
||||
CreateDnsRecord
|
||||
},
|
||||
props: {
|
||||
resource: {
|
||||
|
|
@ -137,7 +141,7 @@ export default {
|
|||
dataIndex: 'contents'
|
||||
},
|
||||
{
|
||||
title: this.$t('label.ttl'),
|
||||
title: this.$t('label.ttl') + ' (' + this.$t('label.seconds') + ')',
|
||||
dataIndex: 'ttl'
|
||||
},
|
||||
{
|
||||
|
|
@ -180,7 +184,16 @@ export default {
|
|||
})
|
||||
},
|
||||
handleDeleteRecord (record) {
|
||||
postAPI('deleteDnsRecord', { id: record.id }).then(() => {
|
||||
const params = {
|
||||
dnszoneid: this.resource.id,
|
||||
name: record.name,
|
||||
type: record.type,
|
||||
contents: record.contents.join(','),
|
||||
ttl: record.ttl
|
||||
}
|
||||
console.log('DeleteDnsRecord params', params)
|
||||
|
||||
postAPI('deleteDnsRecord', params).then(() => {
|
||||
this.$notification.success({
|
||||
message: this.$t('message.success.delete.dns.record')
|
||||
})
|
||||
|
|
|
|||
|
|
@ -24,15 +24,15 @@
|
|||
:rules="rules"
|
||||
layout="vertical">
|
||||
|
||||
<a-form-item name="name" ref="name">
|
||||
<a-form-item name="description" ref="description">
|
||||
<template #label>
|
||||
<tooltip-label
|
||||
:title="$t('label.name')"
|
||||
:tooltip="apiParams.name?.description" />
|
||||
:title="$t('label.description')"
|
||||
:tooltip="apiParams.description?.description" />
|
||||
</template>
|
||||
<a-input
|
||||
v-model:value="form.name"
|
||||
:placeholder="apiParams.name?.description"
|
||||
v-model:value="form.description"
|
||||
:placeholder="apiParams.description?.description"
|
||||
v-focus="true" />
|
||||
</a-form-item>
|
||||
|
||||
|
|
@ -72,17 +72,14 @@ export default {
|
|||
loading: false,
|
||||
apiParams: {},
|
||||
form: {
|
||||
name: ''
|
||||
description: ''
|
||||
},
|
||||
rules: {}
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.apiParams = this.$getApiParams('updateDnsZone') || {}
|
||||
this.rules = {
|
||||
name: [{ required: true, message: this.$t('message.error.required.input') }]
|
||||
}
|
||||
this.form.name = this.resource.name || ''
|
||||
this.form.description = this.resource.description || ''
|
||||
},
|
||||
methods: {
|
||||
async handleSubmit () {
|
||||
|
|
@ -98,9 +95,8 @@ export default {
|
|||
}
|
||||
|
||||
this.loading = true
|
||||
|
||||
try {
|
||||
await postAPI('updateDnsZone', { id: this.resource.id, name: this.form.name })
|
||||
await postAPI('updateDnsZone', { id: this.resource.id, description: this.form.description })
|
||||
|
||||
this.$notification.success({
|
||||
message: this.$t('label.dns.update.zone'),
|
||||
|
|
|
|||
Loading…
Reference in New Issue