To make every new VPS be assigned to a domain and optionally have own CNAME aliased to a DNS A record, you have to modify respectively the VPS creation wizard and the views plugged into it as described in this document.
In this document:
Integration with DNS adds the following requirements to the wizard:
The wizard must analyze if a request for creating a VPS contains a domain APS ID, which indicates if the wizard is started from a domain profile. In this is a case, the wizard must send the ID to the first plugged application view. The latter must use the received domain APS ID to make the respective domain preselected for a new VPS.
If the CNAME is required for the new VPS, the wizard must create such a DNS record.
The first plugged view must require a customer to select one of available domains for the new VPS and to specify if the CNAME is required.
Continue the demo project from the previous step.
Follow these steps to meet the above requirements in the ui/vps-wizard.js
file.
In the main callback function, define a function for creating the CNAME record:
Note
If in your own project, you also need to create various other DNS records, modify the function to make it more general and able to create the needed type of DNS record.
function createDnsRecord(vps, domain) {
var jsonData = {
"aps": {
"type": "http://aps-standard.org/types/dns1p/record/cname/1.0"
},
"RRState": "active",
"TTL": 3600,
"source": vps.name + "." + domain + ".",
"cname": "vps." + domain + ".",
"zone": {
"aps": {
"id": vps.domain.aps.id
}
}
};
return xhr("/aps/2/resources/" + vps.aps.id + "/records", {
method: "POST",
data: JSON.stringify(jsonData)
});
}
In the onNext
handler, send the domain APS ID to the first view if the wizard has received
that ID:
onNext: function() {
/* Direct a user to the first view */
if (aps.context.params.domainApsId) { // If we've come here from the DNS Manager
aps.apsc.next(aps.context.params.domainApsId);
}
else aps.apsc.next();
},
In the onSubmit
handler, create the CNAME record if it is required:
onSubmit: function() {
/* Specify the subscription whose resource will be used */
aps.context.subscriptionId = aps.context.vars.context.aps.subscription;
/* Declare the data store */
var store = new Store({
apsType: "http://aps-standard.org/samples/dns1p/vps/1.0",
target: "/aps/2/resources/" + aps.context.vars.context.aps.id + "/vpses"
});
/* Receive data from the 1st view and save the new VPS */
var newVPS =
aps.context.wizardData["http://aps-standard.org/samples/dns1p#server-new-1"];
store.put(newVPS)
.then(function(vps) {
if(newVPS.cnameRecord)
return createDnsRecord(vps, newVPS.domainName);
})
.then(function() {
aps.apsc.gotoView("servers");
}, displayError
);
}
The existing ui/wizard/server-new-1.js
file should be modified in several places.
Declare two store objects to operate the domains. One, aps/Memory
, must be used
to present a list of domains for selection.
The other one, aps/ResourceStore
, must interact with the APS controller. In the init
function,
it is not recommended to get resources from the APS controller, since this is a long operations.
So, the domain list will be an aps/Memory
object with the initially empty data.
Require the JS modules in the top level define
function as in the following list:
define([
"dojo/_base/declare",
"dojox/mvc/at",
"dojox/mvc/getStateful",
"aps/View",
"aps/ResourceStore",
"aps/Memory",
/* Include JSON file that defines the VPS default properties */
"aps/json!./newvps.json"
],
Declare the respective arguments in the main callback function:
function (declare, at, getStateful, View, Store, Memory, newVPS) {
In the init
method, declare the domain store object as a global object:
this.domainStore = new Memory({
data: [],
idProperty: "aps.id"
});
Add a field set that allows a user to select a domain and require the CNAME for the VPS in this domain.
Make it the last child in the top most aps/Panel
:
["aps/FieldSet", { id: this.genId("srvNew1_domains") },
[
["aps/Select", {
id: this.genId("srvNew1_domainSelect"),
gridSize: 'md-3 xs-12',
store: this.domainStore,
labelAttr: "name",
value: at(this.vpsModel.data.domain.aps, "id")
}],
["aps/CheckBox", {
id: this.genId("srvNew1_domainCname"),
gridSize: 'md-3 xs-12',
description: 'CNAME record',
checked: at(this.vpsModel.data, "cnameRecord")
}]
]]
Keynotes:
The newly declared domainStore
is used to select domains.
In the selection list, the domain name
property will be presented as a label.
The selected domain is linked to the VPS through the domain
link defined in
the Domain Service type.
The CNAME record checkbox is synced with the VPS cnameRecord
property.
Update the onContext
method to do all required operations with the APS controller.
onContext: function() {
if (!aps.context.wizardData["http://aps-standard.org/samples/dns1p#server-new-1"])
this.vpsModel.set("data", newVPS);
var store = new Store({
target: "/aps/2/resources/",
apsType: "http://aps-standard.org/types/dns/zone/1.1"
});
/* Retrieve all customer's domains */
store.query().then(function(domains) {
/* Refresh the store */
this.domainStore.setData(domains);
var domainSelection = this.byId("srvNew1_domainSelect");
domainSelection.set("store", this.domainStore);
/* Define the selected domain */
if (aps.context.wizardData["http://aps-standard.org/samples/dns1p#vps-wizard"]) {
this.vpsModel.data.domain.aps.set(
"id",
aps.context.wizardData["http://aps-standard.org/samples/dns1p#vps-wizard"]
);
}
else domainSelection.set("value", domains[0].aps.id);
aps.apsc.hideLoading();
}.bind(this));
}
Keynotes:
The store
operates the resources of the Hosted Domain type. It retrieves all
domains available for the customer and assign this list to the domainStore.data
array. Then, the store
of the domain selection widget is updated.
Once the selection list is defined, the method identifies a domain to be pre-selected. If the VPS wizard sends a domain APS ID here, the specified domain must be pre-selected. Otherwise, the first domain from the list is pre-selected.
Modify the onNext
handler to identify the selected domain name before proceeding to the next step:
onNext: function() {
/* Get domain name from the selection list and set the VPS domainName property*/
var selectWidget = this.byId("srvNew1_domainSelect");
var domainId = selectWidget.get("value");
this.vpsModel.data.set("domainName", selectWidget.getOption(domainId)[0].label);
/* Proceed to the next step */
aps.apsc.next(this.vpsModel.data);
}
The code operates the selection widget to identify both, the APS ID and the name of the selected domain.
The last step in VPS creation must show the selected domain name and display if the CNAME is required by means of an icon.
For the above reasons, modify the ui/wizard/server-new-last.js
file as follows.
In the main callback function, declare a global variable to specify if the CNAME was required in the previous step:
var cNameNeeded = "false";
In the widget definition return
statement, add two output widgets presenting the DNS properties:
["aps/Output", {
id: this.genId("srvNew_domain"),
label: "Domain",
value: at(aps.app.model.newVPS, "domainName")
}],
["aps/Status", {
id: this.gendId("srvNew_cName"),
label: "CNAME",
status: cNameNeeded,
useIcon: true,
statusInfo: {
"no": {
"label": "",
"type": "disabled",
"icon": "fa-minus"
},
"yes": {
"label": "",
"type": "success",
"icon": "fa-check"
}}
}]
In the above code, the former widget prints out the domain name, and the latter one is an icon indicating if the CNAME is required (success type) or not (disabled type).
In the onContext
handler, define the actual value of the cNameNeeded
variable and then
update the widget that shows if the CNAME is needed:
cNameNeeded = (this.vpsModel.data.get("cnameRecord")) ? "yes" : "no";
this.byId("srvNew_cName").set("status", cNameNeeded);
On completion of this step, the application is partially integrated with the Domain Manager in terms of providing tools for linking VPSes to domains and creating DNS records for them.
The project files you have updated are similar to the respective files in the
sample package
.
In the next project phase, you will complete the integration by embedding custom view-plugins into the Domain Manager views.