API v2 Dashboard
A Horizon dashboard based on the Designate v2 API. Using some of the latest Angular code available in Mitaka Horizon and a passthough API to avoid the need for the designate-client.. To view the new panel: - copy the following: * designatedashboard/enabled/_1710_project_dns_panel_group.py * designatedashboard/enabled/_1721_project_ngdns_panel.py * designatedashboard/enabled/_1722_dns_reversedns_panel.py into horizon/openstack_dashboard/local/enabled/ and restart horizon. Change-Id: I726bffbdc9514e1dc04dcb8e888d9808c6203867
This commit is contained in:
parent
5627ddb4a6
commit
54e46c9275
16
designatedashboard/api/rest/__init__.py
Normal file
16
designatedashboard/api/rest/__init__.py
Normal file
@ -0,0 +1,16 @@
|
||||
# (c) Copyright <year(s)> Hewlett Packard Enterprise Development LP
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
"""REST API for Horizon dashboard Javascript code.
|
||||
"""
|
||||
from . import passthrough # noqa
|
114
designatedashboard/api/rest/passthrough.py
Normal file
114
designatedashboard/api/rest/passthrough.py
Normal file
@ -0,0 +1,114 @@
|
||||
# Copyright 2016, Hewlett Packard Enterprise Development, LP
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
"""API for the passthrough service.
|
||||
"""
|
||||
from django.conf import settings
|
||||
from django.views import generic
|
||||
import functools
|
||||
import logging
|
||||
import requests
|
||||
from requests.exceptions import HTTPError
|
||||
|
||||
from horizon import exceptions
|
||||
from openstack_dashboard.api import base
|
||||
from openstack_dashboard.api.rest import urls
|
||||
from openstack_dashboard.api.rest import utils as rest_utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _passthrough_request(request_method, url,
|
||||
request, data=None, params=None):
|
||||
"""Makes a request to the appropriate service API with an optional payload.
|
||||
|
||||
Should set any necessary auth headers and SSL parameters.
|
||||
"""
|
||||
service = 'dns' \
|
||||
''
|
||||
# Set verify if a CACERT is set and SSL_NO_VERIFY isn't True
|
||||
verify = getattr(settings, 'OPENSTACK_SSL_CACERT', None)
|
||||
if getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False):
|
||||
verify = False
|
||||
|
||||
response = request_method(
|
||||
_get_service_url(request, service) + url,
|
||||
headers={'X-Auth-Token': request.user.token.id},
|
||||
json=data,
|
||||
verify=verify,
|
||||
params=params
|
||||
)
|
||||
|
||||
try:
|
||||
response.raise_for_status()
|
||||
except HTTPError as e:
|
||||
LOG.debug(e.response.content)
|
||||
for error in rest_utils.http_errors:
|
||||
if (e.response.status_code == getattr(error, 'status_code', 0) and
|
||||
exceptions.HorizonException in error.__bases__):
|
||||
raise error
|
||||
raise
|
||||
|
||||
return response
|
||||
|
||||
|
||||
# Create some convenience partial functions
|
||||
passthrough_get = functools.partial(_passthrough_request, requests.get)
|
||||
passthrough_post = functools.partial(_passthrough_request, requests.post)
|
||||
passthrough_put = functools.partial(_passthrough_request, requests.put)
|
||||
passthrough_patch = functools.partial(_passthrough_request, requests.patch)
|
||||
passthrough_delete = functools.partial(_passthrough_request, requests.delete)
|
||||
|
||||
|
||||
def _get_service_url(request, service):
|
||||
"""Get service's URL from keystone; allow an override in settings"""
|
||||
service_url = getattr(settings, service.upper() + '_URL', None)
|
||||
try:
|
||||
service_url = base.url_for(request, service)
|
||||
except exceptions.ServiceCatalogException:
|
||||
pass
|
||||
# Currently the keystone endpoint is http://host:port/
|
||||
# without the version.
|
||||
return service_url
|
||||
|
||||
|
||||
@urls.register
|
||||
class Passthrough(generic.View):
|
||||
"""Pass-through API for executing service requests.
|
||||
|
||||
Horizon only adds auth and CORS proxying.
|
||||
"""
|
||||
url_regex = r'dns/(?P<path>.+)$'
|
||||
|
||||
@rest_utils.ajax()
|
||||
def get(self, request, path):
|
||||
return passthrough_get(path, request).json()
|
||||
|
||||
@rest_utils.ajax()
|
||||
def post(self, request, path):
|
||||
data = dict(request.DATA) if request.DATA else {}
|
||||
return passthrough_post(path, request, data).json()
|
||||
|
||||
@rest_utils.ajax()
|
||||
def put(self, request, path):
|
||||
data = dict(request.DATA) if request.DATA else {}
|
||||
return passthrough_put(path, request, data).json()
|
||||
|
||||
@rest_utils.ajax()
|
||||
def patch(self, request, path):
|
||||
data = dict(request.DATA) if request.DATA else {}
|
||||
return passthrough_patch(path, request, data).json()
|
||||
|
||||
@rest_utils.ajax()
|
||||
def delete(self, request, path):
|
||||
return passthrough_delete(path, request).json()
|
@ -23,6 +23,7 @@ from openstack_dashboard.api.network import tenant_floating_ip_list
|
||||
from openstack_dashboard.api.nova import server_list
|
||||
|
||||
from designatedashboard import api
|
||||
from designatedashboard.api import rest # noqa
|
||||
|
||||
from .forms import DomainCreate # noqa
|
||||
from .forms import DomainUpdate # noqa
|
||||
|
1
designatedashboard/dashboards/project/ngdns/__init__.py
Normal file
1
designatedashboard/dashboards/project/ngdns/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from designatedashboard.api import rest # noqa
|
@ -0,0 +1,25 @@
|
||||
# (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
import horizon
|
||||
from openstack_dashboard.dashboards.project import dashboard
|
||||
|
||||
|
||||
class ReverseDns(horizon.Panel):
|
||||
name = _("Reverse DNS")
|
||||
slug = 'reverse_dns'
|
||||
permissions = ('openstack.services.dns',)
|
||||
|
||||
dashboard.Project.register(ReverseDns)
|
@ -0,0 +1,22 @@
|
||||
# (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from designatedashboard.dashboards.project.ngdns.reverse_dns import views
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url('', views.IndexView.as_view(), name='index'),
|
||||
]
|
@ -0,0 +1,19 @@
|
||||
# (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.views import generic
|
||||
|
||||
|
||||
class IndexView(generic.TemplateView):
|
||||
template_name = 'angular.html'
|
25
designatedashboard/dashboards/project/ngdns/zones/panel.py
Normal file
25
designatedashboard/dashboards/project/ngdns/zones/panel.py
Normal file
@ -0,0 +1,25 @@
|
||||
# (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
import horizon
|
||||
from openstack_dashboard.dashboards.project import dashboard
|
||||
|
||||
|
||||
class Zones(horizon.Panel):
|
||||
name = _("Zones")
|
||||
slug = 'dnszones'
|
||||
permissions = ('openstack.services.dns',)
|
||||
|
||||
dashboard.Project.register(Zones)
|
22
designatedashboard/dashboards/project/ngdns/zones/urls.py
Normal file
22
designatedashboard/dashboards/project/ngdns/zones/urls.py
Normal file
@ -0,0 +1,22 @@
|
||||
# (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from designatedashboard.dashboards.project.ngdns.zones import views
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url('', views.IndexView.as_view(), name='index'),
|
||||
]
|
19
designatedashboard/dashboards/project/ngdns/zones/views.py
Normal file
19
designatedashboard/dashboards/project/ngdns/zones/views.py
Normal file
@ -0,0 +1,19 @@
|
||||
# (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.views import generic
|
||||
|
||||
|
||||
class IndexView(generic.TemplateView):
|
||||
template_name = 'angular.html'
|
@ -32,3 +32,5 @@ ADD_EXCEPTIONS = {
|
||||
# Python panel class of the PANEL to be added.
|
||||
ADD_PANEL = (
|
||||
'designatedashboard.dashboards.project.dns_domains.panel.DNSDomains')
|
||||
|
||||
DISABLED = True
|
||||
|
40
designatedashboard/enabled/_1721_dns_zones_panel.py
Normal file
40
designatedashboard/enabled/_1721_dns_zones_panel.py
Normal file
@ -0,0 +1,40 @@
|
||||
# Copyright 2013 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from designatedashboard import exceptions
|
||||
|
||||
# The name of the panel to be added to HORIZON_CONFIG. Required.
|
||||
PANEL = 'dnszones'
|
||||
# The name of the dashboard the PANEL associated with. Required.
|
||||
PANEL_DASHBOARD = 'project'
|
||||
# The name of the panel group the PANEL is associated with.
|
||||
PANEL_GROUP = 'dns'
|
||||
|
||||
ADD_EXCEPTIONS = {
|
||||
'recoverable': exceptions.RECOVERABLE,
|
||||
'not_found': exceptions.NOT_FOUND,
|
||||
'unauthorized': exceptions.UNAUTHORIZED,
|
||||
}
|
||||
|
||||
ADD_INSTALLED_APPS = ['designatedashboard']
|
||||
|
||||
# Python panel class of the PANEL to be added.
|
||||
ADD_PANEL = (
|
||||
'designatedashboard.dashboards.project.ngdns.zones.panel.Zones')
|
||||
|
||||
ADD_ANGULAR_MODULES = ['designatedashboard']
|
||||
|
||||
ADD_SCSS_FILES = ['designatedashboard/designatedashboard.scss']
|
||||
|
||||
AUTO_DISCOVER_STATIC_FILES = True
|
38
designatedashboard/enabled/_1722_dns_reversedns_panel.py
Normal file
38
designatedashboard/enabled/_1722_dns_reversedns_panel.py
Normal file
@ -0,0 +1,38 @@
|
||||
# Copyright 2013 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from designatedashboard import exceptions
|
||||
|
||||
# The name of the panel to be added to HORIZON_CONFIG. Required.
|
||||
PANEL = 'reverse_dns'
|
||||
# The name of the dashboard the PANEL associated with. Required.
|
||||
PANEL_DASHBOARD = 'project'
|
||||
# The name of the panel group the PANEL is associated with.
|
||||
PANEL_GROUP = 'dns'
|
||||
|
||||
ADD_EXCEPTIONS = {
|
||||
'recoverable': exceptions.RECOVERABLE,
|
||||
'not_found': exceptions.NOT_FOUND,
|
||||
'unauthorized': exceptions.UNAUTHORIZED,
|
||||
}
|
||||
|
||||
# Python panel class of the PANEL to be added.
|
||||
ADD_PANEL = (
|
||||
'designatedashboard.dashboards.project.ngdns.reverse_dns.panel.ReverseDns')
|
||||
|
||||
ADD_ANGULAR_MODULES = ['designatedashboard']
|
||||
|
||||
ADD_SCSS_FILES = ['designatedashboard/designatedashboard.scss']
|
||||
|
||||
AUTO_DISCOVER_STATIC_FILES = True
|
@ -0,0 +1,78 @@
|
||||
/**
|
||||
* (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc overview
|
||||
* @ngname designatedashboard
|
||||
*
|
||||
* @description
|
||||
* Provides the services and widgets required
|
||||
* to support and display the project search panel.
|
||||
*/
|
||||
angular
|
||||
.module('designatedashboard', [
|
||||
'ngRoute',
|
||||
'designatedashboard.resources'
|
||||
])
|
||||
.constant(
|
||||
'designatedashboard.apiPassthroughUrl', '/api/dns/')
|
||||
.config(config)
|
||||
.run(run);
|
||||
|
||||
config.$inject = [
|
||||
'$provide',
|
||||
'$routeProvider',
|
||||
'$windowProvider'
|
||||
];
|
||||
|
||||
/**
|
||||
* @name designatedashboard.basePath
|
||||
* @description Base path for the project dashboard
|
||||
*
|
||||
* @param {function} $provide ng provide service
|
||||
*
|
||||
* @param {function} $routeProvider ng route service
|
||||
*
|
||||
* @param {function} $windowProvider NG window provider
|
||||
*
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function config($provide, $routeProvider, $windowProvider) {
|
||||
var path = $windowProvider.$get().STATIC_URL + 'designatedashboard/';
|
||||
$provide.constant('designatedashboard.basePath', path);
|
||||
|
||||
$routeProvider
|
||||
.when('/project/dnszones/', {
|
||||
templateUrl: path + 'zones.html'
|
||||
})
|
||||
.when('/project/reverse_dns/', {
|
||||
templateUrl: path + 'reverse_dns.html'
|
||||
});
|
||||
}
|
||||
|
||||
run.$inject = [
|
||||
'horizon.framework.conf.resource-type-registry.service',
|
||||
'designatedashboard.basePath'
|
||||
];
|
||||
|
||||
function run(registry, basePath) {
|
||||
//registry.setDefaultSummaryTemplateUrl(basePath + 'table/default-drawer.html');
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,66 @@
|
||||
/**
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc overview
|
||||
* @ngname designatedashboard.resources.os-designate-floatingip.actions
|
||||
*
|
||||
* @description
|
||||
* Provides all of the actions for DNS Floating IPs.
|
||||
*/
|
||||
angular.module('designatedashboard.resources.os-designate-floatingip.actions', [
|
||||
'horizon.framework.conf',
|
||||
'horizon.app.core'
|
||||
])
|
||||
.run(run);
|
||||
|
||||
run.$inject = [
|
||||
'horizon.framework.conf.resource-type-registry.service',
|
||||
'designatedashboard.resources.os-designate-floatingip.resourceType',
|
||||
'designatedashboard.resources.os-designate-floatingip.actions.set',
|
||||
'designatedashboard.resources.os-designate-floatingip.actions.unset'
|
||||
];
|
||||
|
||||
function run(
|
||||
registry,
|
||||
resourceTypeString,
|
||||
setAction,
|
||||
unsetAction)
|
||||
{
|
||||
var resourceType = registry.getResourceType(resourceTypeString);
|
||||
|
||||
resourceType
|
||||
.itemActions
|
||||
.append({
|
||||
id: 'setFloatingIp',
|
||||
service: setAction,
|
||||
template: {
|
||||
text: gettext('Set')
|
||||
}
|
||||
})
|
||||
.append({
|
||||
id: 'unsetFloatingIp',
|
||||
service: unsetAction,
|
||||
template: {
|
||||
text: gettext('Unset')
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,170 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development Company LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use self file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('designatedashboard.resources.os-designate-floatingip.actions')
|
||||
.factory('designatedashboard.resources.os-designate-floatingip.actions.set', action);
|
||||
|
||||
action.$inject = [
|
||||
'$q',
|
||||
'designatedashboard.resources.os-designate-floatingip.api',
|
||||
'designatedashboard.resources.os-designate-floatingip.resourceType',
|
||||
'designatedashboard.resources.util',
|
||||
'horizon.app.core.openstack-service-api.serviceCatalog',
|
||||
'horizon.framework.widgets.form.ModalFormService',
|
||||
'horizon.framework.widgets.toast.service',
|
||||
'horizon.framework.widgets.modal-wait-spinner.service'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngDoc factory
|
||||
* @name designatedashboard.resources.os-designate-floatingip.actions.set
|
||||
*
|
||||
* @Description
|
||||
* Brings up the Set Floating IP modal.
|
||||
*/
|
||||
function action($q,
|
||||
api,
|
||||
resourceTypeName,
|
||||
util,
|
||||
serviceCatalog,
|
||||
schemaFormModalService,
|
||||
toast,
|
||||
waitSpinner) {
|
||||
var dnsServiceEnabled;
|
||||
var title = null; // Set once perform is called
|
||||
var formConfig = {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"ptrdname": {
|
||||
"type": "string",
|
||||
"pattern": /^.+\.$/
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"ttl": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 2147483647
|
||||
},
|
||||
}
|
||||
},
|
||||
"form": [
|
||||
{
|
||||
"key": "ptrdname",
|
||||
"title": gettext("Domain Name"),
|
||||
"description": gettext("Domain name ending in '.'"),
|
||||
"validationMessage": gettext("Domain must end with '.'"),
|
||||
"placeholder": "smtp.example.com.",
|
||||
"type": "text",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"key": "description",
|
||||
"type": "textarea",
|
||||
"title": gettext("Description"),
|
||||
"description": gettext("Details about the PTR record.")
|
||||
},
|
||||
{
|
||||
"key": "ttl",
|
||||
"title": gettext("TTL"),
|
||||
"description": gettext("Time To Live in seconds."),
|
||||
"type": "number"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var message = {
|
||||
success: gettext('Domain name PTR %s was successfully set.')
|
||||
};
|
||||
|
||||
var service = {
|
||||
initScope: initScope,
|
||||
allowed: allowed,
|
||||
perform: perform
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
/////////////////
|
||||
|
||||
function initScope() {
|
||||
dnsServiceEnabled = serviceCatalog.ifTypeEnabled('dns');
|
||||
}
|
||||
|
||||
function allowed(item) {
|
||||
return $q.all([
|
||||
// TODO (tyr) designate currently has no floating ips policy rules
|
||||
dnsServiceEnabled,
|
||||
util.notPending(item)
|
||||
]);
|
||||
}
|
||||
|
||||
function perform(item) {
|
||||
// Initialize the per-item title for use now and during submit
|
||||
title = gettext("Set Domain Name PTR for ") + item.address;
|
||||
formConfig.title = title;
|
||||
|
||||
// Get a form model based on the current item
|
||||
formConfig.model = util.getModel(formConfig.form, item);
|
||||
|
||||
// Initialize default data
|
||||
formConfig.model.ttl = formConfig.model.ttl || 3600;
|
||||
|
||||
// Remember the ID for use during submit
|
||||
formConfig.model.floatingIpId = item.id;
|
||||
|
||||
return schemaFormModalService.open(formConfig).then(onSubmit, onCancel);
|
||||
}
|
||||
|
||||
function onSubmit(context) {
|
||||
var model = angular.copy(context.model);
|
||||
var floatingIpId = formConfig.model.floatingIpId;
|
||||
|
||||
waitSpinner.showModalSpinner(title);
|
||||
return api.set(floatingIpId, model).then(onSuccess, onFailure);
|
||||
}
|
||||
|
||||
function onCancel() {
|
||||
waitSpinner.hideModalSpinner();
|
||||
}
|
||||
|
||||
function onSuccess(response) {
|
||||
waitSpinner.hideModalSpinner();
|
||||
var floatingIp = response.data;
|
||||
toast.add('success', interpolate(message.success, [floatingIp.ptrdname]));
|
||||
|
||||
// To make the result of this action generically useful, reformat the return
|
||||
// from the deleteModal into a standard form
|
||||
return {
|
||||
created: [],
|
||||
updated: [{type: resourceTypeName, id: floatingIp.id}],
|
||||
deleted: [],
|
||||
failed: []
|
||||
};
|
||||
}
|
||||
|
||||
function onFailure() {
|
||||
waitSpinner.hideModalSpinner();
|
||||
}
|
||||
}
|
||||
})();
|
@ -0,0 +1,139 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development Company LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use self file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('designatedashboard.resources.os-designate-floatingip.actions')
|
||||
.factory('designatedashboard.resources.os-designate-floatingip.actions.unset', action);
|
||||
|
||||
action.$inject = [
|
||||
'$q',
|
||||
'designatedashboard.resources.os-designate-floatingip.api',
|
||||
'designatedashboard.resources.os-designate-floatingip.resourceType',
|
||||
'designatedashboard.resources.util',
|
||||
'horizon.app.core.openstack-service-api.serviceCatalog',
|
||||
'horizon.framework.util.q.extensions',
|
||||
'horizon.framework.widgets.form.ModalFormService',
|
||||
'horizon.framework.widgets.toast.service',
|
||||
'horizon.framework.widgets.modal-wait-spinner.service'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngDoc factory
|
||||
* @name designatedashboard.resources.os-designate-floatingip.actions.unset
|
||||
*
|
||||
* @Description
|
||||
* Brings up the Unset Floating IP modal.
|
||||
*/
|
||||
function action($q,
|
||||
api,
|
||||
resourceTypeName,
|
||||
util,
|
||||
serviceCatalog,
|
||||
$qExtensions,
|
||||
schemaFormModalService,
|
||||
toast,
|
||||
waitSpinner) {
|
||||
var dnsServiceEnabled;
|
||||
var title = null; // Set on perform
|
||||
var currentFloatingIpId; // Used to remember the ID we are modifying since it isn't returned by the unset API call
|
||||
|
||||
// Unset it just a simple case of "set", but with ptrdname of 'null'
|
||||
var formConfig = {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
}
|
||||
},
|
||||
"form": [
|
||||
],
|
||||
"model": {
|
||||
}
|
||||
};
|
||||
|
||||
var message = {
|
||||
success: gettext('Domain name PTR successfully unset.')
|
||||
};
|
||||
|
||||
var service = {
|
||||
initScope: initScope,
|
||||
allowed: allowed,
|
||||
perform: perform
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
/////////////////
|
||||
|
||||
function initScope() {
|
||||
dnsServiceEnabled = serviceCatalog.ifTypeEnabled('dns');
|
||||
}
|
||||
|
||||
function allowed(item) {
|
||||
return $q.all([
|
||||
// TODO (tyr) designate currently has no floating ip policy rules
|
||||
dnsServiceEnabled,
|
||||
domainNameSet(item),
|
||||
util.notPending(item)
|
||||
]);
|
||||
}
|
||||
|
||||
function domainNameSet(item) {
|
||||
return $qExtensions.booleanAsPromise(
|
||||
angular.isString(item.ptrdname)
|
||||
);
|
||||
}
|
||||
|
||||
function perform(item) {
|
||||
title = gettext("Unset Domain Name PTR for ") + item.address;
|
||||
// Store the zone ID so it can be used on submit
|
||||
formConfig.model.floatingIpId = item.id;
|
||||
formConfig.title = title;
|
||||
return schemaFormModalService.open(formConfig).then(onSubmit, onCancel);
|
||||
}
|
||||
|
||||
function onSubmit(context) {
|
||||
waitSpinner.showModalSpinner(title);
|
||||
currentFloatingIpId = context.model.floatingIpId;
|
||||
return api.unset(currentFloatingIpId).then(onSuccess, onFailure);
|
||||
}
|
||||
|
||||
function onCancel() {
|
||||
waitSpinner.hideModalSpinner();
|
||||
}
|
||||
|
||||
function onSuccess(response) {
|
||||
waitSpinner.hideModalSpinner();
|
||||
toast.add('success', message.success);
|
||||
|
||||
// To make the result of this action generically useful, reformat the return
|
||||
// from the deleteModal into a standard form
|
||||
return {
|
||||
created: [],
|
||||
updated: [{type: resourceTypeName, id: currentFloatingIpId}],
|
||||
deleted: [],
|
||||
failed: []
|
||||
};
|
||||
}
|
||||
|
||||
function onFailure() {
|
||||
waitSpinner.hideModalSpinner();
|
||||
}
|
||||
}
|
||||
})();
|
@ -0,0 +1,121 @@
|
||||
/**
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('designatedashboard.resources.os-designate-floatingip')
|
||||
.factory('designatedashboard.resources.os-designate-floatingip.api', apiService);
|
||||
|
||||
apiService.$inject = [
|
||||
'designatedashboard.apiPassthroughUrl',
|
||||
'horizon.framework.util.http.service',
|
||||
'horizon.framework.widgets.toast.service'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @param {Object} httpService
|
||||
* @param {Object} toastService
|
||||
* @name apiService
|
||||
* @description Provides direct access to Designate Floating IP APIs.
|
||||
* @returns {Object} The service
|
||||
*/
|
||||
function apiService(apiPassthroughUrl, httpService, toastService) {
|
||||
var service = {
|
||||
list: list,
|
||||
get: get,
|
||||
set: set,
|
||||
unset: unset
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
///////////////
|
||||
|
||||
/**
|
||||
* @name list
|
||||
* @description
|
||||
* Get a list of DNS floating ips.
|
||||
*
|
||||
* The listing result is an object with property "items." Each item is
|
||||
* a floating IP PTR record.
|
||||
*
|
||||
* @param {Object} params
|
||||
* Query parameters. Optional.
|
||||
*
|
||||
* @returns {Object} The result of the API call
|
||||
*/
|
||||
function list(params) {
|
||||
var config = params ? {'params': params} : {};
|
||||
return httpService.get(apiPassthroughUrl + 'v2/reverse/floatingips', config)
|
||||
.error(function () {
|
||||
toastService.add('error', gettext('Unable to retrieve the floating ip PTRs.'));
|
||||
});
|
||||
}
|
||||
|
||||
function get(id, params) {
|
||||
var config = params ? {'params': params} : {};
|
||||
return httpService.get(apiPassthroughUrl + 'v2/reverse/floatingips/' + id, config)
|
||||
.error(function () {
|
||||
toastService.add('error', gettext('Unable to get the floating ip PTR ' + id));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @name set
|
||||
* @description
|
||||
* Set a floating ip PTR record
|
||||
*
|
||||
* @param {string} floatingIpID - ID of PTR record to unset
|
||||
* @param {Object} data
|
||||
* Specifies the PTR information to set
|
||||
*
|
||||
* @returns {Object} The updated DNS floating IP object
|
||||
*/
|
||||
function set(floatingIpID, data) {
|
||||
// The update API will not accept extra data. Restrict the input to only the allowed
|
||||
// fields
|
||||
var apiData = {
|
||||
ptrdname: data.ptrdname,
|
||||
description: data.description,
|
||||
ttl: data.ttl
|
||||
};
|
||||
return httpService.patch(apiPassthroughUrl + 'v2/reverse/floatingips/' + floatingIpID, apiData)
|
||||
.error(function () {
|
||||
toastService.add('error', gettext('Unable to set the floating IP PTR record.'));
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @name unset
|
||||
* @description
|
||||
* Unset a floating ip PTR record
|
||||
*
|
||||
* @param {string} floatingIpID - ID of PTR record to unset
|
||||
*
|
||||
* @returns {Object} The updated DNS floating IP object
|
||||
*/
|
||||
function unset(floatingIpID) {
|
||||
// Unset is just a special case of 'set'
|
||||
return set(floatingIpID, {
|
||||
ptrdname: null,
|
||||
description: null,
|
||||
ttl: null
|
||||
})
|
||||
}
|
||||
}
|
||||
}());
|
@ -0,0 +1,66 @@
|
||||
/**
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc overview
|
||||
* @ngname designatedashboard.resources.os-designate-floatingip.details
|
||||
*
|
||||
* @description
|
||||
* Provides details features for floating IPs.
|
||||
*/
|
||||
angular.module('designatedashboard.resources.os-designate-floatingip.details',
|
||||
['horizon.framework.conf', 'horizon.app.core'])
|
||||
.run(run);
|
||||
|
||||
run.$inject = [
|
||||
'designatedashboard.resources.os-designate-floatingip.resourceType',
|
||||
'designatedashboard.resources.os-designate-floatingip.api',
|
||||
'designatedashboard.resources.os-designate-floatingip.basePath',
|
||||
'horizon.framework.conf.resource-type-registry.service'
|
||||
];
|
||||
|
||||
function run(
|
||||
resourceTypeName,
|
||||
api,
|
||||
basePath,
|
||||
registry
|
||||
) {
|
||||
var resourceType = registry.getResourceType(resourceTypeName);
|
||||
resourceType
|
||||
.setLoadFunction(loadFunction)
|
||||
.setSummaryTemplateUrl(basePath + 'details/drawer.html')
|
||||
.setItemNameFunction(itemNameFunction);
|
||||
|
||||
resourceType.detailsViews
|
||||
.prepend({
|
||||
id: 'floatingIpDetailsOverview',
|
||||
name: gettext('Overview'),
|
||||
template: basePath + 'details/overview.html'
|
||||
}, 0);
|
||||
|
||||
function loadFunction(identifier) {
|
||||
return api.get(identifier);
|
||||
}
|
||||
|
||||
function itemNameFunction(floatingIp) {
|
||||
return floatingIp.address;
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,10 @@
|
||||
<hz-resource-property-list
|
||||
ng-if="item"
|
||||
resource-type-name="OS::Designate::FloatingIp"
|
||||
item="item"
|
||||
cls="dl-horizontal"
|
||||
property-groups="[
|
||||
['description'],
|
||||
['id']
|
||||
]">
|
||||
</hz-resource-property-list>
|
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
angular
|
||||
.module('designatedashboard.resources.os-designate-floatingip.details')
|
||||
.controller('designatedashboard.resources.os-designate-floatingip.details.overviewController', controller);
|
||||
|
||||
controller.$inject = [
|
||||
'designatedashboard.resources.os-designate-floatingip.resourceType',
|
||||
'horizon.framework.conf.resource-type-registry.service',
|
||||
'$scope'
|
||||
];
|
||||
|
||||
function controller(
|
||||
resourceTypeCode,
|
||||
registry,
|
||||
$scope
|
||||
) {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.item;
|
||||
ctrl.resourceType = registry.getResourceType(resourceTypeCode);
|
||||
|
||||
$scope.context.loadPromise.then(onGetResponse);
|
||||
|
||||
function onGetResponse(response) {
|
||||
ctrl.item = response.data;
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,11 @@
|
||||
<div ng-controller="designatedashboard.resources.os-designate-floatingip.details.overviewController as ctrl">
|
||||
<hz-resource-property-list
|
||||
ng-if="ctrl.item"
|
||||
resource-type-name="OS::Designate::FloatingIp"
|
||||
item="ctrl.item"
|
||||
cls="dl-horizontal"
|
||||
property-groups="[
|
||||
['ptrdname', 'description', 'id', 'ttl', 'status', 'action']
|
||||
]">
|
||||
</hz-resource-property-list>
|
||||
</div>
|
@ -0,0 +1,154 @@
|
||||
/**
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc overview
|
||||
* @ngname designatedashboard.resources.os-designate-floatingip
|
||||
*
|
||||
* @description
|
||||
* Provides all of the services and widgets required
|
||||
* to support and display DNS (designate) floating ip related content.
|
||||
*/
|
||||
angular
|
||||
.module('designatedashboard.resources.os-designate-floatingip', [
|
||||
'ngRoute',
|
||||
'designatedashboard.resources.os-designate-floatingip.actions',
|
||||
'designatedashboard.resources.os-designate-floatingip.details'
|
||||
])
|
||||
.constant(
|
||||
'designatedashboard.resources.os-designate-floatingip.resourceType',
|
||||
'OS::Designate::FloatingIp')
|
||||
.config(config)
|
||||
.run(run);
|
||||
|
||||
config.$inject = [ '$provide', '$windowProvider' ];
|
||||
|
||||
function config($provide, $windowProvider) {
|
||||
var path = $windowProvider.$get().STATIC_URL + 'designatedashboard/resources/os-designate-floatingip/';
|
||||
$provide.constant('designatedashboard.resources.os-designate-floatingip.basePath', path);
|
||||
}
|
||||
|
||||
run.$inject = [
|
||||
'horizon.framework.conf.resource-type-registry.service',
|
||||
'designatedashboard.resources.os-designate-floatingip.api',
|
||||
'designatedashboard.resources.os-designate-floatingip.resourceType',
|
||||
'designatedashboard.resources.util'
|
||||
];
|
||||
|
||||
function run(
|
||||
registry,
|
||||
api,
|
||||
resourceTypeString,
|
||||
util)
|
||||
{
|
||||
var resourceType = registry.getResourceType(resourceTypeString);
|
||||
resourceType
|
||||
.setNames(gettext('Floating IP'), gettext('Floating IPs'))
|
||||
.setListFunction(listFloatingIps)
|
||||
.setProperty('id', {
|
||||
label: gettext('ID')
|
||||
})
|
||||
.setProperty('ptrdname', {
|
||||
label: gettext('PTR Domain Name'),
|
||||
filters: ['noName']
|
||||
})
|
||||
.setProperty('description', {
|
||||
label: gettext('Description'),
|
||||
filters: ['noName']
|
||||
})
|
||||
.setProperty('ttl', {
|
||||
label: gettext('Time To Live'),
|
||||
filters: ['noValue']
|
||||
})
|
||||
.setProperty('address', {
|
||||
label: gettext('Address'),
|
||||
filters: ['noName']
|
||||
})
|
||||
.setProperty('status', {
|
||||
label: gettext('Status'),
|
||||
filters: ['lowercase', 'noName'],
|
||||
values: util.statusMap()
|
||||
})
|
||||
.setProperty('action', {
|
||||
label: gettext('Action'),
|
||||
filters: ['lowercase', 'noName'],
|
||||
values: util.actionMap()
|
||||
});
|
||||
|
||||
resourceType
|
||||
.tableColumns
|
||||
.append({
|
||||
id: 'address',
|
||||
priority: 1,
|
||||
sortDefault: true,
|
||||
template: '<a ng-href="{$ \'project/ngdetails/OS::Designate::FloatingIp/\' + item.id $}">{$ item.address $}</a>'
|
||||
})
|
||||
.append({
|
||||
id: 'ptrdname',
|
||||
filters: ['noValue'],
|
||||
priority: 1,
|
||||
})
|
||||
.append({
|
||||
id: 'status',
|
||||
filters: ['lowercase'],
|
||||
values: util.statusMap(),
|
||||
priority: 2
|
||||
});
|
||||
|
||||
resourceType
|
||||
.filterFacets
|
||||
.append({
|
||||
label: gettext('Address'),
|
||||
name: 'address',
|
||||
isServer: false,
|
||||
singleton: true,
|
||||
persistent: false
|
||||
})
|
||||
.append({
|
||||
label: gettext('PTR Domain Name'),
|
||||
name: 'ptrdname',
|
||||
isServer: false,
|
||||
singleton: true,
|
||||
persistent: false
|
||||
})
|
||||
.append({
|
||||
label: gettext('Status'),
|
||||
name: 'status',
|
||||
isServer: false,
|
||||
singleton: true,
|
||||
persistent: false,
|
||||
options: [
|
||||
{label: gettext('Active'), key: 'active'},
|
||||
{label: gettext('Pending'), key: 'pending'}
|
||||
]
|
||||
});
|
||||
|
||||
function listFloatingIps() {
|
||||
return api.list().then(function onList(response) {
|
||||
// listFunctions are expected to return data in "items"
|
||||
response.data.items = response.data.floatingips;
|
||||
|
||||
util.addTimestampIds(response.data.items);
|
||||
|
||||
return response;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc overview
|
||||
* @ngname designatedashboard.resources.os-designate-recordset.actions
|
||||
*
|
||||
* @description
|
||||
* Provides all of the actions for DNS Recordsets.
|
||||
*/
|
||||
angular.module('designatedashboard.resources.os-designate-recordset.actions', [
|
||||
'horizon.framework.conf',
|
||||
'horizon.app.core'
|
||||
])
|
||||
.run(run);
|
||||
|
||||
run.$inject = [
|
||||
'horizon.framework.conf.resource-type-registry.service',
|
||||
'designatedashboard.resources.os-designate-recordset.resourceType',
|
||||
'designatedashboard.resources.os-designate-recordset.actions.create',
|
||||
'designatedashboard.resources.os-designate-recordset.actions.delete',
|
||||
'designatedashboard.resources.os-designate-recordset.actions.update'
|
||||
];
|
||||
|
||||
function run(registry,
|
||||
resourceTypeString,
|
||||
createAction,
|
||||
deleteAction,
|
||||
updateAction) {
|
||||
var resourceType = registry.getResourceType(resourceTypeString);
|
||||
|
||||
resourceType
|
||||
.itemActions
|
||||
.append({
|
||||
id: 'updateRecordset',
|
||||
service: updateAction,
|
||||
template: {
|
||||
text: gettext('Update')
|
||||
}
|
||||
})
|
||||
.append({
|
||||
id: 'deleteRecordset',
|
||||
service: deleteAction,
|
||||
template: {
|
||||
text: gettext('Delete'),
|
||||
type: 'delete'
|
||||
}
|
||||
});
|
||||
|
||||
// Append a record set view to the zones actions
|
||||
var zoneResourceType = registry.getResourceType("OS::Designate::Zone");
|
||||
zoneResourceType
|
||||
.itemActions
|
||||
.append({
|
||||
id: 'createRecordset',
|
||||
service: createAction,
|
||||
template: {
|
||||
text: gettext('Create Record Set')
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,165 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development Company LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use self file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('designatedashboard.resources.os-designate-recordset.actions')
|
||||
.factory('designatedashboard.resources.os-designate-recordset.actions.common-forms', service);
|
||||
|
||||
service.$inject = [
|
||||
'designatedashboard.resources.os-designate-recordset.editableTypes',
|
||||
'designatedashboard.resources.os-designate-recordset.typeMap'
|
||||
];
|
||||
|
||||
/**
|
||||
* Service to return a schema form config for action forms. Especially useful for forms
|
||||
* like create and update that differ only in the readonly state of certain form fields.
|
||||
*
|
||||
* @returns {object} A schema form config
|
||||
*/
|
||||
function service(editableTypes, typeMap) {
|
||||
var service = {
|
||||
getCreateFormConfig: getCreateFormConfig,
|
||||
getUpdateFormConfig: getUpdateFormConfig
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
/////////////////
|
||||
|
||||
/**
|
||||
* Returns the create form config
|
||||
* @returns {{schema, form, model}|*}
|
||||
*/
|
||||
function getCreateFormConfig() {
|
||||
return getCreateUpdateFormConfig(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the update form config
|
||||
* @returns {{schema, form, model}|*}
|
||||
*/
|
||||
function getUpdateFormConfig() {
|
||||
return getCreateUpdateFormConfig(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the create/update form. The two forms are identical except for
|
||||
* during update, some fields are read-only.
|
||||
*
|
||||
* @param readonly - sets readonly value on form fields that change between update and create
|
||||
* @returns {object} a schema form config, including default model
|
||||
*/
|
||||
function getCreateUpdateFormConfig(readonly) {
|
||||
return {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"pattern": /^.+\.$/
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": editableTypes
|
||||
},
|
||||
"ttl": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 2147483647
|
||||
},
|
||||
"records": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"record": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"minItems": 1,
|
||||
"uniqueItems": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"form": [
|
||||
{
|
||||
"key": "type",
|
||||
"readonly": readonly,
|
||||
"title": gettext("Type"),
|
||||
"description": gettext("Select the type of record set"),
|
||||
"type": "select",
|
||||
"titleMap": editableTypes.map(function toTitleMap(type) {
|
||||
return {
|
||||
"value": type,
|
||||
"name": typeMap[type]
|
||||
}
|
||||
}),
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"key": "name",
|
||||
"readonly": readonly,
|
||||
"type": "text",
|
||||
"title": gettext("Name"),
|
||||
"description": gettext("DNS name for the record set, ending in '.'"),
|
||||
"validationMessage": gettext("DNS name must end with '.'"),
|
||||
"placeholder": "www.example.com.",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"key": "description",
|
||||
"type": "textarea",
|
||||
"title": gettext("Description"),
|
||||
"description": gettext("Details about the zone.")
|
||||
},
|
||||
{
|
||||
"key": "ttl",
|
||||
"title": gettext("TTL"),
|
||||
"description": gettext("Time To Live in seconds."),
|
||||
"type": "number",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"key": "records",
|
||||
"title": gettext("Records"),
|
||||
"type": "array",
|
||||
"description": gettext("Records for the record set."),
|
||||
"add": gettext("Add Record"),
|
||||
"items": [
|
||||
{
|
||||
"key": "records[].record",
|
||||
"title": gettext("Record")
|
||||
}
|
||||
],
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"model": {
|
||||
"type": "A",
|
||||
"ttl": 3600
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
})();
|
@ -0,0 +1,132 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development Company LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use self file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('designatedashboard.resources.os-designate-recordset.actions')
|
||||
.factory('designatedashboard.resources.os-designate-recordset.actions.create', action);
|
||||
|
||||
action.$inject = [
|
||||
'$q',
|
||||
'designatedashboard.resources.os-designate-recordset.actions.common-forms',
|
||||
'designatedashboard.resources.os-designate-recordset.api',
|
||||
'designatedashboard.resources.os-designate-recordset.resourceType',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
'horizon.app.core.openstack-service-api.serviceCatalog',
|
||||
'horizon.framework.conf.resource-type-registry.service',
|
||||
'horizon.framework.widgets.form.ModalFormService',
|
||||
'horizon.framework.widgets.toast.service',
|
||||
'horizon.framework.widgets.modal-wait-spinner.service'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngDoc factory
|
||||
* @name designatedashboard.resources.os-designate-recordset.actions.create
|
||||
*
|
||||
* @Description
|
||||
* Brings up the Create Record Set modal.
|
||||
*/
|
||||
function action($q,
|
||||
forms,
|
||||
api,
|
||||
resourceTypeName,
|
||||
policy,
|
||||
serviceCatalog,
|
||||
registry,
|
||||
schemaFormModalService,
|
||||
toast,
|
||||
waitSpinner) {
|
||||
var createRecordSetPolicy, dnsServiceEnabled;
|
||||
var title = gettext("Create Record Set");
|
||||
var message = {
|
||||
success: gettext('Record Set %s was successfully created.')
|
||||
};
|
||||
|
||||
var service = {
|
||||
initScope: initScope,
|
||||
allowed: allowed,
|
||||
perform: perform
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
/////////////////
|
||||
|
||||
function initScope() {
|
||||
createRecordSetPolicy = policy.ifAllowed({rules: [['dns', 'create_recordset']]});
|
||||
dnsServiceEnabled = serviceCatalog.ifTypeEnabled('dns');
|
||||
}
|
||||
|
||||
function allowed(item) {
|
||||
return $q.all([
|
||||
createRecordSetPolicy,
|
||||
dnsServiceEnabled
|
||||
]);
|
||||
}
|
||||
|
||||
function perform(item) {
|
||||
var formConfig = forms.getCreateFormConfig();
|
||||
|
||||
// Store the zone ID so it can be used on submit
|
||||
formConfig.model.zoneId = item.id;
|
||||
|
||||
formConfig.title = title;
|
||||
return schemaFormModalService.open(formConfig).then(onSubmit, onCancel);
|
||||
}
|
||||
|
||||
function onSubmit(context) {
|
||||
var model = angular.copy(context.model);
|
||||
var zoneId = model.zoneId;
|
||||
delete model.zoneId;
|
||||
|
||||
// schema form doesn't appear to support populating arrays directly
|
||||
// Map the records objects to simple array of records
|
||||
var records = context.model.records.map(function (item) {
|
||||
return item.record;
|
||||
});
|
||||
model.records = records;
|
||||
|
||||
waitSpinner.showModalSpinner(gettext('Creating Record Set'));
|
||||
return api.create(zoneId, model).then(onSuccess, onFailure);
|
||||
}
|
||||
|
||||
function onCancel() {
|
||||
waitSpinner.hideModalSpinner();
|
||||
}
|
||||
|
||||
function onSuccess(response) {
|
||||
waitSpinner.hideModalSpinner();
|
||||
var zone = response.data;
|
||||
toast.add('success', interpolate(message.success, [zone.name]));
|
||||
|
||||
// To make the result of this action generically useful, reformat the return
|
||||
// from the deleteModal into a standard form
|
||||
return {
|
||||
created: [{type: resourceTypeName, id: zone.id}],
|
||||
updated: [],
|
||||
deleted: [],
|
||||
failed: []
|
||||
};
|
||||
}
|
||||
|
||||
function onFailure() {
|
||||
waitSpinner.hideModalSpinner();
|
||||
}
|
||||
}
|
||||
})();
|
@ -0,0 +1,182 @@
|
||||
/**
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use self file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('designatedashboard.resources.os-designate-recordset.actions')
|
||||
.factory('designatedashboard.resources.os-designate-recordset.actions.delete', action);
|
||||
|
||||
action.$inject = [
|
||||
'$q',
|
||||
'designatedashboard.resources.os-designate-recordset.api',
|
||||
'designatedashboard.resources.os-designate-recordset.editableTypes',
|
||||
'designatedashboard.resources.os-designate-recordset.resourceType',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
'horizon.framework.util.actions.action-result.service',
|
||||
'horizon.framework.util.i18n.gettext',
|
||||
'horizon.framework.util.q.extensions',
|
||||
'horizon.framework.widgets.modal.deleteModalService',
|
||||
'horizon.framework.widgets.toast.service'
|
||||
];
|
||||
|
||||
/*
|
||||
* @ngdoc factory
|
||||
* @name designatedashboard.resources.os-designate-recordset.actions.delete
|
||||
*
|
||||
* @Description
|
||||
* Brings up the delete recordset confirmation modal dialog.
|
||||
|
||||
* On submit, delete given recordset.
|
||||
* On cancel, do nothing.
|
||||
*/
|
||||
function action(
|
||||
$q,
|
||||
recordsetApi,
|
||||
editableTypes,
|
||||
resourceType,
|
||||
policy,
|
||||
actionResultService,
|
||||
gettext,
|
||||
$qExtensions,
|
||||
deleteModal,
|
||||
toast
|
||||
) {
|
||||
var scope, context, deletePromise;
|
||||
var notAllowedMessage = gettext("You are not allowed to delete record sets: %s");
|
||||
var allowedRecordsets = [];
|
||||
|
||||
var service = {
|
||||
initScope: initScope,
|
||||
allowed: allowed,
|
||||
perform: perform
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
//////////////
|
||||
|
||||
function initScope(newScope) {
|
||||
scope = newScope;
|
||||
context = { };
|
||||
deletePromise = policy.ifAllowed({rules: [['dns', 'delete_recordset']]});
|
||||
}
|
||||
|
||||
function perform(items) {
|
||||
var recordsets = angular.isArray(items) ? items : [items];
|
||||
context.labels = labelize(recordsets.length);
|
||||
context.deleteEntity = deleteRecordSet;
|
||||
return $qExtensions.allSettled(recordsets.map(checkPermission)).then(afterCheck);
|
||||
}
|
||||
|
||||
function allowed(recordset) {
|
||||
// only row actions pass in recordset
|
||||
// otherwise, assume it is a batch action
|
||||
if (recordset) {
|
||||
return $q.all([
|
||||
deletePromise,
|
||||
editableRecordType(recordset)
|
||||
]);
|
||||
} else {
|
||||
return policy.ifAllowed({ rules: [['dns', 'delete_recordset']] });
|
||||
}
|
||||
}
|
||||
|
||||
function checkPermission(recordset) {
|
||||
return {promise: allowed(recordset), context: recordset};
|
||||
}
|
||||
|
||||
function afterCheck(result) {
|
||||
var outcome = $q.reject(); // Reject the promise by default
|
||||
if (result.fail.length > 0) {
|
||||
toast.add('error', getMessage(notAllowedMessage, result.fail));
|
||||
outcome = $q.reject(result.fail);
|
||||
}
|
||||
if (result.pass.length > 0) {
|
||||
// Remember the record sets we are allowed to delete so that on delete modal submit
|
||||
// we can map the recordset ID back to the full recordset. Then we can fetch the
|
||||
// corresponding zone ID
|
||||
allowedRecordsets = result.pass.map(getEntity)
|
||||
outcome = deleteModal.open(scope, allowedRecordsets, context).then(createResult);
|
||||
}
|
||||
return outcome;
|
||||
}
|
||||
|
||||
function createResult(deleteModalResult) {
|
||||
// To make the result of this action generically useful, reformat the return
|
||||
// from the deleteModal into a standard form
|
||||
var actionResult = actionResultService.getActionResult();
|
||||
deleteModalResult.pass.forEach(function markDeleted(item) {
|
||||
actionResult.deleted(resourceType, getEntity(item).id);
|
||||
});
|
||||
deleteModalResult.fail.forEach(function markFailed(item) {
|
||||
actionResult.failed(resourceType, getEntity(item).id);
|
||||
});
|
||||
return actionResult.result;
|
||||
}
|
||||
|
||||
function labelize(count) {
|
||||
return {
|
||||
|
||||
title: ngettext(
|
||||
'Confirm Delete Record Set',
|
||||
'Confirm Delete Record Sets', count),
|
||||
|
||||
message: ngettext(
|
||||
'You have selected "%s". Deleted record set is not recoverable.',
|
||||
'You have selected "%s". Deleted record sets are not recoverable.', count),
|
||||
|
||||
submit: ngettext(
|
||||
'Delete Record Set',
|
||||
'Delete Record Sets', count),
|
||||
|
||||
success: ngettext(
|
||||
'Deleted Record Set: %s.',
|
||||
'Deleted Record Sets: %s.', count),
|
||||
|
||||
error: ngettext(
|
||||
'Unable to delete Record Set: %s.',
|
||||
'Unable to delete Record Sets: %s.', count)
|
||||
};
|
||||
}
|
||||
|
||||
function editableRecordType(recordset) {
|
||||
return $qExtensions.booleanAsPromise(
|
||||
editableTypes.indexOf(recordset.type) > -1
|
||||
);
|
||||
}
|
||||
|
||||
function deleteRecordSet(recordSetId) {
|
||||
var recordSet = allowedRecordsets.find(function(element) {
|
||||
return element.id === recordSetId;
|
||||
})
|
||||
return recordsetApi.deleteRecordSet(recordSet.zone_id, recordSet.id);
|
||||
}
|
||||
|
||||
function getMessage(message, entities) {
|
||||
return interpolate(message, [entities.map(getName).join(", ")]);
|
||||
}
|
||||
|
||||
function getName(result) {
|
||||
return getEntity(result).name;
|
||||
}
|
||||
|
||||
function getEntity(result) {
|
||||
return result.context;
|
||||
}
|
||||
}
|
||||
})();
|
@ -0,0 +1,159 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development Company LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use self file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('designatedashboard.resources.os-designate-recordset.actions')
|
||||
.factory('designatedashboard.resources.os-designate-recordset.actions.update', action);
|
||||
|
||||
action.$inject = [
|
||||
'$q',
|
||||
'designatedashboard.resources.util',
|
||||
'designatedashboard.resources.os-designate-recordset.actions.common-forms',
|
||||
'designatedashboard.resources.os-designate-recordset.api',
|
||||
'designatedashboard.resources.os-designate-recordset.editableTypes',
|
||||
'designatedashboard.resources.os-designate-recordset.resourceType',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
'horizon.app.core.openstack-service-api.serviceCatalog',
|
||||
'horizon.framework.util.q.extensions',
|
||||
'horizon.framework.widgets.form.ModalFormService',
|
||||
'horizon.framework.widgets.toast.service',
|
||||
'horizon.framework.widgets.modal-wait-spinner.service'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngDoc factory
|
||||
* @name designatedashboard.resources.os-designate-recordset.actions.update
|
||||
*
|
||||
* @Description
|
||||
* Brings up the Update modal.
|
||||
*/
|
||||
function action($q,
|
||||
util,
|
||||
forms,
|
||||
api,
|
||||
editableTypes,
|
||||
resourceTypeName,
|
||||
policy,
|
||||
serviceCatalog,
|
||||
$qExtensions,
|
||||
schemaFormModalService,
|
||||
toast,
|
||||
waitSpinner) {
|
||||
var updateRecordSetPolicy, dnsServiceEnabled;
|
||||
var title = gettext("Update Record Set");
|
||||
var message = {
|
||||
success: gettext('Record Set %s was successfully updated.')
|
||||
};
|
||||
|
||||
var service = {
|
||||
initScope: initScope,
|
||||
allowed: allowed,
|
||||
perform: perform
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
/////////////////
|
||||
|
||||
function initScope() {
|
||||
updateRecordSetPolicy = policy.ifAllowed({rules: [['dns', 'update_recordset']]});
|
||||
dnsServiceEnabled = serviceCatalog.ifTypeEnabled('dns');
|
||||
}
|
||||
|
||||
function allowed(recordset) {
|
||||
// only supports row action (exactly 1 recordset)
|
||||
if (recordset) {
|
||||
return $q.all([
|
||||
updateRecordSetPolicy,
|
||||
util.notDeleted(recordset),
|
||||
util.notPending(recordset),
|
||||
editableRecordType(recordset)
|
||||
]);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function editableRecordType(recordset) {
|
||||
return $qExtensions.booleanAsPromise(
|
||||
editableTypes.indexOf(recordset.type) > -1
|
||||
);
|
||||
}
|
||||
|
||||
function perform(item) {
|
||||
var formConfig = forms.getUpdateFormConfig();
|
||||
formConfig.title = title;
|
||||
formConfig.model = util.getModel(formConfig.form, item);
|
||||
|
||||
// Append the id and zoneId so it can be used on submit
|
||||
formConfig.model.id = item.id;
|
||||
formConfig.model.zoneId = item.zone_id;
|
||||
|
||||
// schema form doesn't appear to support populating the records array directly
|
||||
// Map the records objects to record objects
|
||||
if (item.hasOwnProperty("records")) {
|
||||
var records = item.records.map(function (item) {
|
||||
return {"record": item}
|
||||
});
|
||||
formConfig.model.records = records;
|
||||
}
|
||||
return schemaFormModalService.open(formConfig).then(onSubmit, onCancel);
|
||||
}
|
||||
|
||||
function onSubmit(context) {
|
||||
var model = angular.copy(context.model);
|
||||
// schema form doesn't appear to support populating the records array directly
|
||||
// Map the records objects to simple array of records
|
||||
if (context.model.hasOwnProperty("records")) {
|
||||
var records = context.model.records.map(function (item) {
|
||||
return item.record;
|
||||
});
|
||||
model.records = records;
|
||||
}
|
||||
|
||||
waitSpinner.showModalSpinner(gettext('Updating Record Set'));
|
||||
|
||||
return api.update(model.zoneId, model.id, model).then(onSuccess, onFailure);
|
||||
}
|
||||
|
||||
function onCancel() {
|
||||
waitSpinner.hideModalSpinner();
|
||||
}
|
||||
|
||||
function onSuccess(response) {
|
||||
waitSpinner.hideModalSpinner();
|
||||
var recordset = response.data;
|
||||
toast.add('success', interpolate(message.success, [recordset.name]));
|
||||
|
||||
// To make the result of this action generically useful, reformat the return
|
||||
// from the deleteModal into a standard form
|
||||
return {
|
||||
created: [],
|
||||
updated: [{type: resourceTypeName, id: recordset.id}],
|
||||
deleted: [],
|
||||
failed: []
|
||||
};
|
||||
}
|
||||
|
||||
function onFailure() {
|
||||
waitSpinner.hideModalSpinner();
|
||||
}
|
||||
}
|
||||
})();
|
@ -0,0 +1,136 @@
|
||||
/**
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('designatedashboard.resources.os-designate-recordset')
|
||||
.factory('designatedashboard.resources.os-designate-recordset.api', apiService);
|
||||
|
||||
apiService.$inject = [
|
||||
'$q',
|
||||
'designatedashboard.apiPassthroughUrl',
|
||||
'horizon.framework.util.http.service',
|
||||
'horizon.framework.widgets.toast.service'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @param {Object} httpService
|
||||
* @param {Object} toastService
|
||||
* @name apiService
|
||||
* @description Provides direct access to Designate Record Set APIs.
|
||||
* @returns {Object} The service
|
||||
*/
|
||||
function apiService($q, apiPassthroughUrl, httpService, toastService) {
|
||||
var service = {
|
||||
get: get,
|
||||
list: list,
|
||||
deleteRecordSet: deleteRecordSet,
|
||||
create: create,
|
||||
update: update
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
///////////////
|
||||
|
||||
/**
|
||||
* @name list
|
||||
* @description
|
||||
* Get a list of record sets.
|
||||
*
|
||||
* The listing result is an object with property "items." Each item is
|
||||
* a record set.
|
||||
*
|
||||
* @param {Object} params
|
||||
* Query parameters. Optional.
|
||||
*
|
||||
* @returns {Object} The result of the API call
|
||||
*/
|
||||
function list(zoneId, params) {
|
||||
return httpService.get(apiPassthroughUrl + 'v2/zones/' + zoneId + '/recordsets/', params)
|
||||
.error(function () {
|
||||
toastService.add('error', gettext('Unable to retrieve the record sets.'));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @name get
|
||||
* @description
|
||||
* Get a single record set by ID.
|
||||
*
|
||||
* @param {string} zoneId
|
||||
* Specifies the id of the zone containing the record set to request.
|
||||
*
|
||||
* @param {string} recordSetId
|
||||
* Specifies the id of the record set to request.
|
||||
*
|
||||
* @returns {Object} The result of the API call
|
||||
*/
|
||||
function get(zoneId, recordSetId) {
|
||||
// Unfortunately routed-details-view is not happy when load fails, which is
|
||||
// common when then delete action removes a record set. Mask this failure by
|
||||
// always returning a successful promise instead of terminating the $http promise
|
||||
// in the .error handler.
|
||||
return httpService.get(apiPassthroughUrl + 'v2/zones/' + zoneId + '/recordsets/' + recordSetId + '/')
|
||||
.then(undefined, function onError() {
|
||||
toastService.add('error', gettext('Unable to retrieve the record set.'));
|
||||
return $q.when({});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @name delete
|
||||
* @description
|
||||
* Delete a single record set by ID
|
||||
* @param {string} zoneId
|
||||
* The id of the zone containing the recordset
|
||||
*
|
||||
* @param {string} recordSetId
|
||||
* The id of the recordset within the zone
|
||||
*
|
||||
* @returns {*}
|
||||
*/
|
||||
function deleteRecordSet(zoneId, recordSetId) {
|
||||
return httpService.delete(apiPassthroughUrl + 'v2/zones/' + zoneId + '/recordsets/' + recordSetId + '/')
|
||||
.error(function () {
|
||||
toastService.add('error', gettext('Unable to delete the record set.'));
|
||||
});
|
||||
}
|
||||
|
||||
function create(zoneId, data) {
|
||||
return httpService.post(apiPassthroughUrl + 'v2/zones/' + zoneId + '/recordsets/', data)
|
||||
.error(function () {
|
||||
toastService.add('error', gettext('Unable to create the record set.'));
|
||||
});
|
||||
}
|
||||
|
||||
function update(zoneId, recordSetId, data) {
|
||||
// The update API will not accept extra data. Restrict the input to only the allowed
|
||||
// fields
|
||||
var apiData = {
|
||||
ttl: data.ttl,
|
||||
description: data.description,
|
||||
records: data.records
|
||||
};
|
||||
return httpService.put(apiPassthroughUrl + 'v2/zones/' + zoneId + '/recordsets/' + recordSetId, apiData)
|
||||
.error(function () {
|
||||
toastService.add('error', gettext('Unable to update the record set.'));
|
||||
});
|
||||
}
|
||||
}
|
||||
}());
|
@ -0,0 +1,109 @@
|
||||
/**
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc overview
|
||||
* @ngname designatedashboard.resources.os-designate-recordset.details
|
||||
*
|
||||
* @description
|
||||
* Provides details features for record sets.
|
||||
*/
|
||||
angular.module('designatedashboard.resources.os-designate-recordset.details',
|
||||
['horizon.framework.conf', 'horizon.app.core'])
|
||||
.run(run);
|
||||
|
||||
run.$inject = [
|
||||
'designatedashboard.resources.os-designate-recordset.resourceType',
|
||||
'designatedashboard.resources.os-designate-recordset.api',
|
||||
'designatedashboard.resources.os-designate-recordset.basePath',
|
||||
'horizon.framework.conf.resource-type-registry.service',
|
||||
];
|
||||
|
||||
function run(
|
||||
recordSetResourceType,
|
||||
recordSetApi,
|
||||
basePath,
|
||||
registry
|
||||
) {
|
||||
var resourceType = registry.getResourceType(recordSetResourceType);
|
||||
resourceType
|
||||
.setLoadFunction(loadFunction)
|
||||
.setPathGenerator(pathGenerator)
|
||||
.setPathParser(pathParser)
|
||||
.setSummaryTemplateUrl(basePath + 'details/drawer.html');
|
||||
|
||||
/**
|
||||
*
|
||||
* @param identifier
|
||||
* The object returned by the pathParser containing the zone ID and record set ID to load
|
||||
*/
|
||||
function loadFunction(identifier) {
|
||||
return recordSetApi.get(identifier.zoneId, identifier.recordSetId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Because a record set is contained by a zone, we implement a custom
|
||||
* pathGenerator to encode the zone ID and record set ID for the generic
|
||||
* details panel.
|
||||
*
|
||||
* @param item
|
||||
* A record set
|
||||
*
|
||||
* @returns {string} In format "<zone_id>/<recordset_id>"
|
||||
*/
|
||||
function pathGenerator(item) {
|
||||
return item.zone_id + '/' + item.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a path, extract the zone and record set ids
|
||||
*
|
||||
* @param path
|
||||
* created by pathGenerator
|
||||
*
|
||||
* @returns {{zoneId: *, recordSetId: *}}
|
||||
* The identifier to pass to the load function needed to uniquely identify
|
||||
* a record set.
|
||||
*/
|
||||
function pathParser(path) {
|
||||
var split = path.split('/');
|
||||
return {
|
||||
zoneId: split[0],
|
||||
recordSetId: split[1]
|
||||
}
|
||||
}
|
||||
|
||||
resourceType.detailsViews
|
||||
.prepend({
|
||||
id: 'recordsetDetailsOverview',
|
||||
name: gettext('Overview'),
|
||||
template: basePath + 'details/overview.html',
|
||||
}, 0);
|
||||
|
||||
// Append a record set view to the zones resource view
|
||||
var zoneResourceType = registry.getResourceType("OS::Designate::Zone");
|
||||
zoneResourceType.detailsViews
|
||||
.append({
|
||||
id: 'zoneRecordSets',
|
||||
name: gettext('Record Sets'),
|
||||
template: basePath + 'details/zone-recordsets.html',
|
||||
});
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,10 @@
|
||||
<hz-resource-property-list
|
||||
ng-if="item"
|
||||
resource-type-name="OS::Designate::RecordSet"
|
||||
item="item"
|
||||
cls="dl-horizontal"
|
||||
property-groups="[
|
||||
['records', 'notes', 'description'],
|
||||
['id']
|
||||
]">
|
||||
</hz-resource-property-list>
|
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
angular
|
||||
.module('designatedashboard.resources.os-designate-recordset')
|
||||
.controller('designatedashboard.resources.os-designate-recordset.detailController', controller);
|
||||
|
||||
controller.$inject = [
|
||||
'designatedashboard.resources.os-designate-recordset.resourceType',
|
||||
'horizon.framework.conf.resource-type-registry.service',
|
||||
'$scope'
|
||||
];
|
||||
|
||||
function controller(
|
||||
resourceTypeCode,
|
||||
registry,
|
||||
$scope
|
||||
) {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.item = {};
|
||||
ctrl.resourceType = registry.getResourceType(resourceTypeCode);
|
||||
|
||||
$scope.context.loadPromise.then(onGetResponse);
|
||||
|
||||
function onGetResponse(response) {
|
||||
ctrl.item = response.data;
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,45 @@
|
||||
<div ng-controller="designatedashboard.resources.os-designate-recordset.detailController as ctrl">
|
||||
<div class="row">
|
||||
<div class="col-md-6 detail">
|
||||
<h3 translate>Details</h3>
|
||||
<hr>
|
||||
<hz-resource-property-list
|
||||
ng-if="ctrl.item"
|
||||
resource-type-name="OS::Designate::RecordSet"
|
||||
item="ctrl.item"
|
||||
cls="dl-horizontal"
|
||||
property-groups="[
|
||||
['id', 'type', 'name', 'records', 'notes', 'description', 'ttl', 'version', 'action', 'status']
|
||||
]">
|
||||
</hz-resource-property-list>
|
||||
</div>
|
||||
<div class="col-md-6 detail">
|
||||
<h3 translate>Associations</h3>
|
||||
<hr>
|
||||
<hz-resource-property-list
|
||||
ng-if="ctrl.item"
|
||||
resource-type-name="OS::Designate::RecordSet"
|
||||
item="ctrl.item"
|
||||
cls="dl-horizontal"
|
||||
property-groups="[
|
||||
['zone_id', 'zone_name', 'project_id']
|
||||
]">
|
||||
</hz-resource-property-list>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 detail">
|
||||
<h3 translate>Modification Times</h3>
|
||||
<hr>
|
||||
<hz-resource-property-list
|
||||
ng-if="ctrl.item"
|
||||
resource-type-name="OS::Designate::RecordSet"
|
||||
item="ctrl.item"
|
||||
cls="dl-horizontal"
|
||||
property-groups="[
|
||||
['created_at', 'updated_at']
|
||||
]">
|
||||
</hz-resource-property-list>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
angular
|
||||
.module('designatedashboard.resources.os-designate-recordset')
|
||||
.controller('designatedashboard.resources.os-designate-recordset.zoneRecordSetsController', controller);
|
||||
|
||||
controller.$inject = [
|
||||
'$scope',
|
||||
'designatedashboard.resources.os-designate-recordset.resourceType'
|
||||
];
|
||||
|
||||
function controller(
|
||||
$scope,
|
||||
resourceTypeName
|
||||
) {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.item = {};
|
||||
ctrl.resourceTypeName = resourceTypeName;
|
||||
ctrl.extraListParams = { zoneId: $scope.context.identifier };
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,8 @@
|
||||
<div
|
||||
ng-controller="designatedashboard.resources.os-designate-recordset.zoneRecordSetsController as ctrl">
|
||||
<hz-resource-table
|
||||
resource-type-name="{$ ctrl.resourceTypeName $}"
|
||||
list-function-extra-params="ctrl.extraListParams"
|
||||
track-by="_timestampId">
|
||||
</hz-resource-table>
|
||||
</div>
|
@ -0,0 +1,238 @@
|
||||
/**
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc overview
|
||||
* @ngname designatedashboard.resources.os-designate-recordset
|
||||
*
|
||||
* @description
|
||||
* Provides all of the services and widgets required
|
||||
* to support and display DNS (designate) record set related content.
|
||||
*/
|
||||
angular
|
||||
.module('designatedashboard.resources.os-designate-recordset', [
|
||||
'ngRoute',
|
||||
'designatedashboard.resources.os-designate-recordset.actions',
|
||||
'designatedashboard.resources.os-designate-recordset.details'
|
||||
])
|
||||
.constant(
|
||||
'designatedashboard.resources.os-designate-recordset.resourceType',
|
||||
'OS::Designate::RecordSet')
|
||||
.constant(
|
||||
'designatedashboard.resources.os-designate-recordset.typeMap',
|
||||
{
|
||||
'A': gettext('A - Address record'),
|
||||
'AAAA': gettext('AAAA - IPv6 address record'),
|
||||
'CNAME': gettext('CNAME - Canonical name record'),
|
||||
'MX': gettext('MX - Mail exchange record'),
|
||||
'PTR': gettext('PTR - Pointer record'),
|
||||
'SPF': gettext('SPR - Sender Policy Framework'),
|
||||
'SRV': gettext('SRV - Service locator'),
|
||||
'SSHFP': gettext('SSHFP - SSH Public Key Fingerprint'),
|
||||
'TXT': gettext('TXT - Text record'),
|
||||
'SOA': gettext('SOA - Start of authority record'),
|
||||
'NS': gettext('NS - Name server')
|
||||
})
|
||||
.constant(
|
||||
'designatedashboard.resources.os-designate-recordset.editableTypes',
|
||||
[
|
||||
"A",
|
||||
"AAAA",
|
||||
"CNAME",
|
||||
"MX",
|
||||
"PTR",
|
||||
"SPF",
|
||||
"SRV",
|
||||
"SSHFP",
|
||||
"TXT"
|
||||
])
|
||||
.config(config)
|
||||
.run(run);
|
||||
|
||||
config.$inject = ['$provide', '$windowProvider'];
|
||||
|
||||
function config($provide, $windowProvider) {
|
||||
var path = $windowProvider.$get().STATIC_URL + 'designatedashboard/resources/os-designate-recordset/';
|
||||
$provide.constant('designatedashboard.resources.os-designate-recordset.basePath', path);
|
||||
}
|
||||
|
||||
run.$inject = [
|
||||
'horizon.framework.conf.resource-type-registry.service',
|
||||
'designatedashboard.resources.os-designate-recordset.api',
|
||||
'designatedashboard.resources.os-designate-recordset.resourceType',
|
||||
'designatedashboard.resources.os-designate-recordset.typeMap',
|
||||
'designatedashboard.resources.util'
|
||||
];
|
||||
|
||||
function run(registry,
|
||||
recordSetApi,
|
||||
resourceTypeString,
|
||||
typeMap,
|
||||
util) {
|
||||
var resourceType = registry.getResourceType(resourceTypeString);
|
||||
resourceType
|
||||
.setNames(gettext('DNS Record Set'), gettext('DNS Record Sets'))
|
||||
.setListFunction(list)
|
||||
.setProperty('id', {
|
||||
label: gettext('ID')
|
||||
})
|
||||
.setProperty('zone_id', {
|
||||
label: gettext('Zone ID'),
|
||||
filters: ['noValue']
|
||||
})
|
||||
.setProperty('zone_name', {
|
||||
label: gettext('Zone Name'),
|
||||
filters: ['noName']
|
||||
})
|
||||
.setProperty('project_id', {
|
||||
label: gettext('Project ID'),
|
||||
filters: ['noValue']
|
||||
})
|
||||
.setProperty('name', {
|
||||
label: gettext('Name'),
|
||||
filters: ['noName']
|
||||
})
|
||||
.setProperty('description', {
|
||||
label: gettext('Description'),
|
||||
filters: ['noName']
|
||||
})
|
||||
.setProperty('type', {
|
||||
label: gettext('Type'),
|
||||
filters: ['uppercase'],
|
||||
values: typeMap
|
||||
})
|
||||
.setProperty('ttl', {
|
||||
label: gettext('Time To Live'),
|
||||
filters: ['noValue']
|
||||
})
|
||||
.setProperty('records', {
|
||||
label: gettext('Records'),
|
||||
filters: ['noValue']
|
||||
})
|
||||
.setProperty('notes', {
|
||||
label: gettext('Notes'),
|
||||
filters: ['noName']
|
||||
})
|
||||
.setProperty('status', {
|
||||
label: gettext('Status'),
|
||||
filters: ['lowercase', 'noName'],
|
||||
values: util.statusMap()
|
||||
})
|
||||
.setProperty('action', {
|
||||
label: gettext('Action'),
|
||||
filters: ['lowercase', 'noName'],
|
||||
values: util.actionMap()
|
||||
})
|
||||
.setProperty('version', {
|
||||
label: gettext('Version'),
|
||||
filters: ['noValue']
|
||||
})
|
||||
.setProperty('created_at', {
|
||||
label: gettext('Created At'),
|
||||
filters: ['noValue']
|
||||
})
|
||||
.setProperty('updated_at', {
|
||||
label: gettext('Updated At'),
|
||||
filters: ['noValue']
|
||||
});
|
||||
|
||||
resourceType
|
||||
.tableColumns
|
||||
.append({
|
||||
id: 'name',
|
||||
priority: 1,
|
||||
sortDefault: true,
|
||||
filters: ['noName'],
|
||||
// For link format, see pathGenerator in details.module.js
|
||||
template: '<a ng-href="{$ \'project/ngdetails/OS::Designate::RecordSet/\' + item.zone_id + \'/\' + item.id $}">{$ item.name $}</a>'
|
||||
})
|
||||
.append({
|
||||
id: 'type',
|
||||
priority: 2,
|
||||
filters: ['uppercase'],
|
||||
values: typeMap
|
||||
})
|
||||
.append({
|
||||
id: 'records',
|
||||
priority: 2,
|
||||
filters: ['noValue']
|
||||
})
|
||||
.append({
|
||||
id: 'status',
|
||||
filters: ['lowercase'],
|
||||
values: util.statusMap(),
|
||||
priority: 2
|
||||
});
|
||||
|
||||
resourceType
|
||||
.filterFacets
|
||||
.append({
|
||||
label: gettext('Type'),
|
||||
name: 'type',
|
||||
isServer: false,
|
||||
singleton: true,
|
||||
persistent: false,
|
||||
options: Object.keys(typeMap).map(function toOptionLabel(key) {
|
||||
return {
|
||||
label: typeMap[key],
|
||||
key: key
|
||||
}
|
||||
})
|
||||
})
|
||||
.append({
|
||||
label: gettext('Name'),
|
||||
name: 'name',
|
||||
isServer: false,
|
||||
singleton: true,
|
||||
persistent: false
|
||||
})
|
||||
.append({
|
||||
label: gettext('Status'),
|
||||
name: 'status',
|
||||
isServer: false,
|
||||
singleton: true,
|
||||
persistent: false,
|
||||
options: [
|
||||
{label: gettext('Active'), key: 'active'},
|
||||
{label: gettext('Pending'), key: 'pending'}
|
||||
]
|
||||
});
|
||||
|
||||
/**
|
||||
* list all recordsets within a zone. Requires "zoneId" in the params. All other
|
||||
* params will be passed unmodified as URL params to the API.
|
||||
*
|
||||
* @param params
|
||||
* zoneId (required) list recordsets within the zone
|
||||
*
|
||||
* @returns {*|Object}
|
||||
*/
|
||||
function list(params) {
|
||||
return recordSetApi.list(params.zoneId, params).then(function onList(response) {
|
||||
// listFunctions are expected to return data in "items"
|
||||
response.data.items = response.data.recordsets;
|
||||
|
||||
util.addTimestampIds(response.data.items);
|
||||
|
||||
return response;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,76 @@
|
||||
/**
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc overview
|
||||
* @ngname designatedashboard.resources.os-designate-zone.actions
|
||||
*
|
||||
* @description
|
||||
* Provides all of the actions for DNS Zones.
|
||||
*/
|
||||
angular.module('designatedashboard.resources.os-designate-zone.actions', [
|
||||
'horizon.framework.conf',
|
||||
'horizon.app.core'
|
||||
])
|
||||
.run(run);
|
||||
|
||||
run.$inject = [
|
||||
'horizon.framework.conf.resource-type-registry.service',
|
||||
'designatedashboard.resources.os-designate-zone.resourceType',
|
||||
'designatedashboard.resources.os-designate-zone.actions.create',
|
||||
'designatedashboard.resources.os-designate-zone.actions.delete',
|
||||
'designatedashboard.resources.os-designate-zone.actions.update'
|
||||
];
|
||||
|
||||
function run(registry,
|
||||
resourceTypeString,
|
||||
createAction,
|
||||
deleteAction,
|
||||
updateAction) {
|
||||
var resourceType = registry.getResourceType(resourceTypeString);
|
||||
resourceType
|
||||
.globalActions
|
||||
.append({
|
||||
id: 'create',
|
||||
service: createAction,
|
||||
template: {
|
||||
text: gettext('Create Zone')
|
||||
}
|
||||
});
|
||||
|
||||
resourceType
|
||||
.itemActions
|
||||
.append({
|
||||
id: 'update',
|
||||
service: updateAction,
|
||||
template: {
|
||||
text: gettext('Update')
|
||||
}
|
||||
})
|
||||
.append({
|
||||
id: 'delete',
|
||||
service: deleteAction,
|
||||
template: {
|
||||
text: gettext('Delete'),
|
||||
type: 'delete'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,184 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development Company LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use self file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('designatedashboard.resources.os-designate-zone.actions')
|
||||
.factory('designatedashboard.resources.os-designate-zone.actions.common-forms', service);
|
||||
|
||||
service.$inject = [
|
||||
];
|
||||
|
||||
/**
|
||||
* Service to return a schema form config for action forms. Especially useful for forms
|
||||
* like create and update that differ only in the readonly state of certain form fields.
|
||||
*
|
||||
* @returns {object} A schema form config
|
||||
*/
|
||||
function service() {
|
||||
var service = {
|
||||
getCreateFormConfig: getCreateFormConfig,
|
||||
getUpdateFormConfig: getUpdateFormConfig
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
/////////////////
|
||||
|
||||
/**
|
||||
* Returns the create zone form config
|
||||
* @returns {{schema, form, model}|*}
|
||||
*/
|
||||
function getCreateFormConfig() {
|
||||
return getCreateUpdateFormConfig(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the update zone form config
|
||||
* @returns {{schema, form, model}|*}
|
||||
*/
|
||||
function getUpdateFormConfig() {
|
||||
return getCreateUpdateFormConfig(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the create/update zone form. The two forms are identical except for
|
||||
* during update, some fields are read-only.
|
||||
*
|
||||
* @param readonly - sets readonly value on form fields that change between update and create
|
||||
* @returns {object} a schema form config, including default model
|
||||
*/
|
||||
function getCreateUpdateFormConfig(readonly) {
|
||||
return {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"pattern": /^.+\.$/
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string",
|
||||
"format": "email",
|
||||
"pattern": /^[^@]+@[^@]+$/
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"PRIMARY",
|
||||
"SECONDARY"
|
||||
]
|
||||
},
|
||||
"ttl": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 2147483647
|
||||
},
|
||||
"masters": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"address": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"minItems": 1,
|
||||
"uniqueItems": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"form": [
|
||||
{
|
||||
"key": "name",
|
||||
"readonly": readonly,
|
||||
"title": gettext("Name"),
|
||||
"description": gettext("Zone name ending in '.'"),
|
||||
"validationMessage": gettext("Zone must end with '.'"),
|
||||
"placeholder": "example.com.",
|
||||
"type": "text",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"key": "description",
|
||||
"type": "textarea",
|
||||
"title": gettext("Description"),
|
||||
"description": gettext("Details about the zone.")
|
||||
},
|
||||
{
|
||||
"key": "email",
|
||||
"title": gettext("Email Address"),
|
||||
"placeholder": "owner@example.com",
|
||||
"description": gettext("Email address to contact the zone owner."),
|
||||
"validationMessage": gettext("Email address must contain a single '@' character"),
|
||||
"type": "text",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"key": "ttl",
|
||||
"title": gettext("TTL"),
|
||||
"description": gettext("Time To Live in seconds."),
|
||||
"type": "number",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"key": "type",
|
||||
"readonly": readonly,
|
||||
"title": gettext("Type"),
|
||||
"description": gettext("Select the type of zone"),
|
||||
"type": "select",
|
||||
"titleMap": [
|
||||
{
|
||||
"value": "PRIMARY",
|
||||
"name": gettext("Primary")
|
||||
},
|
||||
{
|
||||
"value": "SECONDARY",
|
||||
"name": gettext("Secondary")
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "masters",
|
||||
"readonly": readonly,
|
||||
"title": gettext("Masters"),
|
||||
"type": "array",
|
||||
"description": gettext("DNS master(s) for the Secondary zone."),
|
||||
"condition": "model.type == 'SECONDARY'",
|
||||
"add": gettext("Add Master"),
|
||||
"items": [
|
||||
{
|
||||
"key": "masters[].address",
|
||||
"title": gettext("IP Address")
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"model": {
|
||||
"type": "PRIMARY",
|
||||
"ttl": 3600
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
})();
|
@ -0,0 +1 @@
|
||||
<h1>CREATE TEMPLATE</h1>
|
@ -0,0 +1,126 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development Company LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use self file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('designatedashboard.resources.os-designate-zone.actions')
|
||||
.factory('designatedashboard.resources.os-designate-zone.actions.create', action);
|
||||
|
||||
action.$inject = [
|
||||
'$q',
|
||||
'designatedashboard.resources.os-designate-zone.actions.common-forms',
|
||||
'designatedashboard.resources.os-designate-zone.api',
|
||||
'designatedashboard.resources.os-designate-zone.resourceType',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
'horizon.app.core.openstack-service-api.serviceCatalog',
|
||||
'horizon.framework.widgets.form.ModalFormService',
|
||||
'horizon.framework.widgets.toast.service',
|
||||
'horizon.framework.widgets.modal-wait-spinner.service'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngDoc factory
|
||||
* @name designatedashboard.resources.os-designate-zone.actions.create
|
||||
*
|
||||
* @Description
|
||||
* Brings up the Create Zone modal.
|
||||
*/
|
||||
function action($q,
|
||||
forms,
|
||||
api,
|
||||
resourceTypeName,
|
||||
policy,
|
||||
serviceCatalog,
|
||||
schemaFormModalService,
|
||||
toast,
|
||||
waitSpinner) {
|
||||
var createZonePolicy, dnsServiceEnabled;
|
||||
var title = gettext("Create Zone");
|
||||
var message = {
|
||||
success: gettext('Zone %s was successfully created.')
|
||||
};
|
||||
|
||||
var service = {
|
||||
initScope: initScope,
|
||||
allowed: allowed,
|
||||
perform: perform
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
/////////////////
|
||||
|
||||
function initScope() {
|
||||
createZonePolicy = policy.ifAllowed({rules: [['dns', 'create_zone']]});
|
||||
dnsServiceEnabled = serviceCatalog.ifTypeEnabled('dns');
|
||||
}
|
||||
|
||||
function allowed() {
|
||||
return $q.all([
|
||||
createZonePolicy,
|
||||
dnsServiceEnabled
|
||||
]);
|
||||
}
|
||||
|
||||
function perform() {
|
||||
var formConfig = forms.getCreateFormConfig();
|
||||
formConfig.title = title;
|
||||
return schemaFormModalService.open(formConfig).then(onSubmit, onCancel);
|
||||
}
|
||||
|
||||
function onSubmit(context) {
|
||||
var zoneModel = angular.copy(context.model);
|
||||
// schema form doesn't appear to support populating the masters array directly
|
||||
// Map the masters objects to simple array of addresses
|
||||
if (context.model.hasOwnProperty("masters")) {
|
||||
var masters = context.model.masters.map(function (item) {
|
||||
return item.address;
|
||||
});
|
||||
zoneModel.masters = masters;
|
||||
}
|
||||
|
||||
waitSpinner.showModalSpinner(gettext('Creating Zone'));
|
||||
|
||||
return api.create(zoneModel).then(onSuccess, onFailure);
|
||||
}
|
||||
|
||||
function onCancel() {
|
||||
waitSpinner.hideModalSpinner();
|
||||
}
|
||||
|
||||
function onSuccess(response) {
|
||||
waitSpinner.hideModalSpinner();
|
||||
var zone = response.data;
|
||||
toast.add('success', interpolate(message.success, [zone.name]));
|
||||
|
||||
// To make the result of this action generically useful, reformat the return
|
||||
// from the deleteModal into a standard form
|
||||
return {
|
||||
created: [{type: resourceTypeName, id: zone.id}],
|
||||
updated: [],
|
||||
deleted: [],
|
||||
failed: []
|
||||
};
|
||||
}
|
||||
|
||||
function onFailure() {
|
||||
waitSpinner.hideModalSpinner();
|
||||
}
|
||||
}
|
||||
})();
|
@ -0,0 +1,169 @@
|
||||
/**
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use self file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('designatedashboard.resources.os-designate-zone.actions')
|
||||
.factory('designatedashboard.resources.os-designate-zone.actions.delete', action);
|
||||
|
||||
action.$inject = [
|
||||
'$q',
|
||||
'designatedashboard.resources.os-designate-zone.api',
|
||||
'designatedashboard.resources.util',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
'horizon.framework.util.actions.action-result.service',
|
||||
'horizon.framework.util.i18n.gettext',
|
||||
'horizon.framework.util.q.extensions',
|
||||
'horizon.framework.widgets.modal.deleteModalService',
|
||||
'horizon.framework.widgets.toast.service',
|
||||
'designatedashboard.resources.os-designate-zone.resourceType'
|
||||
];
|
||||
|
||||
/*
|
||||
* @ngdoc factory
|
||||
* @name designatedashboard.resources.os-designate-zone.actions.delete
|
||||
*
|
||||
* @Description
|
||||
* Brings up the delete zone confirmation modal dialog.
|
||||
|
||||
* On submit, delete given zone.
|
||||
* On cancel, do nothing.
|
||||
*/
|
||||
function action(
|
||||
$q,
|
||||
zoneApi,
|
||||
util,
|
||||
policy,
|
||||
actionResultService,
|
||||
gettext,
|
||||
$qExtensions,
|
||||
deleteModal,
|
||||
toast,
|
||||
resourceType
|
||||
) {
|
||||
var scope, context, deleteZonePromise;
|
||||
var notAllowedMessage = gettext("You are not allowed to delete zones: %s");
|
||||
|
||||
var service = {
|
||||
initScope: initScope,
|
||||
allowed: allowed,
|
||||
perform: perform
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
//////////////
|
||||
|
||||
function initScope(newScope) {
|
||||
scope = newScope;
|
||||
context = { };
|
||||
deleteZonePromise = policy.ifAllowed({rules: [['dns', 'delete_zone']]});
|
||||
}
|
||||
|
||||
function perform(items) {
|
||||
var zones = angular.isArray(items) ? items : [items];
|
||||
context.labels = labelize(zones.length);
|
||||
context.deleteEntity = deleteZone;
|
||||
return $qExtensions.allSettled(zones.map(checkPermission)).then(afterCheck);
|
||||
}
|
||||
|
||||
function allowed(zone) {
|
||||
// only row actions pass in zone
|
||||
// otherwise, assume it is a batch action
|
||||
if (zone) {
|
||||
return $q.all([
|
||||
deleteZonePromise,
|
||||
util.notDeleted(zone),
|
||||
util.notPending(zone)
|
||||
]);
|
||||
} else {
|
||||
return policy.ifAllowed({ rules: [['dns', 'delete_zone']] });
|
||||
}
|
||||
}
|
||||
|
||||
function checkPermission(zone) {
|
||||
return {promise: allowed(zone), context: zone};
|
||||
}
|
||||
|
||||
function afterCheck(result) {
|
||||
var outcome = $q.reject(); // Reject the promise by default
|
||||
if (result.fail.length > 0) {
|
||||
toast.add('error', getMessage(notAllowedMessage, result.fail));
|
||||
outcome = $q.reject(result.fail);
|
||||
}
|
||||
if (result.pass.length > 0) {
|
||||
outcome = deleteModal.open(scope, result.pass.map(getEntity), context).then(createResult);
|
||||
}
|
||||
return outcome;
|
||||
}
|
||||
|
||||
function createResult(deleteModalResult) {
|
||||
// To make the result of this action generically useful, reformat the return
|
||||
// from the deleteModal into a standard form
|
||||
var actionResult = actionResultService.getActionResult();
|
||||
deleteModalResult.pass.forEach(function markDeleted(item) {
|
||||
actionResult.deleted(resourceType, getEntity(item).id);
|
||||
});
|
||||
deleteModalResult.fail.forEach(function markFailed(item) {
|
||||
actionResult.failed(resourceType, getEntity(item).id);
|
||||
});
|
||||
return actionResult.result;
|
||||
}
|
||||
|
||||
function labelize(count) {
|
||||
return {
|
||||
|
||||
title: ngettext(
|
||||
'Confirm Delete Zone',
|
||||
'Confirm Delete Zones', count),
|
||||
|
||||
message: ngettext(
|
||||
'You have selected "%s". Deleted zone is not recoverable.',
|
||||
'You have selected "%s". Deleted zones are not recoverable.', count),
|
||||
|
||||
submit: ngettext(
|
||||
'Delete Zone',
|
||||
'Delete Zones', count),
|
||||
|
||||
success: ngettext(
|
||||
'Deleted Zone: %s.',
|
||||
'Deleted Zones: %s.', count),
|
||||
|
||||
error: ngettext(
|
||||
'Unable to delete Zone: %s.',
|
||||
'Unable to delete Zones: %s.', count)
|
||||
};
|
||||
}
|
||||
|
||||
function deleteZone(zone) {
|
||||
return zoneApi.deleteZone(zone, true);
|
||||
}
|
||||
|
||||
function getMessage(message, entities) {
|
||||
return interpolate(message, [entities.map(getName).join(", ")]);
|
||||
}
|
||||
|
||||
function getName(result) {
|
||||
return getEntity(result).name;
|
||||
}
|
||||
|
||||
function getEntity(result) {
|
||||
return result.context;
|
||||
}
|
||||
}
|
||||
})();
|
@ -0,0 +1,147 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development Company LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use self file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('designatedashboard.resources.os-designate-zone.actions')
|
||||
.factory('designatedashboard.resources.os-designate-zone.actions.update', action);
|
||||
|
||||
action.$inject = [
|
||||
'$q',
|
||||
'designatedashboard.resources.os-designate-zone.actions.common-forms',
|
||||
'designatedashboard.resources.os-designate-zone.api',
|
||||
'designatedashboard.resources.os-designate-zone.resourceType',
|
||||
'designatedashboard.resources.util',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
'horizon.app.core.openstack-service-api.serviceCatalog',
|
||||
'horizon.framework.widgets.form.ModalFormService',
|
||||
'horizon.framework.widgets.toast.service',
|
||||
'horizon.framework.widgets.modal-wait-spinner.service'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngDoc factory
|
||||
* @name designatedashboard.resources.os-designate-zone.actions.update
|
||||
*
|
||||
* @Description
|
||||
* Brings up the Update Zone modal.
|
||||
*/
|
||||
function action($q,
|
||||
forms,
|
||||
api,
|
||||
resourceTypeName,
|
||||
util,
|
||||
policy,
|
||||
serviceCatalog,
|
||||
schemaFormModalService,
|
||||
toast,
|
||||
waitSpinner) {
|
||||
var updateZonePolicy, dnsServiceEnabled;
|
||||
var title = gettext("Update Zone");
|
||||
var message = {
|
||||
success: gettext('Zone %s was successfully updated.')
|
||||
};
|
||||
|
||||
var service = {
|
||||
initScope: initScope,
|
||||
allowed: allowed,
|
||||
perform: perform
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
/////////////////
|
||||
|
||||
function initScope() {
|
||||
updateZonePolicy = policy.ifAllowed({rules: [['dns', 'update_zone']]});
|
||||
dnsServiceEnabled = serviceCatalog.ifTypeEnabled('dns');
|
||||
}
|
||||
|
||||
function allowed(zone) {
|
||||
// only supports row action (exactly 1 zone)
|
||||
if (zone) {
|
||||
return $q.all([
|
||||
updateZonePolicy,
|
||||
util.notDeleted(zone),
|
||||
util.notPending(zone)
|
||||
]);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function perform(item) {
|
||||
var formConfig = forms.getUpdateFormConfig();
|
||||
formConfig.title = title;
|
||||
formConfig.model = util.getModel(formConfig.form, item);
|
||||
|
||||
// Append the id so it can be used on submit
|
||||
formConfig.model.id = item.id;
|
||||
|
||||
// schema form doesn't appear to support populating the masters array directly
|
||||
// Map the masters objects to address objects
|
||||
if (item.hasOwnProperty("masters")) {
|
||||
var masters = item.masters.map(function (item) {
|
||||
return { "address": item }
|
||||
})
|
||||
formConfig.masters = masters;
|
||||
}
|
||||
return schemaFormModalService.open(formConfig).then(onSubmit, onCancel);
|
||||
}
|
||||
|
||||
function onSubmit(context) {
|
||||
var zoneModel = angular.copy(context.model);
|
||||
// schema form doesn't appear to support populating the masters array directly
|
||||
// Map the masters objects to simple array of addresses
|
||||
if (context.model.hasOwnProperty("masters")) {
|
||||
var masters = context.model.masters.map(function (item) {
|
||||
return item.address;
|
||||
})
|
||||
zoneModel.masters = masters;
|
||||
}
|
||||
|
||||
waitSpinner.showModalSpinner(gettext('Updating Zone'));
|
||||
|
||||
return api.update(zoneModel.id, zoneModel).then(onSuccess, onFailure);
|
||||
}
|
||||
|
||||
function onCancel() {
|
||||
waitSpinner.hideModalSpinner();
|
||||
}
|
||||
|
||||
function onSuccess(response) {
|
||||
waitSpinner.hideModalSpinner();
|
||||
var zone = response.data;
|
||||
toast.add('success', interpolate(message.success, [zone.name]));
|
||||
|
||||
// To make the result of this action generically useful, reformat the return
|
||||
// from the deleteModal into a standard form
|
||||
return {
|
||||
created: [],
|
||||
updated: [{type: resourceTypeName, id: zone.id}],
|
||||
deleted: [],
|
||||
failed: []
|
||||
};
|
||||
}
|
||||
|
||||
function onFailure() {
|
||||
waitSpinner.hideModalSpinner();
|
||||
}
|
||||
}
|
||||
})();
|
@ -0,0 +1,152 @@
|
||||
/**
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('designatedashboard.resources.os-designate-zone')
|
||||
.factory('designatedashboard.resources.os-designate-zone.api', apiService);
|
||||
|
||||
apiService.$inject = [
|
||||
'designatedashboard.apiPassthroughUrl',
|
||||
'horizon.framework.util.http.service',
|
||||
'horizon.framework.widgets.toast.service'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @param {Object} httpService
|
||||
* @param {Object} toastService
|
||||
* @name apiService
|
||||
* @description Provides direct access to Designate Zone APIs.
|
||||
* @returns {Object} The service
|
||||
*/
|
||||
function apiService(apiPassthroughUrl, httpService, toastService) {
|
||||
var service = {
|
||||
get: get,
|
||||
list: list,
|
||||
deleteZone: deleteZone,
|
||||
create: create,
|
||||
update: update
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
///////////////
|
||||
|
||||
/**
|
||||
* @name list
|
||||
* @description
|
||||
* Get a list of zones.
|
||||
*
|
||||
* The listing result is an object with property "items." Each item is
|
||||
* a zone.
|
||||
*
|
||||
* @param {Object} params
|
||||
* Query parameters. Optional.
|
||||
*
|
||||
* @returns {Object} The result of the API call
|
||||
*/
|
||||
/*
|
||||
function list(params) {
|
||||
var config = params ? {'params': params} : {};
|
||||
return httpService.get('/api/designate/zones/', config)
|
||||
.error(function () {
|
||||
toastService.add('error', gettext('Unable to retrieve the zone.'));
|
||||
});
|
||||
}*/
|
||||
function list(params) {
|
||||
var config = params ? {'params': params} : {};
|
||||
return httpService.get(apiPassthroughUrl + 'v2/zones/', config)
|
||||
.error(function () {
|
||||
toastService.add('error', gettext('Unable to retrieve the zone.'));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @name get
|
||||
* @description
|
||||
* Get a single zone by ID.
|
||||
*
|
||||
* @param {string} id
|
||||
* Specifies the id of the zone to request.
|
||||
*
|
||||
* @returns {Object} The result of the API call
|
||||
*/
|
||||
function get(id) {
|
||||
return httpService.get(apiPassthroughUrl + 'v2/zones/' + id + '/')
|
||||
.error(function () {
|
||||
toastService.add('error', gettext('Unable to retrieve the zone.'));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @name deleteZone
|
||||
* @description
|
||||
* Delete a single zone by ID
|
||||
* @param id
|
||||
* @returns {*}
|
||||
*/
|
||||
function deleteZone(id) {
|
||||
return httpService.delete(apiPassthroughUrl + 'v2/zones/' + id + '/')
|
||||
.error(function () {
|
||||
toastService.add('error', gettext('Unable to delete the zone.'));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @name create
|
||||
* @description
|
||||
* Create a zone
|
||||
*
|
||||
* @param {Object} data
|
||||
* Specifies the zone information to create
|
||||
*
|
||||
* @returns {Object} The created zone object
|
||||
*/
|
||||
function create(data) {
|
||||
return httpService.post(apiPassthroughUrl + 'v2/zones/', data)
|
||||
.error(function() {
|
||||
toastService.add('error', gettext('Unable to create the zone.'));
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @name create
|
||||
* @description
|
||||
* Update a zone
|
||||
*
|
||||
* @param {Object} id - zone id
|
||||
* @param {Object} data to pass directly to zone update API
|
||||
* Specifies the zone information to update
|
||||
*
|
||||
* @returns {Object} The updated zone object
|
||||
*/
|
||||
function update(id, data) {
|
||||
// The update API will not accept extra data. Restrict the input to only the allowed
|
||||
// fields
|
||||
var apiData = {
|
||||
email: data.email,
|
||||
ttl: data.ttl,
|
||||
description: data.description
|
||||
};
|
||||
return httpService.patch(apiPassthroughUrl + 'v2/zones/' + id + '/', apiData )
|
||||
.error(function() {
|
||||
toastService.add('error', gettext('Unable to update the zone.'));
|
||||
})
|
||||
}
|
||||
}
|
||||
}());
|
@ -0,0 +1,61 @@
|
||||
/**
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc overview
|
||||
* @ngname designatedashboard.resources.os-designate-zone.details
|
||||
*
|
||||
* @description
|
||||
* Provides details features for zones.
|
||||
*/
|
||||
angular.module('designatedashboard.resources.os-designate-zone.details',
|
||||
['horizon.framework.conf', 'horizon.app.core'])
|
||||
.run(run);
|
||||
|
||||
run.$inject = [
|
||||
'designatedashboard.resources.os-designate-zone.resourceType',
|
||||
'designatedashboard.resources.os-designate-zone.api',
|
||||
'designatedashboard.resources.os-designate-zone.basePath',
|
||||
'horizon.framework.conf.resource-type-registry.service'
|
||||
];
|
||||
|
||||
function run(
|
||||
zoneResourceType,
|
||||
zoneApi,
|
||||
basePath,
|
||||
registry
|
||||
) {
|
||||
var resourceType = registry.getResourceType(zoneResourceType);
|
||||
resourceType
|
||||
.setLoadFunction(loadFunction)
|
||||
.setSummaryTemplateUrl(basePath + 'details/drawer.html');
|
||||
|
||||
resourceType.detailsViews
|
||||
.prepend({
|
||||
id: 'zoneDetailsOverview',
|
||||
name: gettext('Overview'),
|
||||
template: basePath + 'details/overview.html',
|
||||
}, 0);
|
||||
|
||||
function loadFunction(identifier) {
|
||||
return zoneApi.get(identifier);
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,10 @@
|
||||
<hz-resource-property-list
|
||||
ng-if="item"
|
||||
resource-type-name="OS::Designate::Zone"
|
||||
item="item"
|
||||
cls="dl-horizontal"
|
||||
property-groups="[
|
||||
['description', 'email'],
|
||||
['id', 'pool_id', 'project_id']
|
||||
]">
|
||||
</hz-resource-property-list>
|
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
angular
|
||||
.module('designatedashboard.resources.os-designate-zone')
|
||||
.controller('designatedashboard.resources.os-designate-zone.detailController', controller);
|
||||
|
||||
controller.$inject = [
|
||||
'designatedashboard.resources.os-designate-zone.resourceType',
|
||||
'horizon.framework.conf.resource-type-registry.service',
|
||||
'$scope'
|
||||
];
|
||||
|
||||
function controller(
|
||||
resourceTypeCode,
|
||||
registry,
|
||||
$scope
|
||||
) {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.item;
|
||||
ctrl.resourceType = registry.getResourceType(resourceTypeCode);
|
||||
|
||||
$scope.context.loadPromise.then(onGetResponse);
|
||||
|
||||
function onGetResponse(response) {
|
||||
ctrl.item = response.data;
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,58 @@
|
||||
<div ng-controller="designatedashboard.resources.os-designate-zone.detailController as ctrl">
|
||||
<div class="row">
|
||||
<div class="col-md-6 detail">
|
||||
<h3 translate>Details</h3>
|
||||
<hr>
|
||||
<hz-resource-property-list
|
||||
ng-if="ctrl.item"
|
||||
resource-type-name="OS::Designate::Zone"
|
||||
item="ctrl.item"
|
||||
cls="dl-horizontal"
|
||||
property-groups="[
|
||||
['id', 'description', 'type', 'status', 'action', 'email', 'serial', 'ttl', 'version']
|
||||
]">
|
||||
</hz-resource-property-list>
|
||||
</div>
|
||||
<div class="col-md-6 detail">
|
||||
<h3 translate>Attributes</h3>
|
||||
<hr>
|
||||
<hz-resource-property-list
|
||||
ng-if="ctrl.item"
|
||||
resource-type-name="OS::Designate::Zone"
|
||||
item="ctrl.item"
|
||||
cls="dl-horizontal"
|
||||
property-groups="[
|
||||
['attributes']
|
||||
]">
|
||||
</hz-resource-property-list>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 detail">
|
||||
<h3 translate>Modification Times</h3>
|
||||
<hr>
|
||||
<hz-resource-property-list
|
||||
ng-if="ctrl.item"
|
||||
resource-type-name="OS::Designate::Zone"
|
||||
item="ctrl.item"
|
||||
cls="dl-horizontal"
|
||||
property-groups="[
|
||||
['created_at', 'updated_at', 'transferred_at']
|
||||
]">
|
||||
</hz-resource-property-list>
|
||||
</div>
|
||||
<div class="col-md-6 detail">
|
||||
<h3 translate>Associations</h3>
|
||||
<hr>
|
||||
<hz-resource-property-list
|
||||
ng-if="ctrl.item"
|
||||
resource-type-name="OS::Designate::Zone"
|
||||
item="ctrl.item"
|
||||
cls="dl-horizontal"
|
||||
property-groups="[
|
||||
['pool_id', 'project_id', 'masters']
|
||||
]">
|
||||
</hz-resource-property-list>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,202 @@
|
||||
/**
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc overview
|
||||
* @ngname designatedashboard.resources.os-designate-zone
|
||||
*
|
||||
* @description
|
||||
* Provides all of the services and widgets required
|
||||
* to support and display DNS (designate) zone related content.
|
||||
*/
|
||||
angular
|
||||
.module('designatedashboard.resources.os-designate-zone', [
|
||||
'ngRoute',
|
||||
'designatedashboard.resources.os-designate-zone.actions',
|
||||
'designatedashboard.resources.os-designate-zone.details'
|
||||
])
|
||||
.constant(
|
||||
'designatedashboard.resources.os-designate-zone.resourceType',
|
||||
'OS::Designate::Zone')
|
||||
.config(config)
|
||||
.run(run);
|
||||
|
||||
config.$inject = ['$provide', '$windowProvider'];
|
||||
|
||||
function config($provide, $windowProvider) {
|
||||
var path = $windowProvider.$get().STATIC_URL + 'designatedashboard/resources/os-designate-zone/';
|
||||
$provide.constant('designatedashboard.resources.os-designate-zone.basePath', path);
|
||||
}
|
||||
|
||||
run.$inject = [
|
||||
'horizon.framework.conf.resource-type-registry.service',
|
||||
'designatedashboard.resources.os-designate-zone.api',
|
||||
'designatedashboard.resources.os-designate-zone.resourceType',
|
||||
'designatedashboard.resources.util'
|
||||
];
|
||||
|
||||
function run(registry,
|
||||
zoneApi,
|
||||
resourceTypeString,
|
||||
util) {
|
||||
var resourceType = registry.getResourceType(resourceTypeString);
|
||||
resourceType
|
||||
.setNames(gettext('DNS Zone'), gettext('DNS Zones'))
|
||||
.setListFunction(listZones)
|
||||
.setProperty('action', {
|
||||
label: gettext('Action'),
|
||||
filters: ['lowercase', 'noName'],
|
||||
values: util.actionMap()
|
||||
})
|
||||
.setProperty('attributes', {
|
||||
label: gettext('Attributes')
|
||||
})
|
||||
.setProperty('created_at', {
|
||||
label: gettext('Created At'),
|
||||
filters: ['noValue']
|
||||
})
|
||||
.setProperty('description', {
|
||||
label: gettext('Description'),
|
||||
filters: ['noName']
|
||||
})
|
||||
.setProperty('email', {
|
||||
label: gettext('Email'),
|
||||
filters: ['noName']
|
||||
})
|
||||
.setProperty('id', {
|
||||
label: gettext('ID')
|
||||
})
|
||||
.setProperty('masters', {
|
||||
label: gettext('Masters'),
|
||||
filters: ['noValue']
|
||||
})
|
||||
.setProperty('name', {
|
||||
label: gettext('Name'),
|
||||
filters: ['noName']
|
||||
})
|
||||
.setProperty('pool_id', {
|
||||
label: gettext('Pool ID')
|
||||
})
|
||||
.setProperty('project_id', {
|
||||
label: gettext('Project ID')
|
||||
})
|
||||
.setProperty('serial', {
|
||||
label: gettext('Serial'),
|
||||
filters: ['noValue']
|
||||
})
|
||||
.setProperty('status', {
|
||||
label: gettext('Status'),
|
||||
filters: ['lowercase', 'noName'],
|
||||
values: util.statusMap()
|
||||
})
|
||||
.setProperty('transferred_at', {
|
||||
label: gettext('Transferred At'),
|
||||
filters: ['noValue']
|
||||
})
|
||||
.setProperty('ttl', {
|
||||
label: gettext('Time To Live'),
|
||||
filters: ['noValue']
|
||||
})
|
||||
.setProperty('type', {
|
||||
label: gettext('Type'),
|
||||
filters: ['lowercase', 'noName'],
|
||||
values: typeMap()
|
||||
})
|
||||
.setProperty('updated_at', {
|
||||
label: gettext('Updated At'),
|
||||
filters: ['noValue']
|
||||
})
|
||||
.setProperty('version', {
|
||||
label: gettext('Version'),
|
||||
filters: ['noValue']
|
||||
});
|
||||
|
||||
resourceType
|
||||
.tableColumns
|
||||
.append({
|
||||
id: 'name',
|
||||
priority: 1,
|
||||
sortDefault: true,
|
||||
template: '<a ng-href="{$ \'project/ngdetails/OS::Designate::Zone/\' + item.id $}">{$ item.name $}</a>'
|
||||
})
|
||||
.append({
|
||||
id: 'type',
|
||||
filters: ['lowercase'],
|
||||
values: typeMap(),
|
||||
priority: 2
|
||||
})
|
||||
.append({
|
||||
id: 'status',
|
||||
filters: ['lowercase'],
|
||||
values: util.statusMap(),
|
||||
priority: 2
|
||||
});
|
||||
|
||||
resourceType
|
||||
.filterFacets
|
||||
.append({
|
||||
label: gettext('Name'),
|
||||
name: 'name',
|
||||
isServer: false,
|
||||
singleton: true,
|
||||
persistent: false
|
||||
})
|
||||
.append({
|
||||
label: gettext('Type'),
|
||||
name: 'type',
|
||||
isServer: false,
|
||||
singleton: true,
|
||||
persistent: false,
|
||||
options: [
|
||||
{label: gettext('Primary'), key: 'primary'},
|
||||
{label: gettext('Secondary'), key: 'secondary'}
|
||||
]
|
||||
})
|
||||
.append({
|
||||
label: gettext('Status'),
|
||||
name: 'status',
|
||||
isServer: false,
|
||||
singleton: true,
|
||||
persistent: false,
|
||||
options: [
|
||||
{label: gettext('Active'), key: 'active'},
|
||||
{label: gettext('Pending'), key: 'pending'}
|
||||
]
|
||||
});
|
||||
|
||||
function typeMap() {
|
||||
return {
|
||||
'primary': gettext('Primary'),
|
||||
'secondary': gettext('Secondary')
|
||||
}
|
||||
}
|
||||
|
||||
function listZones() {
|
||||
return zoneApi.list().then(function onList(response) {
|
||||
// listFunctions are expected to return data in "items"
|
||||
response.data.items = response.data.zones;
|
||||
|
||||
util.addTimestampIds(response.data.items, 'updated_at');
|
||||
|
||||
return response;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* (c) Copyright 2016 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc overview
|
||||
* @name designatedashboard.resources
|
||||
* @description
|
||||
*
|
||||
* # designatedashboard.resources
|
||||
*
|
||||
* This module hosts registered resource types. This module file may
|
||||
* contain individual registrations, or may have sub-modules that
|
||||
* more fully contain registrations.
|
||||
*/
|
||||
angular
|
||||
.module('designatedashboard.resources', [
|
||||
'designatedashboard.resources.os-designate-recordset',
|
||||
'designatedashboard.resources.os-designate-zone',
|
||||
'designatedashboard.resources.os-designate-floatingip'
|
||||
]);
|
||||
})();
|
@ -0,0 +1,107 @@
|
||||
/**
|
||||
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('designatedashboard.resources')
|
||||
.factory('designatedashboard.resources.util', utilService);
|
||||
|
||||
utilService.$inject = [
|
||||
'horizon.framework.util.q.extensions',
|
||||
];
|
||||
|
||||
|
||||
function utilService($qExtensions) {
|
||||
var service = {
|
||||
notDeleted: notDeleted,
|
||||
notPending: notPending,
|
||||
getModel: getModel,
|
||||
actionMap: actionMap,
|
||||
statusMap: statusMap,
|
||||
addTimestampIds: addTimestampIds
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
///////////////
|
||||
|
||||
function notDeleted(resource) {
|
||||
return $qExtensions.booleanAsPromise(resource.status !== 'DELETED');
|
||||
}
|
||||
|
||||
function notPending(resource) {
|
||||
return $qExtensions.booleanAsPromise(resource.status !== 'PENDING');
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a model object based on the given item, using only the fields present in the form config 'key's.
|
||||
* Only 'truthy' values are copied.
|
||||
*
|
||||
* @param form - an array of objects describing the form. Must have a 'key' attribute.
|
||||
* @param item - the data to copy into the model
|
||||
*/
|
||||
function getModel(form, item) {
|
||||
var result = {};
|
||||
var value;
|
||||
form.forEach(function iterateForm(formItem) {
|
||||
value = item[formItem.key];
|
||||
if (value) {
|
||||
result[formItem.key] = item[formItem.key];
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function actionMap() {
|
||||
return {
|
||||
'none': gettext('None'),
|
||||
'create': gettext('Create')
|
||||
}
|
||||
}
|
||||
|
||||
function statusMap() {
|
||||
return {
|
||||
'active': gettext('Active'),
|
||||
'pending': gettext('Pending')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* hz-resource-table tracks by 'id' which doesn't change when an individual item is updated.
|
||||
* Create a synthetic '_timestampId' using the item id plus the specified timestamp field.
|
||||
* When this field is used as a track-by in hz-resource-table, items in the table to update
|
||||
* after row actions.
|
||||
*
|
||||
* If a timestamp field is not specified, the current time is used.
|
||||
*
|
||||
* @param items {object} - The items to add a _timestampId.
|
||||
* @param idField {string} - (Optional) A field on the item to use as the id. Defaults to 'id'
|
||||
* @param timestampField {string} - (Optional) A field on item to use as a timestamp. Defaults
|
||||
* to current time.
|
||||
*/
|
||||
function addTimestampIds(items, idField, timestampField) {
|
||||
var _idField = idField || 'id';
|
||||
var timestamp = Date.now();
|
||||
items.map(function annotateFloatingIp(item) {
|
||||
if ( angular.isDefined(timestampField) ) {
|
||||
timestamp = item[timestampField];
|
||||
}
|
||||
item._timestampId = item[_idField] + timestamp;
|
||||
});
|
||||
}
|
||||
}
|
||||
}());
|
@ -0,0 +1,4 @@
|
||||
<hz-resource-panel resource-type-name="OS::Designate::FloatingIp">
|
||||
<hz-resource-table resource-type-name="OS::Designate::FloatingIp"
|
||||
track-by="_timestampId"></hz-resource-table>
|
||||
</hz-resource-panel>
|
4
designatedashboard/static/designatedashboard/zones.html
Normal file
4
designatedashboard/static/designatedashboard/zones.html
Normal file
@ -0,0 +1,4 @@
|
||||
<hz-resource-panel resource-type-name="OS::Designate::Zone">
|
||||
<hz-resource-table resource-type-name="OS::Designate::Zone"
|
||||
track-by="_timestampId"></hz-resource-table>
|
||||
</hz-resource-panel>
|
Loading…
Reference in New Issue
Block a user