diff --git a/app/index.html b/app/index.html index 71a5c0c718..c836dc4c2c 100644 --- a/app/index.html +++ b/app/index.html @@ -255,6 +255,8 @@

JavaScript Required

+ + diff --git a/app/scripts/app.js b/app/scripts/app.js index ca4513454c..78c47d6d03 100644 --- a/app/scripts/app.js +++ b/app/scripts/app.js @@ -271,6 +271,16 @@ angular controller: 'ServiceController', reloadOnSearch: false }) + .when('/project/:project/browse/service-instances', { + templateUrl: 'views/service-instances.html', + controller: 'ServiceInstancesController', + reloadOnSearch: false + }) + .when('/project/:project/browse/service-instances/:instance', { + templateUrl: 'views/browse/service-instance.html', + controller: 'ServiceInstanceController', + reloadOnSearch: false + }) .when('/project/:project/browse/storage', { templateUrl: 'views/storage.html', controller: 'StorageController', diff --git a/app/scripts/constants.js b/app/scripts/constants.js index 1dfcc84f35..333bf3b40c 100644 --- a/app/scripts/constants.js +++ b/app/scripts/constants.js @@ -190,6 +190,23 @@ angular.extend(window.OPENSHIFT_CONSTANTS, { prefixes: [ "/browse/routes/" ] + }, + { + label: "Provisioned Services", + href: "/browse/service-instances", + prefixes: [ + "/browse/service-instances/" + ], + isValid: function(){ + return _.get(window.OPENSHIFT_CONSTANTS, 'ENABLE_TECH_PREVIEW_FEATURE.service_catalog_landing_page'); + }, + canI: { + resource: { + group: 'servicecatalog.k8s.io', + resource: 'instances' + }, + verb: 'list' + } } ] } diff --git a/app/scripts/controllers/serviceInstance.js b/app/scripts/controllers/serviceInstance.js new file mode 100644 index 0000000000..14bfeeff3d --- /dev/null +++ b/app/scripts/controllers/serviceInstance.js @@ -0,0 +1,104 @@ +'use strict'; + +angular.module('openshiftConsole') + .controller('ServiceInstanceController', function ($scope, + $filter, + $routeParams, + DataService, + ProjectsService) { + $scope.alerts = {}; + //$scope.displayName = null; + $scope.projectName = $routeParams.project; + $scope.serviceInstance = null; + $scope.serviceClass = null; + $scope.serviceClasses = {}; + + $scope.breadcrumbs = [ + { + title: "Provisioned Services", + link: "project/" + $routeParams.project + "/browse/service-instances" + }, + { + title: $routeParams.instance + } + ]; + + var watches = []; + + /*var setDisplayName = function() { + if(!$scope.serviceInstance || !$scope.serviceClasses) { + return; + } + + $scope.displayName = $filter('serviceInstanceDisplayName')($scope.serviceInstance, $scope.serviceClasses); + };*/ + + var updateServiceClassMetadata = function() { + if(!$scope.serviceInstance || !$scope.serviceClasses) { + return; + } + + var serviceClassName = _.get($scope.serviceInstance.spec, 'serviceClassName'); + $scope.serviceClass = _.get($scope.serviceClasses, [serviceClassName]); + $scope.plan = _.find(_.get($scope.serviceClass, 'plans'), {name: 'default'}); + }; + + var serviceResolved = function(service, action) { + $scope.loaded = true; + $scope.serviceInstance = service; + + if (action === "DELETED") { + $scope.alerts["deleted"] = { + type: "warning", + message: "This provisioned service has been deleted." + }; + } + + //setDisplayName(); + updateServiceClassMetadata(); + }; + + ProjectsService + .get($routeParams.project) + .then(_.spread(function(project, context) { + $scope.project = project; + $scope.projectContext = context; + + DataService + .get({ + group: 'servicecatalog.k8s.io', + resource: 'instances' + }, $routeParams.instance, context, { errorNotification: false }) + .then(function(service) { + + serviceResolved(service); + + watches.push(DataService.watchObject({ + group: 'servicecatalog.k8s.io', + resource: 'instances' + }, $routeParams.instance, context, serviceResolved)); + + }, function(error) { + $scope.loaded = true; + $scope.alerts["load"] = { + type: "error", + message: "The service details could not be loaded.", + details: $filter('getErrorDetails')(error) + }; + }); + + DataService.list({ + group: 'servicecatalog.k8s.io', + resource: 'serviceclasses' + }, context, function(serviceClasses) { + $scope.serviceClasses = serviceClasses.by('metadata.name'); + //setDisplayName(); + updateServiceClassMetadata(); + }); + + $scope.$on('$destroy', function(){ + DataService.unwatchAll(watches); + }); + + })); + }); diff --git a/app/scripts/controllers/serviceInstances.js b/app/scripts/controllers/serviceInstances.js new file mode 100644 index 0000000000..5e7b7a5935 --- /dev/null +++ b/app/scripts/controllers/serviceInstances.js @@ -0,0 +1,185 @@ +'use strict'; + +angular.module('openshiftConsole') + .controller('ServiceInstancesController', function ($scope, + $filter, + $routeParams, + APIService, + BindingService, + Constants, + DataService, + LabelFilter, + Logger, + ProjectsService) { + $scope.alerts = {}; + $scope.applicationsByBinding = {}; + $scope.bindings = {}; + $scope.bindableServiceInstances = {}; + //$scope.bindingsByApplicationUID = {}; + $scope.bindingsByInstanceRef = {}; + $scope.emptyMessage = "Loading..."; + $scope.labelSuggestions = {}; + $scope.projectName = $routeParams.project; + $scope.serviceClasses = {}; + $scope.serviceInstances = {}; + $scope.unfilteredServiceInstances = {}; + + var watches = []; + + var updateFilter = function() { + $scope.serviceInstances = LabelFilter.getLabelSelector().select($scope.unfilteredServiceInstances); + }; + + var sortServiceInstances = function() { + $scope.bindableServiceInstances = BindingService.filterBindableServiceInstances($scope.unfilteredServiceInstances, $scope.serviceClasses); + $scope.unfilteredServiceInstances = BindingService.sortServiceInstances($scope.unfilteredServiceInstances, $scope.serviceClasses); + }; + + var groupBindings = function() { + // Build two maps: + // - Bindings by the UID of the target object + // - API objects by binding name + /* + state.bindingsByApplicationUID = {}; + state.applicationsByBinding = {}; + //state.deleteableBindingsByApplicationUID = {}; + + // If there are no bindings, nothing to do. + if (_.isEmpty(state.bindings)) { + return; + } + + // All objects that can be a target for bindings. + var objectsByKind = [ + overview.deployments, + overview.deploymentConfigs, + overview.vanillaReplicationControllers, + overview.vanillaReplicaSets, + overview.statefulSets + ]; + + // Make sure all the binding targets have loaded first. + if (_.some(objectsByKind, function(collection) { return !collection; })) { + return; + } + + // Build a map of pod preset selectors by binding name. + var podPresetSelectors = {}; + _.each(state.bindings, function(binding) { + var podPresetSelector = _.get(binding, 'spec.alphaPodPresetTemplate.selector'); + if (podPresetSelector) { + podPresetSelectors[binding.metadata.name] = new LabelSelector(podPresetSelector); + } + }); + + _.each(objectsByKind, function(collection) { + _.each(collection, function(apiObject) { + // Key by UID since name is not unique across different kinds. + var applicationUID = getUID(apiObject); + + // Create a selector for the potential binding target to check if the + // pod preset covers the selector. + var applicationSelector = new LabelSelector(_.get(apiObject, 'spec.selector')); + state.bindingsByApplicationUID[applicationUID] = []; + state.deleteableBindingsByApplicationUID[applicationUID] = []; + + // Look at each pod preset selector to see if it covers this API object selector. + _.each(podPresetSelectors, function(podPresetSelector, bindingName) { + if (podPresetSelector.covers(applicationSelector)) { + // Keep a map of the target UID to the binding and the binding to + // the target. We want to show bindings both in the "application" + // object rows and the service instance rows. + state.bindingsByApplicationUID[applicationUID].push(state.bindings[bindingName]); + if (!_.get(state.bindings[bindingName], 'metadata.deletionTimestamp')) { + state.deleteableBindingsByApplicationUID[applicationUID].push(state.bindings[bindingName]); + } + state.applicationsByBinding[bindingName] = state.applicationsByBinding[bindingName] || []; + state.applicationsByBinding[bindingName].push(apiObject); + } + }); + }); + }); + + $scope.bindingsByInstanceRef = _.reduce(state.bindingsByInstanceRef, function(result, bindingList, key) { + result[key] = _.sortBy(bindingList, function(binding) { + var apps = _.get(state.applicationsByBinding, [binding.metadata.name]); + var firstName = _.get(_.head(apps), ['metadata', 'name']); + return firstName || binding.metadata.name; + }); + return result; + }, {});*/ + }; + + ProjectsService + .get($routeParams.project) + .then(_.spread(function(project, context) { + $scope.project = project; + $scope.projectContext = context; + + watches.push(DataService.watch({ + group: 'servicecatalog.k8s.io', + resource: 'bindings' + }, context, function(bindings) { + $scope.bindings = bindings.by('metadata.name'); + $scope.bindingsByInstanceRef = _.groupBy($scope.bindings, 'spec.instanceRef.name'); + groupBindings(); + //refreshSecrets(context); + })); + + watches.push(DataService.watch({ + group: 'servicecatalog.k8s.io', + resource: 'instances' + }, context, function(serviceInstances) { + $scope.emptyMessage = "No provisioned services to show"; + $scope.unfilteredServiceInstances = serviceInstances.by('metadata.name'); + + //_.each($scope.unfilteredServiceInstances, function (instance) { + // var notifications = ResourceAlertsService.getServiceInstanceAlerts(instance); + // setNotifications(instance, notifications); + //}); + + sortServiceInstances(); + updateFilter(); + updateFilterWarning(); + + LabelFilter.addLabelSuggestionsFromResources($scope.unfilteredServiceInstances, $scope.labelSuggestions); + LabelFilter.setLabelSuggestions($scope.labelSuggestions); + + Logger.log("provisioned services (subscribe)", $scope.unfilteredServiceInstances); + })); + + DataService.list({ + group: 'servicecatalog.k8s.io', + resource: 'serviceclasses' + }, context, function(serviceClasses) { + $scope.serviceClasses = serviceClasses.by('metadata.name'); + sortServiceInstances(); + updateFilter(); + }); + + function updateFilterWarning() { + if (!LabelFilter.getLabelSelector().isEmpty() && _.isEmpty($scope.serviceInstances) && !_.isEmpty($scope.unfilteredServiceInstances)) { + $scope.alerts["all-instances-filtered"] = { + type: "warning", + details: "The active filters are hiding all provisioned services." + }; + } + else { + delete $scope.alerts["all-instances-filtered"]; + } + } + + LabelFilter.onActiveFiltersChanged(function(labelSelector) { + // trigger a digest loop + $scope.$apply(function() { + $scope.serviceInstances = labelSelector.select($scope.unfilteredServiceInstances); + updateFilterWarning(); + }); + }); + + $scope.$on('$destroy', function(){ + DataService.unwatchAll(watches); + }); + + })); + }); diff --git a/app/scripts/directives/overview/serviceBinding.js b/app/scripts/directives/overview/serviceBinding.js index 02b56107da..836f0068bb 100644 --- a/app/scripts/directives/overview/serviceBinding.js +++ b/app/scripts/directives/overview/serviceBinding.js @@ -9,6 +9,7 @@ bindings: { namespace: '<', binding: '<', + refApiObject: ' + + + +
+
+
+
+ + +
Loading...
+
+

+ + {{serviceInstance | serviceInstanceDisplayName:serviceClasses}} + created +

+ +
+
+
+
+
+
+
+ + + Details +
+
+
+

Plan

+

+ {{plan.description}} +

+
+
Description:
+
+

+

+
+
Status:
+
+ + {{serviceInstance | serviceInstanceStatus | sentenceCase}} +
+
Status Reason:
+
+ {{serviceInstance | serviceInstanceMessage}} +
+ +
+
+
+ + +
+
+ +
+
+ + Events + + +
+
+
+
+
+
+
+
diff --git a/app/views/directives/resource-service-bindings.html b/app/views/directives/resource-service-bindings.html index 5a24978902..b2fab00811 100644 --- a/app/views/directives/resource-service-bindings.html +++ b/app/views/directives/resource-service-bindings.html @@ -1,9 +1,10 @@
-

Service Bindings

+

Bindings

diff --git a/app/views/overview/_service-binding.html b/app/views/overview/_service-binding.html index a57cefd0a6..d1501c308d 100644 --- a/app/views/overview/_service-binding.html +++ b/app/views/overview/_service-binding.html @@ -3,7 +3,12 @@

- {{$ctrl.serviceClass.externalMetadata.displayName || $ctrl.serviceClass.metadata.name}} + + {{$ctrl.serviceClass.externalMetadata.displayName || $ctrl.serviceClass.metadata.name}} + + + {{$ctrl.binding.spec.secretName}} + {{$ctrl.binding.spec.instanceRef.name}} diff --git a/app/views/overview/_service-instance-row.html b/app/views/overview/_service-instance-row.html index 69b4699809..3f11b9f57f 100644 --- a/app/views/overview/_service-instance-row.html +++ b/app/views/overview/_service-instance-row.html @@ -6,7 +6,8 @@

- + +

diff --git a/app/views/service-instances.html b/app/views/service-instances.html new file mode 100644 index 0000000000..435cc48e85 --- /dev/null +++ b/app/views/service-instances.html @@ -0,0 +1,89 @@ + + + + +
+
+
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
NameStatusCreatedBindings
{{emptyMessage}}
{{serviceInstance | serviceInstanceDisplayName:serviceClasses}} +
+ + {{serviceInstance | serviceInstanceStatus | sentenceCase}} +
+
+ ago + +
+

+ + {{application.metadata.name}} + + + {{firstBinding.spec.secretName}} + + + +

+
+
+ No bindings +
+
+
+
+
+
+
+
+
diff --git a/dist/scripts/scripts.js b/dist/scripts/scripts.js index badb5c1aa8..f746960df8 100644 --- a/dist/scripts/scripts.js +++ b/dist/scripts/scripts.js @@ -3,7 +3,7 @@ function OverviewController(e, t, n, a, r, o, i, s, c, l, u, d, m, p, g, f, h, v, y, b, C, S, w, k, j) { var P = this, R = t("isIE")() || t("isEdge")(); e.projectName = n.project; -var E, T, I = t("annotation"), N = t("buildConfigForBuild"), D = t("deploymentIsInProgress"), A = t("imageObjectRef"), B = t("isJenkinsPipelineStrategy"), L = t("isNewerResource"), U = t("label"), O = t("podTemplate"), x = {}, F = {}, M = {}, V = P.state = { +var E, I, T = t("annotation"), N = t("buildConfigForBuild"), D = t("deploymentIsInProgress"), A = t("imageObjectRef"), B = t("isJenkinsPipelineStrategy"), L = t("isNewerResource"), U = t("label"), O = t("podTemplate"), x = {}, F = {}, M = {}, V = P.state = { alerts: {}, builds: {}, clusterQuotas: {}, @@ -53,10 +53,10 @@ return _.get(e, "metadata.name"); return _.get(e, "metadata.uid"); }, K = function() { return _.size(P.deploymentConfigs) + _.size(P.vanillaReplicationControllers) + _.size(P.deployments) + _.size(P.vanillaReplicaSets) + _.size(P.statefulSets) + _.size(P.monopods) + _.size(P.state.serviceInstances); -}, G = function() { -return _.size(P.filteredDeploymentConfigs) + _.size(P.filteredReplicationControllers) + _.size(P.filteredDeployments) + _.size(P.filteredReplicaSets) + _.size(P.filteredStatefulSets) + _.size(P.filteredMonopods) + _.size(P.filteredServiceInstances); }, W = function() { -P.size = K(), P.filteredSize = G(); +return _.size(P.filteredDeploymentConfigs) + _.size(P.filteredReplicationControllers) + _.size(P.filteredDeployments) + _.size(P.filteredReplicaSets) + _.size(P.filteredStatefulSets) + _.size(P.filteredMonopods) + _.size(P.filteredServiceInstances); +}, G = function() { +P.size = K(), P.filteredSize = W(); var e = 0 === P.size, t = P.deploymentConfigs && P.replicationControllers && P.deployments && P.replicaSets && P.statefulSets && P.pods && P.state.serviceInstances; V.expandAll = t && 1 === P.size, P.showGetStarted = t && e, P.showLoading = !t && e, P.everythingFiltered = !e && !P.filteredSize, P.hidePipelineOtherResources = "pipeline" === P.viewBy && (P.filterActive || _.isEmpty(P.pipelineBuildConfigs)); }, Q = function(e) { @@ -119,7 +119,7 @@ case "name": return !_.isEmpty(V.filterKeywords); } }, ie = function() { -P.filteredDeploymentConfigs = re(P.deploymentConfigs), P.filteredReplicationControllers = re(P.vanillaReplicationControllers), P.filteredDeployments = re(P.deployments), P.filteredReplicaSets = re(P.vanillaReplicaSets), P.filteredStatefulSets = re(P.statefulSets), P.filteredMonopods = re(P.monopods), P.filteredPipelineBuildConfigs = re(P.pipelineBuildConfigs), P.filteredServiceInstances = re(V.orderedServiceInstances), P.filterActive = oe(), Z(), W(); +P.filteredDeploymentConfigs = re(P.deploymentConfigs), P.filteredReplicationControllers = re(P.vanillaReplicationControllers), P.filteredDeployments = re(P.deployments), P.filteredReplicaSets = re(P.vanillaReplicaSets), P.filteredStatefulSets = re(P.statefulSets), P.filteredMonopods = re(P.monopods), P.filteredPipelineBuildConfigs = re(P.pipelineBuildConfigs), P.filteredServiceInstances = re(V.orderedServiceInstances), P.filterActive = oe(), Z(), G(); }, se = n.project + "/overview/view-by"; P.viewBy = localStorage.getItem(se) || "app", e.$watch(function() { return P.viewBy; @@ -205,14 +205,14 @@ _.isEmpty(e) || (f.addLabelSuggestionsFromResources(e, x), "pipeline" !== P.view }, ke = function(e) { _.isEmpty(e) || (f.addLabelSuggestionsFromResources(e, F), "pipeline" === P.viewBy && f.setLabelSuggestions(F)); }, je = function(e) { -return "Succeeded" !== e.status.phase && "Failed" !== e.status.phase && (!U(e, "openshift.io/deployer-pod-for.name") && (!I(e, "openshift.io/build.name") && "slave" !== U(e, "jenkins"))); +return "Succeeded" !== e.status.phase && "Failed" !== e.status.phase && (!U(e, "openshift.io/deployer-pod-for.name") && (!T(e, "openshift.io/build.name") && "slave" !== U(e, "jenkins"))); }, Pe = function() { V.podsByOwnerUID = C.groupByOwnerUID(P.pods), P.monopods = _.filter(V.podsByOwnerUID[""], je); }, Re = function(e) { -return !!_.get(e, "status.replicas") || (!I(e, "deploymentConfig") || D(e)); +return !!_.get(e, "status.replicas") || (!T(e, "deploymentConfig") || D(e)); }, Ee = function(e) { -return I(e, "deploymentConfig"); -}, Te = function() { +return T(e, "deploymentConfig"); +}, Ie = function() { if (P.deploymentConfigs && P.replicationControllers) { var e = []; P.replicationControllersByDeploymentConfig = {}, P.currentByDeploymentConfig = {}, M = {}; @@ -223,7 +223,7 @@ var r = Ee(a) || ""; var o = M[r]; o && !L(a, o) || (M[r] = a); var i; -"Complete" === I(a, "deploymentStatus") && ((i = t[r]) && !L(a, i) || (t[r] = a)), Re(a) && _.set(n, [ r, a.metadata.name ], a); +"Complete" === T(a, "deploymentStatus") && ((i = t[r]) && !L(a, i) || (t[r] = a)), Re(a) && _.set(n, [ r, a.metadata.name ], a); }), _.each(t, function(e, t) { _.set(n, [ t, e.metadata.name ], e); }), _.each(n, function(e, t) { @@ -231,7 +231,7 @@ var n = u.sortByDeploymentVersion(e, !0); P.replicationControllersByDeploymentConfig[t] = n, P.currentByDeploymentConfig[t] = _.head(n); }), P.vanillaReplicationControllers = _.sortBy(e, "metadata.name"), ve(); } -}, Ie = function(e, t) { +}, Te = function(e, t) { if (_.get(e, "status.replicas")) return !0; var n = u.getRevision(e); return !n || !!t && u.getRevision(t) === n; @@ -239,7 +239,7 @@ return !n || !!t && u.getRevision(t) === n; P.replicaSets && E && (P.replicaSetsByDeploymentUID = b.groupByControllerUID(P.replicaSets), P.currentByDeploymentUID = {}, _.each(P.replicaSetsByDeploymentUID, function(e, t) { if (t) { var n = E[t], a = _.filter(e, function(e) { -return Ie(e, n); +return Te(e, n); }), r = u.sortByRevision(a); P.replicaSetsByDeploymentUID[t] = r, P.currentByDeploymentUID[t] = _.head(r); } @@ -315,7 +315,7 @@ _.isEmpty(o) || (t = t.concat(o)); qe(), ze(); }, Ke = function() { _.each(P.deploymentConfigs, Me); -}, Ge = function() { +}, We = function() { if (V.builds && P.buildConfigs) { P.recentPipelinesByBuildConfig = {}, V.recentBuildsByBuildConfig = {}, V.recentPipelinesByDeploymentConfig = {}; var e = {}; @@ -330,7 +330,7 @@ return i.sortBuilds(e, !0); return i.sortBuilds(e, !0); }), Ke(); } -}, We = function() { +}, Ge = function() { k.setGenericQuotaWarning(V.quotas, V.clusterQuotas, n.project, V.alerts); }; P.clearFilter = function() { @@ -381,9 +381,9 @@ P.pods && p.fetchReferencedImageStreamImages(P.pods, V.imagesByDockerReference, Ye.push(l.watch("pods", a, function(e) { P.pods = e.by("metadata.name"), Pe(), r(), _e(), $e(P.monopods), pe(P.monopods), we(P.monopods), ie(), h.log("pods (subscribe)", P.pods); })), Ye.push(l.watch("replicationcontrollers", a, function(e) { -P.replicationControllers = e.by("metadata.name"), Te(), $e(P.vanillaReplicationControllers), $e(P.monopods), pe(P.vanillaReplicationControllers), we(P.vanillaReplicationControllers), Qe(), ie(), h.log("replicationcontrollers (subscribe)", P.replicationControllers); +P.replicationControllers = e.by("metadata.name"), Ie(), $e(P.vanillaReplicationControllers), $e(P.monopods), pe(P.vanillaReplicationControllers), we(P.vanillaReplicationControllers), Qe(), ie(), h.log("replicationcontrollers (subscribe)", P.replicationControllers); })), Ye.push(l.watch("deploymentconfigs", a, function(e) { -P.deploymentConfigs = e.by("metadata.name"), Te(), $e(P.deploymentConfigs), $e(P.vanillaReplicationControllers), we(P.deploymentConfigs), Ce(), He(), Ke(), Qe(), ie(), h.log("deploymentconfigs (subscribe)", P.deploymentConfigs); +P.deploymentConfigs = e.by("metadata.name"), Ie(), $e(P.deploymentConfigs), $e(P.vanillaReplicationControllers), we(P.deploymentConfigs), Ce(), He(), Ke(), Qe(), ie(), h.log("deploymentconfigs (subscribe)", P.deploymentConfigs); })), Ye.push(l.watch({ group: "extensions", resource: "replicasets" @@ -395,7 +395,7 @@ resource: "deployments" }, a, function(e) { E = e.by("metadata.uid"), P.deployments = _.sortBy(E, "metadata.name"), Ne(), $e(P.deployments), $e(P.vanillaReplicaSets), we(P.deployments), Qe(), ie(), h.log("deployments (subscribe)", P.deploymentsByUID); })), Ye.push(l.watch("builds", a, function(e) { -V.builds = e.by("metadata.name"), Ge(), h.log("builds (subscribe)", V.builds); +V.builds = e.by("metadata.name"), We(), h.log("builds (subscribe)", V.builds); })), Ye.push(l.watch({ group: "apps", resource: "statefulsets" @@ -415,7 +415,7 @@ P.routes = e.by("metadata.name"), Be(), h.log("routes (subscribe)", P.routes); poll: R, pollInterval: 6e4 })), Ye.push(l.watch("buildConfigs", a, function(e) { -P.buildConfigs = e.by("metadata.name"), xe(), He(), Ge(), ie(), h.log("buildconfigs (subscribe)", P.buildConfigs); +P.buildConfigs = e.by("metadata.name"), xe(), He(), We(), ie(), h.log("buildconfigs (subscribe)", P.buildConfigs); }, { poll: R, pollInterval: 6e4 @@ -429,17 +429,17 @@ P.horizontalPodAutoscalers = e.by("metadata.name"), Le(), h.log("autoscalers (su poll: R, pollInterval: 6e4 })), Ye.push(l.watch("imagestreams", a, function(e) { -T = e.by("metadata.name"), p.buildDockerRefMapForImageStreams(T, V.imageStreamImageRefByDockerReference), r(), h.log("imagestreams (subscribe)", T); +I = e.by("metadata.name"), p.buildDockerRefMapForImageStreams(I, V.imageStreamImageRefByDockerReference), r(), h.log("imagestreams (subscribe)", I); }, { poll: R, pollInterval: 6e4 })), Ye.push(l.watch("resourcequotas", a, function(e) { -V.quotas = e.by("metadata.name"), We(); +V.quotas = e.by("metadata.name"), Ge(); }, { poll: !0, pollInterval: 6e4 })), Ye.push(l.watch("appliedclusterresourcequotas", a, function(e) { -V.clusterQuotas = e.by("metadata.name"), We(); +V.clusterQuotas = e.by("metadata.name"), Ge(); }, { poll: !0, pollInterval: 6e4 @@ -498,7 +498,7 @@ function ResourceServiceBindings(e, t, n, a) { var r = this, o = e("enableTechPreviewFeature"); r.bindings = [], r.bindableServiceInstances = [], r.serviceClasses = [], r.serviceInstances = [], r.showBindings = a.SERVICE_CATALOG_ENABLED && o("pod_presets"); var i = e("isIE")() || e("isEdge")(), s = [], c = e("canI"), l = function() { -r.apiObject && r.bindings && (r.bindings = n.getBindingsForResource(r.bindings, r.apiObject)); +r.apiObject && r.bindings && ("Instance" === _.get(r.apiObject, "kind") ? r.bindings = _.filter(r.bindings, [ "spec.instanceRef.name", _.get(r.apiObject, "metadata.name") ]) : r.bindings = n.getBindingsForResource(r.bindings, r.apiObject)); }, u = function() { r.bindableServiceInstances = n.filterBindableServiceInstances(r.serviceInstances, r.serviceClasses), r.orderedServiceInstances = n.sortServiceInstances(r.serviceInstances, r.serviceClasses); }; @@ -738,6 +738,20 @@ prefixes: [ "/browse/services/" ] label: "Routes", href: "/browse/routes", prefixes: [ "/browse/routes/" ] +}, { +label: "Provisioned Services", +href: "/browse/service-instances", +prefixes: [ "/browse/service-instances/" ], +isValid: function() { +return _.get(window.OPENSHIFT_CONSTANTS, "ENABLE_TECH_PREVIEW_FEATURE.service_catalog_landing_page"); +}, +canI: { +resource: { +group: "servicecatalog.k8s.io", +resource: "instances" +}, +verb: "list" +} } ] } ] }, { @@ -1084,6 +1098,14 @@ reloadOnSearch: !1 templateUrl: "views/browse/service.html", controller: "ServiceController", reloadOnSearch: !1 +}).when("/project/:project/browse/service-instances", { +templateUrl: "views/service-instances.html", +controller: "ServiceInstancesController", +reloadOnSearch: !1 +}).when("/project/:project/browse/service-instances/:instance", { +templateUrl: "views/browse/service-instance.html", +controller: "ServiceInstanceController", +reloadOnSearch: !1 }).when("/project/:project/browse/storage", { templateUrl: "views/storage.html", controller: "StorageController", @@ -1611,6 +1633,10 @@ var m = s.indexOf(":"); c.segment("images").segmentCoded(s.substring(0, m)).segmentCoded(s.substring(m + 1)); break; +case "Instance": +c.segment("service-instances").segmentCoded(s); +break; + case "StatefulSet": c.segment("stateful-sets").segmentCoded(s); break; @@ -1668,6 +1694,7 @@ replicationcontrollers: "deployments", routes: "routes", secrets: "secrets", services: "services", +instances: "service-instances", persistentvolumeclaims: "storage", statefulsets: "stateful-sets" }; @@ -4645,15 +4672,15 @@ t && (n.logOptions.replicationControllers[e.metadata.name].version = t), n.logCa n.logOptions.builds[e.metadata.name] = {}, n.logCanRun.builds[e.metadata.name] = !_.includes([ "New", "Pending", "Error" ], e.status.phase); }, E = function() { n.filteredStatefulSets = s.filterForKeywords(_.values(n.statefulSets), S, w); -}, T = function() { +}, I = function() { b = _.filter(n.pods, function(e) { return !n.filters.hideOlderResources || "Succeeded" !== e.status.phase && "Failed" !== e.status.phase; }), n.filteredPods = s.filterForKeywords(b, S, w); -}, I = a("isIncompleteBuild"), N = a("buildConfigForBuild"), D = a("isRecentBuild"), A = function() { +}, T = a("isIncompleteBuild"), N = a("buildConfigForBuild"), D = a("isRecentBuild"), A = function() { moment().subtract(5, "m"); h = _.filter(n.builds, function(e) { if (!n.filters.hideOlderResources) return !0; -if (I(e)) return !0; +if (T(e)) return !0; var t = N(e); return t ? n.latestBuildByConfig[t].metadata.name === e.metadata.name : D(e); }), n.filteredBuilds = s.filterForKeywords(h, S, w); @@ -4709,7 +4736,7 @@ var t = _.get(n, [ "podsByOwnerUID", e.metadata.uid ], []); _.isEmpty(t) || u.toPodsForDeployment(e, t); }, m.get(e.project).then(_.spread(function(e, a) { n.project = e, n.projectContext = a, o.watch("pods", a, function(e) { -n.podsByName = e.by("metadata.name"), n.pods = C(n.podsByName, !0), n.podsByOwnerUID = d.groupByOwnerUID(n.pods), n.podsLoaded = !0, _.each(n.pods, j), T(), c.log("pods", n.pods); +n.podsByName = e.by("metadata.name"), n.pods = C(n.podsByName, !0), n.podsByOwnerUID = d.groupByOwnerUID(n.pods), n.podsLoaded = !0, _.each(n.pods, j), I(), c.log("pods", n.pods); }), o.watch({ resource: "statefulsets", group: "apps", @@ -4728,7 +4755,7 @@ n.replicaSets = C(e.by("metadata.name"), !0), n.replicaSetsLoaded = !0, O(), c.l }), n.$on("$destroy", function() { o.unwatchAll(g); }), n.$watch("filters.hideOlderResources", function() { -T(), A(), U(), O(), E(); +I(), A(), U(), O(), E(); var e = t.search(); e.hideOlderResources = n.filters.hideOlderResources ? "true" : "false", t.replace().search(e); }), n.$watch("kindSelector.selected.kind", function() { @@ -4828,12 +4855,12 @@ httpErr: e("getErrorDetails")(a) }); }, E = {}; n.tab && (E[n.tab] = !0); -var T = u.getSubjectKinds(); +var I = u.getSubjectKinds(); angular.extend(a, { selectedTab: E, projectName: f, forms: {}, -subjectKinds: T, +subjectKinds: I, newBinding: { role: "", kind: n.tab || "User", @@ -4866,7 +4893,7 @@ return e ? a + (v(e, "description") || "") : ""; } } }); -var I = function(e, t, n, r) { +var T = function(e, t, n, r) { var o = { alerts: {}, detailsMarkup: C.remove.areYouSure.html.subject({ @@ -4909,10 +4936,10 @@ e && !_.includes(a.projects, e) ? a.projects = [ e ].concat(t) : a.projects = t; }), l.get(n.project).then(_.spread(function(n, r) { g = r, j(), k(g), angular.extend(a, { project: n, -subjectKinds: T, +subjectKinds: I, canUpdateRolebindings: y("rolebindings", "update", f), confirmRemove: function(n, r, i) { -var c = null, l = I(n, r, i, a.user.metadata.name); +var c = null, l = T(n, r, i, a.user.metadata.name); _.isEqual(n, a.user.metadata.name) && u.isLastRole(a.user.metadata.name, a.roleBindings) && (c = !0), o.open({ animation: !0, templateUrl: "views/modals/confirm.html", @@ -5671,7 +5698,7 @@ e.logCanRun = !_.includes([ "New", "Pending" ], P(t)); }, E = t("isIE")() || t("isEdge")(); f.get(n.project).then(_.spread(function(u, f) { e.project = u, e.projectContext = f; -var v = {}, T = function() { +var v = {}, I = function() { if (e.hpaForRS = s.filterHPA(v, y, n.replicaSet), e.deploymentConfigName && e.isActive) { var t = s.filterHPA(v, "DeploymentConfig", e.deploymentConfigName); e.autoscalers = e.hpaForRS.concat(t); @@ -5679,12 +5706,12 @@ e.autoscalers = e.hpaForRS.concat(t); var a = s.filterHPA(v, "Deployment", e.deployment.metadata.name); e.autoscalers = e.hpaForRS.concat(a); } else e.autoscalers = e.hpaForRS; -}, I = function() { +}, T = function() { j.push(o.watch(e.resource, f, function(t) { var n, a = []; angular.forEach(t.by("metadata.name"), function(t) { (C(t, "deploymentConfig") || "") === e.deploymentConfigName && a.push(t); -}), n = i.getActiveDeployment(a), e.isActive = n && n.metadata.uid === e.replicaSet.metadata.uid, T(); +}), n = i.getActiveDeployment(a), e.isActive = n && n.metadata.uid === e.replicaSet.metadata.uid, I(); })); }, N = function() { s.getHPAWarnings(e.replicaSet, e.autoscalers, e.limitRanges, u).then(function(t) { @@ -5742,7 +5769,7 @@ title: e.deployment.metadata.name, link: m.resourceURL(e.deployment) }, humanizedKind: "Deployments" -}), $(), T(); +}), $(), I(); })), j.push(o.watch({ group: "extensions", resource: "replicasets" @@ -5775,7 +5802,7 @@ object: t type: "warning", message: "This " + S + " has been deleted." }), e.replicaSet = t, R(t), N(), U(), e.deployment && $(); -})), e.deploymentConfigName && I(), j.push(o.watch("pods", f, function(t) { +})), e.deploymentConfigName && T(), j.push(o.watch("pods", f, function(t) { var n = t.by("metadata.name"); e.podsForDeployment = g.filterForOwner(n, e.replicaSet); })); @@ -5805,7 +5832,7 @@ group: "autoscaling", resource: "horizontalpodautoscalers", version: "v1" }, f, function(e) { -v = e.by("metadata.name"), T(), N(); +v = e.by("metadata.name"), I(), N(); }, { poll: E, pollInterval: 6e4 @@ -6021,6 +6048,89 @@ e.routesForService = {}, angular.forEach(n.by("metadata.name"), function(n) { n.unwatchAll(i); }); })); +} ]), angular.module("openshiftConsole").controller("ServiceInstancesController", [ "$scope", "$filter", "$routeParams", "APIService", "BindingService", "Constants", "DataService", "LabelFilter", "Logger", "ProjectsService", function(e, t, n, a, r, o, i, s, c, l) { +e.alerts = {}, e.applicationsByBinding = {}, e.bindings = {}, e.bindableServiceInstances = {}, e.bindingsByInstanceRef = {}, e.emptyMessage = "Loading...", e.labelSuggestions = {}, e.projectName = n.project, e.serviceClasses = {}, e.serviceInstances = {}, e.unfilteredServiceInstances = {}; +var u = [], d = function() { +e.serviceInstances = s.getLabelSelector().select(e.unfilteredServiceInstances); +}, m = function() { +e.bindableServiceInstances = r.filterBindableServiceInstances(e.unfilteredServiceInstances, e.serviceClasses), e.unfilteredServiceInstances = r.sortServiceInstances(e.unfilteredServiceInstances, e.serviceClasses); +}, p = function() {}; +l.get(n.project).then(_.spread(function(t, n) { +function a() { +s.getLabelSelector().isEmpty() || !_.isEmpty(e.serviceInstances) || _.isEmpty(e.unfilteredServiceInstances) ? delete e.alerts["all-instances-filtered"] : e.alerts["all-instances-filtered"] = { +type: "warning", +details: "The active filters are hiding all provisioned services." +}; +} +e.project = t, e.projectContext = n, u.push(i.watch({ +group: "servicecatalog.k8s.io", +resource: "bindings" +}, n, function(t) { +e.bindings = t.by("metadata.name"), e.bindingsByInstanceRef = _.groupBy(e.bindings, "spec.instanceRef.name"), p(); +})), u.push(i.watch({ +group: "servicecatalog.k8s.io", +resource: "instances" +}, n, function(t) { +e.emptyMessage = "No provisioned services to show", e.unfilteredServiceInstances = t.by("metadata.name"), m(), d(), a(), s.addLabelSuggestionsFromResources(e.unfilteredServiceInstances, e.labelSuggestions), s.setLabelSuggestions(e.labelSuggestions), c.log("provisioned services (subscribe)", e.unfilteredServiceInstances); +})), i.list({ +group: "servicecatalog.k8s.io", +resource: "serviceclasses" +}, n, function(t) { +e.serviceClasses = t.by("metadata.name"), m(), d(); +}), s.onActiveFiltersChanged(function(t) { +e.$apply(function() { +e.serviceInstances = t.select(e.unfilteredServiceInstances), a(); +}); +}), e.$on("$destroy", function() { +i.unwatchAll(u); +}); +})); +} ]), angular.module("openshiftConsole").controller("ServiceInstanceController", [ "$scope", "$filter", "$routeParams", "DataService", "ProjectsService", function(e, t, n, a, r) { +e.alerts = {}, e.projectName = n.project, e.serviceInstance = null, e.serviceClass = null, e.serviceClasses = {}, e.breadcrumbs = [ { +title: "Provisioned Services", +link: "project/" + n.project + "/browse/service-instances" +}, { +title: n.instance +} ]; +var o = [], i = function() { +if (e.serviceInstance && e.serviceClasses) { +var t = _.get(e.serviceInstance.spec, "serviceClassName"); +e.serviceClass = _.get(e.serviceClasses, [ t ]), e.plan = _.find(_.get(e.serviceClass, "plans"), { +name: "default" +}); +} +}, s = function(t, n) { +e.loaded = !0, e.serviceInstance = t, "DELETED" === n && (e.alerts.deleted = { +type: "warning", +message: "This provisioned service has been deleted." +}), i(); +}; +r.get(n.project).then(_.spread(function(r, c) { +e.project = r, e.projectContext = c, a.get({ +group: "servicecatalog.k8s.io", +resource: "instances" +}, n.instance, c, { +errorNotification: !1 +}).then(function(e) { +s(e), o.push(a.watchObject({ +group: "servicecatalog.k8s.io", +resource: "instances" +}, n.instance, c, s)); +}, function(n) { +e.loaded = !0, e.alerts.load = { +type: "error", +message: "The service details could not be loaded.", +details: t("getErrorDetails")(n) +}; +}), a.list({ +group: "servicecatalog.k8s.io", +resource: "serviceclasses" +}, c, function(t) { +e.serviceClasses = t.by("metadata.name"), i(); +}), e.$on("$destroy", function() { +a.unwatchAll(o); +}); +})); } ]), angular.module("openshiftConsole").controller("SecretsController", [ "$routeParams", "$scope", "DataService", "ProjectsService", function(e, t, n, a) { t.projectName = e.project, t.secretsByType = {}, t.alerts = t.alerts || {}, a.get(e.project).then(_.spread(function(e, a) { t.project = e, t.context = a, n.list("secrets", a).then(function(e) { @@ -7507,7 +7617,7 @@ title: R var E = { name: "app", value: "" -}, T = t("orderByDisplayName"), I = t("getErrorDetails"), N = {}, D = function() { +}, I = t("orderByDisplayName"), T = t("getErrorDetails"), N = {}, D = function() { f.hideNotification("create-builder-list-config-maps-error"), f.hideNotification("create-builder-list-secrets-error"), _.each(N, function(e) { !e.id || "error" !== e.type && "warning" !== e.type || f.hideNotification(e.id); }); @@ -7572,18 +7682,18 @@ var a = [], o = []; e.valueFromObjects = [], c.list("configmaps", i, null, { errorNotification: !1 }).then(function(t) { -a = T(t.by("metadata.name")), e.valueFromObjects = a.concat(o); +a = I(t.by("metadata.name")), e.valueFromObjects = a.concat(o); }, function(e) { 403 !== e.code && f.addNotification({ id: "create-builder-list-config-maps-error", type: "error", message: "Could not load config maps.", -details: I(e) +details: T(e) }); }), c.list("secrets", i, null, { errorNotification: !1 }).then(function(t) { -o = T(t.by("metadata.name")), e.valueFromObjects = o.concat(a); +o = I(t.by("metadata.name")), e.valueFromObjects = o.concat(a); var n = b.groupSecretsByType(t), r = _.mapValues(n, function(e) { return _.map(e, "metadata.name"); }); @@ -7595,7 +7705,7 @@ e.unshift(""); id: "create-builder-list-secrets-error", type: "error", message: "Could not load secrets.", -details: I(e) +details: T(e) }); }), c.get("imagestreams", t.imageName, { namespace: t.namespace || r.project @@ -9060,7 +9170,7 @@ t > 0 && a.push(k()), e > 0 && a.push(w()), n.all(a).then(b); } function b() { var e, n; -I(), "Template" === p.resourceKind && p.templateOptions.process && !p.errorOccurred ? p.isDialog ? p.$emit("fileImportedFromYAMLOrJSON", { +T(), "Template" === p.resourceKind && p.templateOptions.process && !p.errorOccurred ? p.isDialog ? p.$emit("fileImportedFromYAMLOrJSON", { project: p.input.selectedProject, template: p.resource }) : (n = p.templateOptions.add || p.updateResources.length > 0 ? p.input.selectedProject.metadata.name : "", e = s.createFromTemplateURL(p.resource, p.input.selectedProject.metadata.name, { @@ -9226,18 +9336,18 @@ cancelButtonText: "Cancel" } } }).result.then(y); -}, T = {}, I = function() { -c.hideNotification("from-file-error"), _.each(T, function(e) { +}, I = {}, T = function() { +c.hideNotification("from-file-error"), _.each(I, function(e) { !e.id || "error" !== e.type && "warning" !== e.type || c.hideNotification(e.id); }); }, N = function(e) { -I(), T = u.getSecurityAlerts(p.createResources, p.input.selectedProject.metadata.name); +T(), I = u.getSecurityAlerts(p.createResources, p.input.selectedProject.metadata.name); var t = e.quotaAlerts || []; -T = T.concat(t), _.filter(T, { +I = I.concat(t), _.filter(I, { type: "error" -}).length ? (_.each(T, function(e) { +}).length ? (_.each(I, function(e) { e.id = _.uniqueId("from-file-alert-"), c.addNotification(e); -}), p.disableInputs = !1) : T.length ? (E(T), p.disableInputs = !1) : y(); +}), p.disableInputs = !1) : I.length ? (E(I), p.disableInputs = !1) : y(); }, D = function() { if (_.has(p.input.selectedProject, "metadata.uid")) return n.when(p.input.selectedProject); var t = p.input.selectedProject.metadata.name, a = p.input.selectedProject.metadata.annotations["new-display-name"], r = e("description")(p.input.selectedProject); @@ -9269,10 +9379,10 @@ details: R(e) }); } }, p.cancel = function() { -I(), s.toProjectOverview(p.input.selectedProject.metadata.name); +T(), s.toProjectOverview(p.input.selectedProject.metadata.name); }; var $ = e("displayName"); -p.$on("importFileFromYAMLOrJSON", p.create), p.$on("$destroy", I); +p.$on("importFileFromYAMLOrJSON", p.create), p.$on("$destroy", T); } ] }; } ]), angular.module("openshiftConsole").directive("oscFileInput", [ "Logger", function(e) { @@ -10697,7 +10807,7 @@ if (!m.pod) return null; var t = m.options.selectedContainer; switch (e) { case "memory/usage": -var n = I(t); +var n = T(t); if (n) return s.bytesToMiB(d(n)); break; @@ -10732,10 +10842,10 @@ _.each(e.datasets, function(e) { t[e.id] = e.data; }); var n, r = c.getSparklineData(t), o = e.chartPrefix + "sparkline"; -T[o] ? T[o].load(r) : ((n = L(e)).data = r, e.chartDataColors && (n.color = { +I[o] ? I[o].load(r) : ((n = L(e)).data = r, e.chartDataColors && (n.color = { pattern: e.chartDataColors }), a(function() { -$ || (T[o] = c3.generate(n)); +$ || (I[o] = c3.generate(n)); })); } } @@ -10823,7 +10933,7 @@ m.loaded = !0; } } m.includedMetrics = m.includedMetrics || [ "cpu", "memory", "network" ]; -var R, E = {}, T = {}, I = n("resources.limits.memory"), N = n("resources.limits.cpu"), D = 30, $ = !1; +var R, E = {}, I = {}, T = n("resources.limits.memory"), N = n("resources.limits.cpu"), D = 30, $ = !1; m.uniqueID = c.uniqueID(), m.metrics = [], _.includes(m.includedMetrics, "memory") && m.metrics.push({ label: "Memory", units: "MiB", @@ -10920,14 +11030,14 @@ delete e.data; }, !0), R = t(P, c.getDefaultUpdateInterval(), !1); }); var O = o.$on("metrics.charts.resize", function() { -c.redraw(E), c.redraw(T); +c.redraw(E), c.redraw(I); }); m.$on("$destroy", function() { R && (t.cancel(R), R = null), O && (O(), O = null), angular.forEach(E, function(e) { e.destroy(); -}), E = null, angular.forEach(T, function(e) { +}), E = null, angular.forEach(I, function(e) { e.destroy(); -}), T = null, $ = !0; +}), I = null, $ = !0; }); } }; @@ -10989,7 +11099,7 @@ return e[0]; function u(e) { k || (N = 0, t.showAverage = _.size(t.pods) > 5 || w, _.each(t.metrics, function(n) { var a, r = o(e, n), i = n.descriptor; -w && n.compactCombineWith && (i = n.compactCombineWith, n.lastValue && (I[i].lastValue = (I[i].lastValue || 0) + n.lastValue)), C[i] ? (C[i].load(r), t.showAverage ? C[i].legend.hide() : C[i].legend.show()) : ((a = D(n)).data = r, C[i] = c3.generate(a)); +w && n.compactCombineWith && (i = n.compactCombineWith, n.lastValue && (T[i].lastValue = (T[i].lastValue || 0) + n.lastValue)), C[i] ? (C[i].load(r), t.showAverage ? C[i].legend.hide() : C[i].legend.show()) : ((a = D(n)).data = r, C[i] = c3.generate(a)); })); } function d() { @@ -11053,7 +11163,7 @@ t.loaded = !0; } var b, C = {}, S = 30, w = "compact" === t.profile, k = !1; t.uniqueID = s.uniqueID(); -var j, P, R = {}, E = w, T = function(e) { +var j, P, R = {}, E = w, I = function(e) { return e >= 1024; }; t.metrics = [ { @@ -11061,10 +11171,10 @@ label: "Memory", units: "MiB", convert: i.bytesToMiB, formatUsage: function(e) { -return T(e) && (e /= 1024), s.formatUsage(e); +return I(e) && (e /= 1024), s.formatUsage(e); }, usageUnits: function(e) { -return T(e) ? "GiB" : "MiB"; +return I(e) ? "GiB" : "MiB"; }, descriptor: "memory/usage", type: "pod_container", @@ -11109,7 +11219,7 @@ compactDatasetLabel: "Received", compactType: "spline", chartID: "network-rx-" + t.uniqueID } ]; -var I = _.keyBy(t.metrics, "descriptor"); +var T = _.keyBy(t.metrics, "descriptor"); t.loaded = !1, t.noData = !0, t.showComputeUnitsHelp = function() { l.showComputeUnitsHelp(); }; @@ -11191,10 +11301,10 @@ offset: { top: t.followAffixTop || 0 } })); -}, T = function() { +}, I = function() { return $("#" + t.logViewerID + " .log-view-output"); -}, I = function(e) { -var n = T(), a = n.offset().top; +}, T = function(e) { +var n = I(), a = n.offset().top; if (!(a < 0)) { var r = $(".ellipsis-pulser").outerHeight(!0), o = t.fixedHeight ? t.fixedHeight : Math.floor($(window).height() - a - r); t.chromeless || t.fixedHeight || (o -= 40), e ? n.animate({ @@ -11209,11 +11319,11 @@ t.sized = !0; }); }, n = 0; S = setInterval(function() { -n > 10 ? e() : (n++, T().is(":visible") && (I(), e())); +n > 10 ? e() : (n++, I().is(":visible") && (T(), e())); }, 100); } }, D = _.debounce(function() { -I(!0), w(), R(), k(), E(), P(); +T(!0), w(), R(), k(), E(), P(); }, 100); p.on("resize", D); var A, B = function() { @@ -13100,6 +13210,7 @@ controllerAs: "$ctrl", bindings: { namespace: "<", binding: "<", +refApiObject: "\n" + + "\n" + + "\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "\n" + + "\n" + + "
Loading...
\n" + + "
\n" + + "

\n" + + "
\n" + + "\n" + + "Actions\n" + + "
    \n" + + "
  • \n" + + "Edit YAML\n" + + "
  • \n" + + "
  • \n" + + "\n" + + "\n" + + "
  • \n" + + "
\n" + + "
\n" + + "{{serviceInstance | serviceInstanceDisplayName:serviceClasses}}\n" + + "created \n" + + "

\n" + + "\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "\n" + + "\n" + + "Details\n" + + "
\n" + + "
\n" + + "
\n" + + "

Plan

\n" + + "

\n" + + "{{plan.description}}\n" + + "

\n" + + "
\n" + + "
Description:
\n" + + "
\n" + + "

\n" + + "

\n" + + "
\n" + + "
Status:
\n" + + "
\n" + + "\n" + + "{{serviceInstance | serviceInstanceStatus | sentenceCase}}\n" + + "
\n" + + "
Status Reason:
\n" + + "
\n" + + "{{serviceInstance | serviceInstanceMessage}}\n" + + "
\n" + + "\n" + + "
\n" + + "
\n" + + "
\n" + + "\n" + + "\n" + + "
\n" + + "
\n" + + "\n" + + "
\n" + + "
\n" + + "\n" + + "Events\n" + + "\n" + + "\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
" + ); + + $templateCache.put('views/browse/service.html', "\n" + "\n" + @@ -8845,8 +8936,8 @@ angular.module('openshiftConsoleTemplates', []).run(['$templateCache', function( $templateCache.put('views/directives/resource-service-bindings.html', "
\n" + - "

Service Bindings

\n" + - "\n" + + "

Bindings

\n" + + "\n" + "\n" + "
\n" + "\n" + @@ -12314,8 +12405,13 @@ angular.module('openshiftConsoleTemplates', []).run(['$templateCache', function( "
\n" + "

\n" + "\n" + + "\n" + "{{$ctrl.serviceClass.externalMetadata.displayName || $ctrl.serviceClass.metadata.name}}\n" + "\n" + + "\n" + + "{{$ctrl.binding.spec.secretName}}\n" + + "\n" + + "\n" + "\n" + "{{$ctrl.binding.spec.instanceRef.name}}\n" + "\n" + @@ -12390,7 +12486,8 @@ angular.module('openshiftConsoleTemplates', []).run(['$templateCache', function( "
\n" + "
\n" + "

\n" + - "\n" + + "\n" + + "\n" + "
\n" + "

\n" + "
\n" + @@ -13203,6 +13300,91 @@ angular.module('openshiftConsoleTemplates', []).run(['$templateCache', function( ); + $templateCache.put('views/service-instances.html', + "\n" + + "\n" + + "\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "

\n" + + "Provisioned Services\n" + + "\n" + + "

\n" + + "
\n" + + "
\n" + + "
\n" + + "\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "\n" + + "
\n" + + "
\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + " 0\">\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
NameStatusCreatedBindings
{{emptyMessage}}
{{serviceInstance | serviceInstanceDisplayName:serviceClasses}}\n" + + "
\n" + + "\n" + + "{{serviceInstance | serviceInstanceStatus | sentenceCase}}\n" + + "
\n" + + "
\n" + + " ago\n" + + "\n" + + "
\n" + + "

\n" + + "\n" + + "{{application.metadata.name}}\n" + + "\n" + + "\n" + + "{{firstBinding.spec.secretName}}\n" + + "\n" + + "\n" + + "\n" + + "

\n" + + "
\n" + + "
\n" + + "No bindings\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
" + ); + + $templateCache.put('views/services.html', "\n" + "\n" +