diff --git a/app/scripts/controllers/overview.js b/app/scripts/controllers/overview.js index 04ba315c5a..27dc45a8c1 100644 --- a/app/scripts/controllers/overview.js +++ b/app/scripts/controllers/overview.js @@ -7,6 +7,7 @@ angular.module('openshiftConsole').controller('OverviewController', [ 'AlertMessageService', 'APIService', 'AppsService', + 'BindingService', 'BuildsService', 'CatalogService', 'Constants', @@ -23,9 +24,9 @@ angular.module('openshiftConsole').controller('OverviewController', [ 'OwnerReferencesService', 'PodsService', 'ProjectsService', - 'BindingService', 'ResourceAlertsService', 'RoutesService', + 'ServiceInstancesService', OverviewController ]); @@ -35,6 +36,7 @@ function OverviewController($scope, AlertMessageService, APIService, AppsService, + BindingService, BuildsService, CatalogService, Constants, @@ -51,9 +53,9 @@ function OverviewController($scope, OwnerReferencesService, PodsService, ProjectsService, - BindingService, ResourceAlertsService, - RoutesService) { + RoutesService, + ServiceInstancesService) { var overview = this; var limitWatches = $filter('isIE')() || $filter('isEdge')(); var DEFAULT_POLL_INTERVAL = 60 * 1000; // milliseconds @@ -63,6 +65,7 @@ function OverviewController($scope, // Filters used by this controller. var annotation = $filter('annotation'); + var canI = $filter('canI'); var getBuildConfigName = $filter('buildConfigForBuild'); var deploymentIsInProgress = $filter('deploymentIsInProgress'); var imageObjectRef = $filter('imageObjectRef'); @@ -71,6 +74,12 @@ function OverviewController($scope, var label = $filter('label'); var getPodTemplate = $filter('podTemplate'); + // API versions + var serviceBindingsVersion = APIService.getPreferredVersion('servicebindings'); + var serviceClassesVersion = APIService.getPreferredVersion('clusterserviceclasses'); + var serviceInstancesVersion = APIService.getPreferredVersion('serviceinstances'); + var servicePlansVersion = APIService.getPreferredVersion('clusterserviceplans'); + var deploymentsByUID; var imageStreams; var labelSuggestions = {}; @@ -102,6 +111,8 @@ function OverviewController($scope, routesByService: {}, servicesByObjectUID: {}, serviceInstances: {}, + serviceClasses: {}, + servicePlans: {}, bindingsByInstanceRef: {}, bindingsByApplicationUID: {}, applicationsByBinding: {}, @@ -314,7 +325,7 @@ function OverviewController($scope, }; // Updated on viewBy changes to include the app label when appropriate. - var filterFields = ['metadata.name', 'spec.serviceClassName']; + var filterFields = ['metadata.name', 'spec.externalServiceClassName']; var filterByName = function(items) { return KeywordService.filterForKeywords(items, filterFields, state.filterKeywords); }; @@ -1150,8 +1161,12 @@ function OverviewController($scope, }; var sortServiceInstances = function() { - state.bindableServiceInstances = BindingService.filterBindableServiceInstances(state.serviceInstances, state.serviceClasses); - state.orderedServiceInstances = BindingService.sortServiceInstances(state.serviceInstances, state.serviceClasses); + state.bindableServiceInstances = + BindingService.filterBindableServiceInstances(state.serviceInstances, + state.serviceClasses, + state.servicePlans); + state.orderedServiceInstances = + BindingService.sortServiceInstances(state.serviceInstances, state.serviceClasses); }; var watches = []; @@ -1312,17 +1327,51 @@ function OverviewController($scope, setQuotaNotifications(); }, {poll: true, pollInterval: DEFAULT_POLL_INTERVAL})); - var canI = $filter('canI'); + var fetchServiceClass, fetchServicePlan; + + // Avoid requesting the same service class or service plan twice. + var serviceClassPromises = {}; + var servicePlanPromises = {}; + // The canI check on watch should be temporary until we have a different solution for handling secret parameters - if (CatalogService.SERVICE_CATALOG_ENABLED && canI({resource: 'serviceinstances', group: 'servicecatalog.k8s.io'}, 'watch')) { - watches.push(DataService.watch({ - group: 'servicecatalog.k8s.io', - resource: 'serviceinstances' - }, context, function(serviceInstances) { + if (CatalogService.SERVICE_CATALOG_ENABLED && canI(serviceInstancesVersion, 'watch')) { + + // Get the service class for this instance. + fetchServiceClass = function(instance) { + var serviceClassName = ServiceInstancesService.getServiceClassNameForInstance(instance); + + // Check if we already have the service class or if a request is already in flight. + if (!_.has(state, ['serviceClasses', serviceClassName]) && !serviceClassPromises[serviceClassName]) { + serviceClassPromises[serviceClassName] = DataService.get(serviceClassesVersion, serviceClassName, {}).then(function(serviceClass) { + state.serviceClasses[serviceClassName] = serviceClass; + }).finally(function() { + delete servicePlanPromises[serviceClassName]; + }); + } + }; + + // Get the service plan for this instance. + fetchServicePlan = function(instance) { + var servicePlanName = ServiceInstancesService.getServicePlanNameForInstance(instance); + + // Check if we already have the service plan or if a request is already in flight. + if (!_.has(state, ['servicePlans', servicePlanName]) && !servicePlanPromises[servicePlanName]) { + servicePlanPromises[servicePlanName] = DataService.get(servicePlansVersion, servicePlanName, {}).then(function(servicePlan) { + state.servicePlans[servicePlanName] = servicePlan; + }).finally(function() { + delete servicePlanPromises[servicePlanName]; + }); + } + }; + + watches.push(DataService.watch(serviceInstancesVersion, context, function(serviceInstances) { state.serviceInstances = serviceInstances.by('metadata.name'); _.each(state.serviceInstances, function(instance) { var notifications = ResourceAlertsService.getServiceInstanceAlerts(instance); setNotifications(instance, notifications); + + fetchServiceClass(instance); + fetchServicePlan(instance); }); sortServiceInstances(); updateLabelSuggestions(state.serviceInstances); @@ -1330,11 +1379,8 @@ function OverviewController($scope, }, {poll: limitWatches, pollInterval: DEFAULT_POLL_INTERVAL})); } - if (CatalogService.SERVICE_CATALOG_ENABLED && canI({resource: 'serviceinstancecredentials', group: 'servicecatalog.k8s.io'}, 'watch')) { - watches.push(DataService.watch({ - group: 'servicecatalog.k8s.io', - resource: 'serviceinstancecredentials' - }, context, function(bindings) { + if (CatalogService.SERVICE_CATALOG_ENABLED && canI(serviceBindingsVersion, 'watch')) { + watches.push(DataService.watch(serviceBindingsVersion, context, function(bindings) { state.bindings = bindings.by('metadata.name'); overview.bindingsByInstanceRef = _.groupBy(state.bindings, 'spec.instanceRef.name'); groupBindings(); @@ -1347,20 +1393,6 @@ function OverviewController($scope, state.limitRanges = response.by("metadata.name"); }); - if (CatalogService.SERVICE_CATALOG_ENABLED && canI({resource: 'serviceinstances', group: 'servicecatalog.k8s.io'}, 'watch')) { - // TODO: update to behave like ImageStreamResolver - // - we may not even need to list these... perhaps just fetch the ones we need when needed - // If we can't watch instances don't bother getting service classes either - DataService.list({ - group: 'servicecatalog.k8s.io', - resource: 'serviceclasses' - }, {}, function(serviceClasses) { - state.serviceClasses = serviceClasses.by('metadata.name'); - sortServiceInstances(); - updateFilter(); - }); - } - var samplePipelineTemplate = Constants.SAMPLE_PIPELINE_TEMPLATE; if (samplePipelineTemplate) { DataService.get("templates", samplePipelineTemplate.name, { diff --git a/app/scripts/controllers/serviceInstance.js b/app/scripts/controllers/serviceInstance.js index 8d05681d83..1102e7d518 100644 --- a/app/scripts/controllers/serviceInstance.js +++ b/app/scripts/controllers/serviceInstance.js @@ -4,6 +4,7 @@ angular.module('openshiftConsole') .controller('ServiceInstanceController', function ($scope, $filter, $routeParams, + APIService, DataService, ProjectsService, ServiceInstancesService) { @@ -11,7 +12,6 @@ angular.module('openshiftConsole') $scope.projectName = $routeParams.project; $scope.serviceInstance = null; $scope.serviceClass = null; - $scope.serviceClasses = null; $scope.breadcrumbs = [ { @@ -26,29 +26,42 @@ angular.module('openshiftConsole') var watches = []; + var serviceInstanceDisplayName = $filter('serviceInstanceDisplayName'); + + // API Versions + var serviceInstancesVersion = APIService.getPreferredVersion('serviceinstances'); + var updateBreadcrumbs = function() { - if(!$scope.serviceInstance || !$scope.serviceClasses) { + $scope.breadcrumbs.push({ + title: $scope.displayName + }); + }; + + var updateServiceClass = function() { + if ($scope.serviceClass) { return; } - $scope.breadcrumbs.push({ - title: $filter('serviceInstanceDisplayName')($scope.serviceInstance, $scope.serviceClasses) + ServiceInstancesService.fetchServiceClassForInstance($scope.serviceInstance).then(function(serviceClass) { + $scope.serviceClass = serviceClass; + $scope.displayName = serviceInstanceDisplayName($scope.serviceInstance, serviceClass); + updateBreadcrumbs(); }); }; - var updateServiceClassMetadata = function() { - if(!$scope.serviceInstance || !$scope.serviceClasses) { + var updatePlan = function() { + if (ServiceInstancesService.isCurrentPlan($scope.serviceInstance, $scope.plan)) { return; } - var serviceClassName = _.get($scope.serviceInstance.spec, 'serviceClassName'); - $scope.serviceClass = _.get($scope.serviceClasses, [serviceClassName]); - $scope.plan = _.find(_.get($scope.serviceClass, 'plans'), {name: $scope.serviceInstance.spec.planName }); + ServiceInstancesService.fetchServicePlanForInstance($scope.serviceInstance).then(function(plan) { + $scope.plan = plan; + }); }; - var serviceResolved = function(service, action) { + var serviceResolved = function(serviceInstance, action) { $scope.loaded = true; - $scope.serviceInstance = service; + $scope.serviceInstance = serviceInstance; if (action === "DELETED") { $scope.alerts["deleted"] = { @@ -57,7 +70,8 @@ angular.module('openshiftConsole') }; } - updateServiceClassMetadata(); + updateServiceClass(); + updatePlan(); }; ProjectsService @@ -67,41 +81,21 @@ angular.module('openshiftConsole') $scope.projectContext = context; DataService - .get({ - group: 'servicecatalog.k8s.io', - resource: 'serviceinstances' - }, $routeParams.instance, context, { errorNotification: false }) - .then(function(service) { - - serviceResolved(service); - updateBreadcrumbs(); - - watches.push(DataService.watchObject({ - group: 'servicecatalog.k8s.io', - resource: 'serviceinstances' - }, $routeParams.instance, context, serviceResolved)); - + .get(serviceInstancesVersion, $routeParams.instance, context, { errorNotification: false }) + .then(function(serviceInstance) { + serviceResolved(serviceInstance); + watches.push(DataService.watchObject(serviceInstancesVersion, $routeParams.instance, context, serviceResolved)); }, function(error) { $scope.loaded = true; $scope.alerts["load"] = { type: "error", - message: "The service details could not be loaded.", + message: "The provisioned service details could not be loaded.", details: $filter('getErrorDetails')(error) }; }); - DataService.list({ - group: 'servicecatalog.k8s.io', - resource: 'serviceclasses' - }, {}, function(serviceClasses) { - $scope.serviceClasses = serviceClasses.by('metadata.name'); - updateServiceClassMetadata(); - updateBreadcrumbs(); - }); - $scope.$on('$destroy', function(){ DataService.unwatchAll(watches); }); - })); }); diff --git a/app/scripts/controllers/serviceInstances.js b/app/scripts/controllers/serviceInstances.js index ca18b5957a..479912f9c5 100644 --- a/app/scripts/controllers/serviceInstances.js +++ b/app/scripts/controllers/serviceInstances.js @@ -30,24 +30,25 @@ angular.module('openshiftConsole') $scope.unfilteredServiceInstances = BindingService.sortServiceInstances($scope.unfilteredServiceInstances, $scope.serviceClasses); }; + $scope.getServiceClass = function(serviceInstance) { + var serviceClassName = _.get(serviceInstance, 'spec.serviceClassRef.name'); + return _.get($scope, ['serviceClasses', serviceClassName]); + }; + ProjectsService .get($routeParams.project) .then(_.spread(function(project, context) { $scope.project = project; $scope.projectContext = context; - watches.push(DataService.watch({ - group: 'servicecatalog.k8s.io', - resource: 'serviceinstancecredentials' - }, context, function(bindings) { + var serviceBindingsVersion = APIService.getPreferredVersion('servicebindings'); + watches.push(DataService.watch(serviceBindingsVersion, context, function(bindings) { var bindingsByName = bindings.by('metadata.name'); $scope.bindingsByInstanceRef = _.groupBy(bindingsByName, 'spec.instanceRef.name'); })); - watches.push(DataService.watch({ - group: 'servicecatalog.k8s.io', - resource: 'serviceinstances' - }, context, function(serviceInstances) { + var serviceInstancesVersion = APIService.getPreferredVersion('serviceinstances'); + watches.push(DataService.watch(serviceInstancesVersion, context, function(serviceInstances) { $scope.emptyMessage = "No provisioned services to show"; $scope.unfilteredServiceInstances = serviceInstances.by('metadata.name'); @@ -61,10 +62,8 @@ angular.module('openshiftConsole') Logger.log("provisioned services (subscribe)", $scope.unfilteredServiceInstances); })); - DataService.list({ - group: 'servicecatalog.k8s.io', - resource: 'serviceclasses' - }, {}, function(serviceClasses) { + var serviceClassesVersion = APIService.getPreferredVersion('clusterserviceclasses'); + DataService.list(serviceClassesVersion, {}, function(serviceClasses) { $scope.serviceClasses = serviceClasses.by('metadata.name'); sortServiceInstances(); updateFilter(); diff --git a/app/scripts/directives/bindService.js b/app/scripts/directives/bindService.js index 0e265ffd27..ee067c22a8 100644 --- a/app/scripts/directives/bindService.js +++ b/app/scripts/directives/bindService.js @@ -5,9 +5,11 @@ controller: [ '$scope', '$filter', + 'APIService', 'ApplicationsService', - 'DataService', 'BindingService', + 'DataService', + 'ServiceInstancesService', BindService ], controllerAs: 'ctrl', @@ -21,9 +23,11 @@ function BindService($scope, $filter, + APIService, ApplicationsService, + BindingService, DataService, - BindingService) { + ServiceInstancesService) { var ctrl = this; var bindFormStep; var bindParametersStep; @@ -50,10 +54,15 @@ }; var sortServiceInstances = function() { - // wait till both service instances and service classes are available so that the sort is stable and items dont jump around + // wait till both service instances and service classes are available so + // that the sort is stable and items dont jump around if (ctrl.serviceClasses && ctrl.serviceInstances) { - ctrl.serviceInstances = BindingService.filterBindableServiceInstances(ctrl.serviceInstances, ctrl.serviceClasses); - ctrl.orderedServiceInstances = BindingService.sortServiceInstances(ctrl.serviceInstances, ctrl.serviceClasses); + ctrl.serviceInstances = + BindingService.filterBindableServiceInstances(ctrl.serviceInstances, + ctrl.serviceClasses, + ctrl.servicePlans); + ctrl.orderedServiceInstances = + BindingService.sortServiceInstances(ctrl.serviceInstances, ctrl.serviceClasses); if (!ctrl.serviceToBind) { preselectService(); @@ -109,10 +118,8 @@ namespace: _.get(ctrl.target, 'metadata.namespace') }; - DataService.list({ - group: 'servicecatalog.k8s.io', - resource: 'serviceinstances' - }, context).then(function(instances) { + var serviceInstancesVersion = APIService.getPreferredVersion('serviceinstances'); + DataService.list(serviceInstancesVersion, context).then(function(instances) { ctrl.serviceInstances = instances.by('metadata.name'); sortServiceInstances(); }); @@ -146,7 +153,7 @@ }; var updateInstance = function() { - if (!ctrl.serviceClasses) { + if (!ctrl.serviceClasses || !ctrl.servicePlans) { return; } @@ -155,11 +162,12 @@ return; } - ctrl.serviceClass = ctrl.serviceClasses[instance.spec.serviceClassName]; - ctrl.serviceClassName = instance.spec.serviceClassName; - ctrl.plan = BindingService.getPlanForInstance(instance, ctrl.serviceClass); - ctrl.parameterSchema = _.get(ctrl.plan, 'serviceInstanceCredentialCreateParameterSchema'); - ctrl.parameterFormDefinition = _.get(ctrl.plan, 'externalMetadata.schemas.service_binding.create.openshift_form_definition'); + var serviceClassName = ServiceInstancesService.getServiceClassNameForInstance(instance); + ctrl.serviceClass = ctrl.serviceClasses[serviceClassName]; + var servicePlanName = ServiceInstancesService.getServicePlanNameForInstance(instance); + ctrl.plan = ctrl.servicePlans[servicePlanName]; + ctrl.parameterSchema = _.get(ctrl.plan, 'spec.serviceInstanceCredentialCreateParameterSchema'); + ctrl.parameterFormDefinition = _.get(ctrl.plan, 'spec.externalMetadata.schemas.service_binding.create.openshift_form_definition'); bindParametersStep.hidden = !_.has(ctrl.parameterSchema, 'properties'); ctrl.nextTitle = bindParametersStep.hidden ? 'Bind' : 'Next >'; ctrl.hideBack = bindParametersStep.hidden; @@ -177,15 +185,21 @@ ctrl.hideBack = bindParametersStep.hidden; // We will want ServiceClasses either way for display purposes - DataService.list({ - group: 'servicecatalog.k8s.io', - resource: 'serviceclasses' - }, {}).then(function(serviceClasses) { + var serviceClassesVersion = APIService.getPreferredVersion('clusterserviceclasses'); + DataService.list(serviceClassesVersion, {}).then(function(serviceClasses) { ctrl.serviceClasses = serviceClasses.by('metadata.name'); updateInstance(); sortServiceInstances(); }); + // We'll need service plans for binding parameters. + // TODO: Only load plans for selected instance. + var servicePlansVersion = APIService.getPreferredVersion('clusterserviceplans'); + DataService.list(servicePlansVersion, {}).then(function(plans) { + ctrl.servicePlans = plans.by('metadata.name'); + updateInstance(); + }); + if (ctrl.target.kind === 'ServiceInstance') { ctrl.bindType = "secret-only"; ctrl.appToBind = null; diff --git a/app/scripts/directives/overview/serviceInstanceRow.js b/app/scripts/directives/overview/serviceInstanceRow.js index 5e65e3f5be..e9bf02aef4 100644 --- a/app/scripts/directives/overview/serviceInstanceRow.js +++ b/app/scripts/directives/overview/serviceInstanceRow.js @@ -32,6 +32,16 @@ var serviceInstanceDisplayName = $filter('serviceInstanceDisplayName'); + var getServiceClass = function() { + var serviceClassName = ServiceInstancesService.getServiceClassNameForInstance(row.apiObject); + return _.get(row, ['state','serviceClasses', serviceClassName]); + }; + + var getServicePlan = function() { + var servicePlanName = ServiceInstancesService.getServicePlanNameForInstance(row.apiObject); + return _.get(row, ['state', 'servicePlans', servicePlanName]); + }; + var updateInstanceStatus = function() { if (_.get(row.apiObject, 'metadata.deletionTimestamp')) { row.instanceStatus = 'deleted'; @@ -48,9 +58,10 @@ updateInstanceStatus(); row.notifications = ListRowUtils.getNotifications(row.apiObject, row.state); - row.displayName = serviceInstanceDisplayName(row.apiObject, row.state.serviceClasses); - row.isBindable = BindingService.isServiceBindable(row.apiObject, row.state.serviceClasses); - row.serviceClass = _.get(row, ['state', 'serviceClasses', row.apiObject.spec.serviceClassName]); + row.serviceClass = getServiceClass(); + row.servicePlan = getServicePlan(); + row.displayName = serviceInstanceDisplayName(row.apiObject, row.serviceClass); + row.isBindable = BindingService.isServiceBindable(row.apiObject, row.serviceClass, row.servicePlan); }; row.$onChanges = function(changes) { diff --git a/app/scripts/directives/resourceServiceBindings.js b/app/scripts/directives/resourceServiceBindings.js index e0eb66d228..a8f399493d 100644 --- a/app/scripts/directives/resourceServiceBindings.js +++ b/app/scripts/directives/resourceServiceBindings.js @@ -3,9 +3,10 @@ angular.module('openshiftConsole').component('resourceServiceBindings', { controller: [ '$filter', - 'DataService', + 'APIService', 'BindingService', 'CatalogService', + 'DataService', ResourceServiceBindings ], controllerAs: '$ctrl', @@ -19,9 +20,14 @@ angular.module('openshiftConsole').component('resourceServiceBindings', { }); -function ResourceServiceBindings($filter, DataService, BindingService, CatalogService) { +function ResourceServiceBindings($filter, + APIService, + BindingService, + CatalogService, + DataService) { var ctrl = this; var enableTechPreviewFeature = $filter('enableTechPreviewFeature'); + var servicePlans; ctrl.bindings = []; ctrl.bindableServiceInstances = []; @@ -34,6 +40,12 @@ function ResourceServiceBindings($filter, DataService, BindingService, CatalogSe var watches = []; var canI = $filter('canI'); + // API versions + var serviceBindingsVersion = ctrl.serviceBindingsVersion = APIService.getPreferredVersion('servicebindings'); + var serviceClassesVersion = APIService.getPreferredVersion('clusterserviceclasses'); + var serviceInstancesVersion = APIService.getPreferredVersion('serviceinstances'); + var servicePlansVersion = APIService.getPreferredVersion('clusterserviceplans'); + var updateBindings = function() { if (!ctrl.apiObject || !ctrl.bindings) { return; @@ -44,7 +56,7 @@ function ResourceServiceBindings($filter, DataService, BindingService, CatalogSe }; var sortServiceInstances = function() { - ctrl.bindableServiceInstances = BindingService.filterBindableServiceInstances(ctrl.serviceInstances, ctrl.serviceClasses); + ctrl.bindableServiceInstances = BindingService.filterBindableServiceInstances(ctrl.serviceInstances, ctrl.serviceClasses, servicePlans); ctrl.orderedServiceInstances = BindingService.sortServiceInstances(ctrl.serviceInstances, ctrl.serviceClasses); }; @@ -61,34 +73,29 @@ function ResourceServiceBindings($filter, DataService, BindingService, CatalogSe DataService.unwatchAll(watches); watches = []; - if (CatalogService.SERVICE_CATALOG_ENABLED && canI({resource: 'serviceinstancecredentials', group: 'servicecatalog.k8s.io'}, 'watch')) { - watches.push(DataService.watch({ - group: 'servicecatalog.k8s.io', - resource: 'serviceinstancecredentials' - }, ctrl.projectContext, function(bindings) { + if (CatalogService.SERVICE_CATALOG_ENABLED && canI(serviceBindingsVersion, 'watch')) { + watches.push(DataService.watch(serviceBindingsVersion, ctrl.projectContext, function(bindings) { ctrl.bindings = bindings.by('metadata.name'); updateBindings(); }, {poll: limitWatches, pollInterval: DEFAULT_POLL_INTERVAL})); } // The canI check on watch should be temporary until we have a different solution for handling secret parameters - if (CatalogService.SERVICE_CATALOG_ENABLED && canI({resource: 'serviceinstances', group: 'servicecatalog.k8s.io'}, 'watch')) { - watches.push(DataService.watch({ - group: 'servicecatalog.k8s.io', - resource: 'serviceinstances' - }, ctrl.projectContext, function(serviceInstances) { + if (CatalogService.SERVICE_CATALOG_ENABLED && canI(serviceInstancesVersion, 'watch')) { + watches.push(DataService.watch(serviceInstancesVersion, ctrl.projectContext, function(serviceInstances) { ctrl.serviceInstances = serviceInstances.by('metadata.name'); sortServiceInstances(); }, {poll: limitWatches, pollInterval: DEFAULT_POLL_INTERVAL})); // If we can't watch instances don't bother getting service classes either - DataService.list({ - group: 'servicecatalog.k8s.io', - resource: 'serviceclasses' - }, {}, function(serviceClasses) { + DataService.list(serviceClassesVersion, {}, function(serviceClasses) { ctrl.serviceClasses = serviceClasses.by('metadata.name'); sortServiceInstances(); }); + + DataService.list(servicePlansVersion, {}, function(planData) { + servicePlans = planData.by('metadata.name'); + }); } }; diff --git a/app/scripts/directives/serviceBinding.js b/app/scripts/directives/serviceBinding.js index f37805239c..e1ee812853 100644 --- a/app/scripts/directives/serviceBinding.js +++ b/app/scripts/directives/serviceBinding.js @@ -24,7 +24,7 @@ if (_.get(ctrl.refApiObject, 'kind') !== 'ServiceInstance') { var instanceName = _.get(ctrl.binding, 'spec.instanceRef.name'); var instance = _.get(ctrl.serviceInstances, [instanceName]); - var serviceClassName = _.get(instance, 'spec.serviceClassName'); + var serviceClassName = _.get(instance, 'spec.serviceClassRef.name'); ctrl.serviceClass = _.get(ctrl.serviceClasses, [serviceClassName]); } }; diff --git a/app/scripts/directives/unbindService.js b/app/scripts/directives/unbindService.js index b88c0d993a..bf20b6e7b9 100644 --- a/app/scripts/directives/unbindService.js +++ b/app/scripts/directives/unbindService.js @@ -6,6 +6,7 @@ controller: [ '$scope', '$filter', + 'APIService', 'DataService', UnbindService ], @@ -19,29 +20,31 @@ templateUrl: 'views/directives/unbind-service.html' }); - function UnbindService($scope, $filter, DataService) { + function UnbindService($scope, + $filter, + APIService, + DataService) { var ctrl = this; var validityWatcher; var context; var enableTechPreviewFeature = $filter('enableTechPreviewFeature'); var serviceInstanceDisplayName = $filter('serviceInstanceDisplayName'); + var serviceBindingsVersion = APIService.getPreferredVersion('servicebindings'); + var unbindService = function() { var bindingName = ctrl.selectedBinding.metadata.name; // Make sure to get the unbound apps now. Otherwise they don't appear on // the result page since deleting the binding will remove them from the // map that is passed in. ctrl.unboundApps = ctrl.appsForBinding(bindingName); - DataService.delete({ - group: 'servicecatalog.k8s.io', - resource: 'serviceinstancecredentials' - }, - bindingName, - context, - { propagationPolicy: null }) - .then(_.noop, function(err) { - ctrl.error = err; - }); + DataService.delete(serviceBindingsVersion, + bindingName, + context, + { propagationPolicy: null }) + .then(_.noop, function(err) { + ctrl.error = err; + }); }; var setupValidator = function() { diff --git a/app/scripts/filters/resources.js b/app/scripts/filters/resources.js index 39f5d3db5f..15c42c08b8 100644 --- a/app/scripts/filters/resources.js +++ b/app/scripts/filters/resources.js @@ -1316,17 +1316,28 @@ angular.module('openshiftConsole') return !_.isEmpty(alternateBackends); }; }) - // .filter('serviceClassDisplayName', function() { - // return function(serviceClass) { - // TODO: this filter may also be useful. - // }; - // }) - .filter('serviceInstanceDisplayName', function() { - return function(instance, serviceClasses) { - var serviceClassName = instance.spec.serviceClassName; - var instanceName = instance.metadata.name; - var serviceClassDisplayName = _.get(serviceClasses, [serviceClassName, 'externalMetadata', 'displayName']); - return serviceClassDisplayName || serviceClassName || instanceName; + .filter('serviceClassDisplayName', function() { + return function(serviceClass) { + var serviceClassDisplayName = _.get(serviceClass, 'spec.externalMetadata.displayName'); + if (serviceClassDisplayName) { + return serviceClassDisplayName; + } + + var serviceClassExternalName = _.get(serviceClass, 'spec.externalName'); + if (serviceClassExternalName) { + return serviceClassExternalName; + } + + return _.get(serviceClass, 'metadata.name'); + }; + }) + .filter('serviceInstanceDisplayName', function(serviceClassDisplayNameFilter) { + return function(instance, serviceClass) { + if (serviceClass) { + return serviceClassDisplayNameFilter(serviceClass); + } + + return _.get(instance, 'metadata.name'); }; }) .filter('serviceInstanceStatus', function(isServiceInstanceReadyFilter) { diff --git a/app/scripts/services/catalog.js b/app/scripts/services/catalog.js index ca1363fd5f..c2ff749242 100644 --- a/app/scripts/services/catalog.js +++ b/app/scripts/services/catalog.js @@ -7,13 +7,19 @@ angular.module("openshiftConsole") KeywordService) { var getTags = $filter('tags'); + // API versions + var serviceBindingsVersion = APIService.getPreferredVersion('servicebindings'); + var serviceClassesVersion = APIService.getPreferredVersion('clusterserviceclasses'); + var serviceInstancesVersion = APIService.getPreferredVersion('serviceinstances'); + var servicePlansVersion = APIService.getPreferredVersion('clusterserviceplans'); + // Enable service catalog features if the new experience is enabled and the // servicecatalog.k8s.io resources are available. - var SERVICE_CATALOG_ENABLED = - !Constants.SERVICE_CATALOG_ENABLED && - APIService.apiInfo({ group: 'servicecatalog.k8s.io', resource: 'serviceclasses' }) && - APIService.apiInfo({ group: 'servicecatalog.k8s.io', resource: 'serviceinstances' }) && - APIService.apiInfo({ group: 'servicecatalog.k8s.io', resource: 'serviceinstancecredentials' }); + var SERVICE_CATALOG_ENABLED = !Constants.DISABLE_SERVICE_CATALOG_LANDING_PAGE && + APIService.apiInfo(serviceBindingsVersion) && + APIService.apiInfo(serviceClassesVersion) && + APIService.apiInfo(serviceInstancesVersion) && + APIService.apiInfo(servicePlansVersion); var categoryItemByID = {}; _.each(Constants.CATALOG_CATEGORIES, function(category) { diff --git a/app/scripts/services/serviceInstances.js b/app/scripts/services/serviceInstances.js index b9a6f30de8..7230cf7590 100644 --- a/app/scripts/services/serviceInstances.js +++ b/app/scripts/services/serviceInstances.js @@ -10,6 +10,33 @@ angular.module("openshiftConsole") DataService, Logger, NotificationsService) { + var serviceClassesVersion = APIService.getPreferredVersion('clusterserviceclasses'); + var servicePlansVersion = APIService.getPreferredVersion('clusterserviceplans'); + + var getServiceClassNameForInstance = function(serviceInstance) { + return _.get(serviceInstance, 'spec.serviceClassRef.name'); + }; + + var fetchServiceClassForInstance = function(serviceInstance) { + var serviceClassName = getServiceClassNameForInstance(serviceInstance); + return DataService.get(serviceClassesVersion, serviceClassName, {}); + }; + + var getServicePlanNameForInstance = function(serviceInstance) { + return _.get(serviceInstance, 'spec.servicePlanRef.name'); + }; + + var fetchServicePlanForInstance = function(serviceInstance) { + var servicePlanName = getServicePlanNameForInstance(serviceInstance); + return DataService.get(servicePlansVersion, servicePlanName, {}); + }; + + // Checks if this plan is currently the one the instance references. + var isCurrentPlan = function(serviceInstance, servicePlan) { + var servicePlanName = getServicePlanNameForInstance(serviceInstance); + return servicePlanName === _.get(servicePlan, 'metadata.name'); + }; + var getBindingsIfNecessary = function(apiObject, bindings) { if (angular.isDefined(bindings)) { return $q.when(bindings); @@ -115,6 +142,11 @@ angular.module("openshiftConsole") }; return { + getServiceClassNameForInstance: getServiceClassNameForInstance, + fetchServiceClassForInstance: fetchServiceClassForInstance, + getServicePlanNameForInstance: getServicePlanNameForInstance, + fetchServicePlanForInstance: fetchServicePlanForInstance, + isCurrentPlan: isCurrentPlan, deprovision: deprovision }; }); diff --git a/app/views/browse/service-instance.html b/app/views/browse/service-instance.html index 480463dd71..66542f6298 100644 --- a/app/views/browse/service-instance.html +++ b/app/views/browse/service-instance.html @@ -28,8 +28,10 @@

- {{serviceInstance | serviceInstanceDisplayName:serviceClasses}} - {{serviceInstance.metadata.name}} + {{displayName}} + + {{serviceInstance.metadata.name}} +
created
@@ -54,7 +56,7 @@

-

+

Status:
@@ -65,10 +67,10 @@

{{serviceInstance | serviceInstanceConditionMessage}}
-
Description:
+
Description:
-

-

+

+

diff --git a/app/views/directives/_service-binding.html b/app/views/directives/_service-binding.html index 2a234d35f5..4d610c3cfe 100644 --- a/app/views/directives/_service-binding.html +++ b/app/views/directives/_service-binding.html @@ -6,7 +6,7 @@

{{$ctrl.binding.metadata.name}} - {{$ctrl.serviceClass.externalMetadata.displayName || $ctrl.serviceClass.metadata.name}} + {{$ctrl.serviceClass.spec.externalMetadata.displayName || $ctrl.serviceClass.metadata.name}} {{$ctrl.binding.spec.instanceRef.name}} diff --git a/app/views/directives/bind-service/bind-service-form.html b/app/views/directives/bind-service/bind-service-form.html index 3ecd07e523..87716c99b6 100644 --- a/app/views/directives/bind-service/bind-service-form.html +++ b/app/views/directives/bind-service/bind-service-form.html @@ -9,7 +9,6 @@
Bindings

service-instances="$ctrl.serviceInstances">
@@ -22,7 +22,7 @@

Bindings

Browse Catalog
-
+
There are no service bindings.
diff --git a/app/views/overview/_service-instance-row.html b/app/views/overview/_service-instance-row.html index a92321cf2c..f9349b21db 100644 --- a/app/views/overview/_service-instance-row.html +++ b/app/views/overview/_service-instance-row.html @@ -135,11 +135,11 @@

-
-

-
- View Documentation - Get Support +
diff --git a/app/views/service-instances.html b/app/views/service-instances.html index b12c76959c..969493ede3 100644 --- a/app/views/service-instances.html +++ b/app/views/service-instances.html @@ -43,7 +43,9 @@

- {{serviceInstance | serviceInstanceDisplayName:serviceClasses}} + + {{serviceInstance | serviceInstanceDisplayName : getServiceClass(serviceInstance)}} + {{serviceInstance.metadata.name}}
diff --git a/bower.json b/bower.json index c5c641a063..a95cd06204 100644 --- a/bower.json +++ b/bower.json @@ -46,8 +46,8 @@ "angular-moment": "1.0.0", "angular-utf8-base64": "0.0.5", "file-saver": "1.3.3", - "origin-web-common": "0.0.63", - "origin-web-catalog": "0.0.52" + "origin-web-common": "0.0.64", + "origin-web-catalog": "0.0.53" }, "devDependencies": { "angular-mocks": "1.5.11", diff --git a/dist/scripts/scripts.js b/dist/scripts/scripts.js index 5e05048ce0..b534cac45d 100644 --- a/dist/scripts/scripts.js +++ b/dist/scripts/scripts.js @@ -1,16 +1,16 @@ "use strict"; -function OverviewController(e, t, n, a, r, o, i, s, c, l, u, d, m, p, f, g, h, v, y, b, C, S, w, k, j) { -var P = this, R = t("isIE")() || t("isEdge")(); -e.projectName = n.project, P.catalogLandingPageEnabled = !c.DISABLE_SERVICE_CATALOG_LANDING_PAGE; -var I, E, T = t("annotation"), N = t("buildConfigForBuild"), D = t("deploymentIsInProgress"), A = t("imageObjectRef"), B = t("isJenkinsPipelineStrategy"), L = t("isNewerResource"), U = t("label"), O = t("podTemplate"), F = {}, x = {}, M = {}, V = P.state = { +function OverviewController(e, t, n, a, r, o, i, s, c, l, u, d, m, p, f, g, h, v, y, b, C, S, w, k, j, P) { +var R = this, I = t("isIE")() || t("isEdge")(); +e.projectName = n.project, R.catalogLandingPageEnabled = !l.DISABLE_SERVICE_CATALOG_LANDING_PAGE; +var E, T, N = t("annotation"), D = t("canI"), A = t("buildConfigForBuild"), B = t("deploymentIsInProgress"), L = t("imageObjectRef"), U = t("isJenkinsPipelineStrategy"), O = t("isNewerResource"), F = t("label"), x = t("podTemplate"), M = r.getPreferredVersion("servicebindings"), V = r.getPreferredVersion("clusterserviceclasses"), q = r.getPreferredVersion("serviceinstances"), z = r.getPreferredVersion("clusterserviceplans"), H = {}, G = {}, K = {}, W = R.state = { alerts: {}, builds: {}, clusterQuotas: {}, imageStreamImageRefByDockerReference: {}, imagesByDockerReference: {}, limitRanges: {}, -limitWatches: R, +limitWatches: I, notificationsByObjectUID: {}, pipelinesByDeploymentConfig: {}, podsByOwnerUID: {}, @@ -19,25 +19,27 @@ recentPipelinesByDeploymentConfig: {}, routesByService: {}, servicesByObjectUID: {}, serviceInstances: {}, +serviceClasses: {}, +servicePlans: {}, bindingsByInstanceRef: {}, bindingsByApplicationUID: {}, applicationsByBinding: {}, showMetrics: !1 }; -P.state.breakpoint = m.getBreakpoint(); -var q = _.throttle(function() { -var t = m.getBreakpoint(); -P.state.breakpoint !== t && e.$evalAsync(function() { -P.state.breakpoint = t; +R.state.breakpoint = p.getBreakpoint(); +var Q = _.throttle(function() { +var t = p.getBreakpoint(); +R.state.breakpoint !== t && e.$evalAsync(function() { +R.state.breakpoint = t; }); }, 50); -$(window).on("resize.overview", q), P.showGetStarted = !1, P.showLoading = !0, P.filterByOptions = [ { +$(window).on("resize.overview", Q), R.showGetStarted = !1, R.showLoading = !0, R.filterByOptions = [ { id: "name", label: "Name" }, { id: "label", label: "Label" -} ], P.filterBy = g.getLabelSelector().isEmpty() ? "name" : "label", P.viewByOptions = [ { +} ], R.filterBy = h.getLabelSelector().isEmpty() ? "name" : "label", R.viewByOptions = [ { id: "app", label: "Application" }, { @@ -47,88 +49,88 @@ label: "Resource Type" id: "pipeline", label: "Pipeline" } ]; -var z = function(e) { +var J = function(e) { return _.get(e, "metadata.name"); -}, H = function(e) { +}, Y = function(e) { return _.get(e, "metadata.uid"); -}, G = function() { -return _.size(P.deploymentConfigs) + _.size(P.vanillaReplicationControllers) + _.size(P.deployments) + _.size(P.vanillaReplicaSets) + _.size(P.statefulSets) + _.size(P.monopods) + _.size(P.state.serviceInstances); -}, K = 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 = G(), P.filteredSize = K(); -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) { +}, Z = function() { +return _.size(R.deploymentConfigs) + _.size(R.vanillaReplicationControllers) + _.size(R.deployments) + _.size(R.vanillaReplicaSets) + _.size(R.statefulSets) + _.size(R.monopods) + _.size(R.state.serviceInstances); +}, X = function() { +return _.size(R.filteredDeploymentConfigs) + _.size(R.filteredReplicationControllers) + _.size(R.filteredDeployments) + _.size(R.filteredReplicaSets) + _.size(R.filteredStatefulSets) + _.size(R.filteredMonopods) + _.size(R.filteredServiceInstances); +}, ee = function() { +R.size = Z(), R.filteredSize = X(); +var e = 0 === R.size, t = R.deploymentConfigs && R.replicationControllers && R.deployments && R.replicaSets && R.statefulSets && R.pods && R.state.serviceInstances; +W.expandAll = t && 1 === R.size, R.showGetStarted = t && e, R.showLoading = !t && e, R.everythingFiltered = !e && !R.filteredSize, R.hidePipelineOtherResources = "pipeline" === R.viewBy && (R.filterActive || _.isEmpty(R.pipelineBuildConfigs)); +}, te = function(e) { return o.groupByApp(e, "metadata.name"); -}, J = function(e) { +}, ne = function(e) { var t = null; return _.each(e, function(e) { t = t ? j.getPreferredDisplayRoute(t, e) : e; }), t; -}, Y = _.debounce(function() { +}, ae = _.debounce(function() { e.$evalAsync(function() { -if (P.bestRouteByApp = {}, P.routes) { -var e = [ P.filteredDeploymentConfigsByApp, P.filteredReplicationControllersByApp, P.filteredDeploymentsByApp, P.filteredReplicaSetsByApp, P.filteredStatefulSetsByApp, P.filteredMonopodsByApp ]; -_.each(P.apps, function(t) { +if (R.bestRouteByApp = {}, R.routes) { +var e = [ R.filteredDeploymentConfigsByApp, R.filteredReplicationControllersByApp, R.filteredDeploymentsByApp, R.filteredReplicaSetsByApp, R.filteredStatefulSetsByApp, R.filteredMonopodsByApp ]; +_.each(R.apps, function(t) { var n = {}; _.each(e, function(e) { var a = _.get(e, t, []); _.each(a, function(e) { -var t = H(e), a = _.get(V, [ "servicesByObjectUID", t ], []); +var t = Y(e), a = _.get(W, [ "servicesByObjectUID", t ], []); _.each(a, function(e) { -var t = _.get(V, [ "routesByService", e.metadata.name ], []); +var t = _.get(W, [ "routesByService", e.metadata.name ], []); _.assign(n, _.keyBy(t, "metadata.name")); }); }); -}), P.bestRouteByApp[t] = J(n); +}), R.bestRouteByApp[t] = ne(n); }); } }); }, 300, { maxWait: 1500 -}), Z = function() { -P.filteredDeploymentConfigsByApp = Q(P.filteredDeploymentConfigs), P.filteredReplicationControllersByApp = Q(P.filteredReplicationControllers), P.filteredDeploymentsByApp = Q(P.filteredDeployments), P.filteredReplicaSetsByApp = Q(P.filteredReplicaSets), P.filteredStatefulSetsByApp = Q(P.filteredStatefulSets), P.filteredMonopodsByApp = Q(P.filteredMonopods), P.apps = _.union(_.keys(P.filteredDeploymentConfigsByApp), _.keys(P.filteredReplicationControllersByApp), _.keys(P.filteredDeploymentsByApp), _.keys(P.filteredReplicaSetsByApp), _.keys(P.filteredStatefulSetsByApp), _.keys(P.filteredMonopodsByApp)), o.sortAppNames(P.apps), Y(); -}, X = function() { -var e = _.filter(P.deploymentConfigs, function(e) { -var t = z(e); -return _.isEmpty(V.pipelinesByDeploymentConfig[t]); +}), re = function() { +R.filteredDeploymentConfigsByApp = te(R.filteredDeploymentConfigs), R.filteredReplicationControllersByApp = te(R.filteredReplicationControllers), R.filteredDeploymentsByApp = te(R.filteredDeployments), R.filteredReplicaSetsByApp = te(R.filteredReplicaSets), R.filteredStatefulSetsByApp = te(R.filteredStatefulSets), R.filteredMonopodsByApp = te(R.filteredMonopods), R.apps = _.union(_.keys(R.filteredDeploymentConfigsByApp), _.keys(R.filteredReplicationControllersByApp), _.keys(R.filteredDeploymentsByApp), _.keys(R.filteredReplicaSetsByApp), _.keys(R.filteredStatefulSetsByApp), _.keys(R.filteredMonopodsByApp)), o.sortAppNames(R.apps), ae(); +}, oe = function() { +var e = _.filter(R.deploymentConfigs, function(e) { +var t = J(e); +return _.isEmpty(W.pipelinesByDeploymentConfig[t]); }); -P.deploymentConfigsNoPipeline = _.sortBy(e, "metadata.name"), P.pipelineViewHasOtherResources = !(_.isEmpty(P.deploymentConfigsNoPipeline) && _.isEmpty(P.vanillaReplicationControllers) && _.isEmpty(P.deployments) && _.isEmpty(P.vanillaReplicaSets) && _.isEmpty(P.statefulSets) && _.isEmpty(P.monopods)); -}, ee = function() { -P.disableFilter = "pipeline" === P.viewBy && _.isEmpty(P.pipelineBuildConfigs); -}, te = function(e) { -return g.getLabelSelector().select(e); -}, ne = [ "metadata.name", "spec.serviceClassName" ], ae = function(e) { -return f.filterForKeywords(e, ne, V.filterKeywords); -}, re = function(e) { -switch (P.filterBy) { +R.deploymentConfigsNoPipeline = _.sortBy(e, "metadata.name"), R.pipelineViewHasOtherResources = !(_.isEmpty(R.deploymentConfigsNoPipeline) && _.isEmpty(R.vanillaReplicationControllers) && _.isEmpty(R.deployments) && _.isEmpty(R.vanillaReplicaSets) && _.isEmpty(R.statefulSets) && _.isEmpty(R.monopods)); +}, ie = function() { +R.disableFilter = "pipeline" === R.viewBy && _.isEmpty(R.pipelineBuildConfigs); +}, se = function(e) { +return h.getLabelSelector().select(e); +}, ce = [ "metadata.name", "spec.externalServiceClassName" ], le = function(e) { +return g.filterForKeywords(e, ce, W.filterKeywords); +}, ue = function(e) { +switch (R.filterBy) { case "label": -return te(e); +return se(e); case "name": -return ae(e); +return le(e); } return e; -}, oe = function() { -switch (P.filterBy) { +}, de = function() { +switch (R.filterBy) { case "label": -return !g.getLabelSelector().isEmpty(); +return !h.getLabelSelector().isEmpty(); case "name": -return !_.isEmpty(V.filterKeywords); +return !_.isEmpty(W.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(); -}, se = n.project + "/overview/view-by"; -P.viewBy = localStorage.getItem(se) || "app", e.$watch(function() { -return P.viewBy; +}, me = function() { +R.filteredDeploymentConfigs = ue(R.deploymentConfigs), R.filteredReplicationControllers = ue(R.vanillaReplicationControllers), R.filteredDeployments = ue(R.deployments), R.filteredReplicaSets = ue(R.vanillaReplicaSets), R.filteredStatefulSets = ue(R.statefulSets), R.filteredMonopods = ue(R.monopods), R.filteredPipelineBuildConfigs = ue(R.pipelineBuildConfigs), R.filteredServiceInstances = ue(W.orderedServiceInstances), R.filterActive = de(), re(), ee(); +}, pe = n.project + "/overview/view-by"; +R.viewBy = localStorage.getItem(pe) || "app", e.$watch(function() { +return R.viewBy; }, function(e) { -localStorage.setItem(se, e), ee(), ne = "app" === P.viewBy ? [ "metadata.name", "metadata.labels.app" ] : [ "metadata.name" ], ie(), "pipeline" === P.viewBy ? g.setLabelSuggestions(x) : g.setLabelSuggestions(F); -}), c.DISABLE_OVERVIEW_METRICS || (v.isAvailable(!0).then(function(e) { -V.showMetrics = e; +localStorage.setItem(pe, e), ie(), ce = "app" === R.viewBy ? [ "metadata.name", "metadata.labels.app" ] : [ "metadata.name" ], me(), "pipeline" === R.viewBy ? h.setLabelSuggestions(G) : h.setLabelSuggestions(H); +}), l.DISABLE_OVERVIEW_METRICS || (y.isAvailable(!0).then(function(e) { +W.showMetrics = e; }), e.$on("metrics-connection-failed", function(e, t) { -a.isAlertPermanentlyHidden("metrics-connection-failed") || V.alerts["metrics-connection-failed"] || (V.alerts["metrics-connection-failed"] = { +a.isAlertPermanentlyHidden("metrics-connection-failed") || W.alerts["metrics-connection-failed"] || (W.alerts["metrics-connection-failed"] = { type: "warning", message: "An error occurred getting metrics.", links: [ { @@ -144,403 +146,384 @@ return a.permanentlyHideAlert("metrics-connection-failed"), !0; } ] }); })); -var ce = function(e) { +var fe = function(e) { return e && "Pod" === e.kind; -}, le = function(e) { -var t = H(e); -return t ? ce(e) ? [ e ] : _.get(P, [ "state", "podsByOwnerUID", t ], []) : []; -}, ue = function(e, t) { -var n = H(e); -V.notificationsByObjectUID[n] = t || {}; -}, de = function(e) { -var t = H(e); -return t ? _.get(V, [ "notificationsByObjectUID", t ], {}) : {}; -}, me = function(e) { -if (H(e)) { -var t = le(e), a = k.getPodAlerts(t, n.project); -ue(e, a); -} -}, pe = function(e) { -_.each(e, me); -}, fe = function(e) { -var t = z(e); -return t ? M[t] : null; }, ge = function(e) { -var t = z(e); -return t ? _.get(P, [ "replicationControllersByDeploymentConfig", t ]) : []; -}; -P.getPreviousReplicationController = function(e) { -var t = ge(e); +var t = Y(e); +return t ? fe(e) ? [ e ] : _.get(R, [ "state", "podsByOwnerUID", t ], []) : []; +}, he = function(e, t) { +var n = Y(e); +W.notificationsByObjectUID[n] = t || {}; +}, ve = function(e) { +var t = Y(e); +return t ? _.get(W, [ "notificationsByObjectUID", t ], {}) : {}; +}, ye = function(e) { +if (Y(e)) { +var t = ge(e), a = k.getPodAlerts(t, n.project); +he(e, a); +} +}, be = function(e) { +_.each(e, ye); +}, Ce = function(e) { +var t = J(e); +return t ? K[t] : null; +}, Se = function(e) { +var t = J(e); +return t ? _.get(R, [ "replicationControllersByDeploymentConfig", t ]) : []; +}; +R.getPreviousReplicationController = function(e) { +var t = Se(e); return _.size(t) < 2 ? null : t[1]; }; -var he = function(e) { -var t = {}, n = fe(e); +var _e = function(e) { +var t = {}, n = Ce(e); _.assign(t, k.getDeploymentStatusAlerts(e, n), k.getPausedDeploymentAlerts(e)); -var a = ge(e); +var a = Se(e); _.each(a, function(e) { -var n = de(e); -_.assign(t, n); -}), ue(e, t); -}, ve = function() { -_.each(P.deploymentConfigs, he); -}, ye = function(e) { -var t = H(e); -return t ? _.get(P, [ "replicaSetsByDeploymentUID", t ]) : {}; -}, be = function(e) { -var t = k.getPausedDeploymentAlerts(e), n = ye(e); -_.each(n, function(e) { -var n = de(e); +var n = ve(e); _.assign(t, n); -}), ue(e, t); -}, Ce = function() { -_.each(P.deployments, be); -}, Se = function() { -pe(P.replicationControllers), pe(P.replicaSets), pe(P.statefulSets), pe(P.monopods); -}, _e = _.debounce(function() { -e.$evalAsync(function() { -Se(), ve(), Ce(); -}); -}, 500), we = function(e) { -_.isEmpty(e) || (g.addLabelSuggestionsFromResources(e, F), "pipeline" !== P.viewBy && g.setLabelSuggestions(F)); +}), he(e, t); +}, we = function() { +_.each(R.deploymentConfigs, _e); }, ke = function(e) { -_.isEmpty(e) || (g.addLabelSuggestionsFromResources(e, x), "pipeline" === P.viewBy && g.setLabelSuggestions(x)); +var t = Y(e); +return t ? _.get(R, [ "replicaSetsByDeploymentUID", t ]) : {}; }, je = function(e) { -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"))); +var t = k.getPausedDeploymentAlerts(e), n = ke(e); +_.each(n, function(e) { +var n = ve(e); +_.assign(t, n); +}), he(e, t); }, Pe = function() { -V.podsByOwnerUID = C.groupByOwnerUID(P.pods), P.monopods = _.filter(V.podsByOwnerUID[""], je); -}, Re = function(e) { -return !!_.get(e, "status.replicas") || (!T(e, "deploymentConfig") || D(e)); -}, Ie = function(e) { -return T(e, "deploymentConfig"); -}, Ee = function() { -if (P.deploymentConfigs && P.replicationControllers) { +_.each(R.deployments, je); +}, Re = function() { +be(R.replicationControllers), be(R.replicaSets), be(R.statefulSets), be(R.monopods); +}, Ie = _.debounce(function() { +e.$evalAsync(function() { +Re(), we(), Pe(); +}); +}, 500), Ee = function(e) { +_.isEmpty(e) || (h.addLabelSuggestionsFromResources(e, H), "pipeline" !== R.viewBy && h.setLabelSuggestions(H)); +}, Te = function(e) { +_.isEmpty(e) || (h.addLabelSuggestionsFromResources(e, G), "pipeline" === R.viewBy && h.setLabelSuggestions(G)); +}, Ne = function(e) { +return "Succeeded" !== e.status.phase && "Failed" !== e.status.phase && (!F(e, "openshift.io/deployer-pod-for.name") && (!N(e, "openshift.io/build.name") && "slave" !== F(e, "jenkins"))); +}, De = function() { +W.podsByOwnerUID = S.groupByOwnerUID(R.pods), R.monopods = _.filter(W.podsByOwnerUID[""], Ne); +}, Ae = function(e) { +return !!_.get(e, "status.replicas") || (!N(e, "deploymentConfig") || B(e)); +}, $e = function(e) { +return N(e, "deploymentConfig"); +}, Be = function() { +if (R.deploymentConfigs && R.replicationControllers) { var e = []; -P.replicationControllersByDeploymentConfig = {}, P.currentByDeploymentConfig = {}, M = {}; +R.replicationControllersByDeploymentConfig = {}, R.currentByDeploymentConfig = {}, K = {}; var t = {}, n = {}; -_.each(P.replicationControllers, function(a) { -var r = Ie(a) || ""; -(!r || !P.deploymentConfigs[r] && _.get(a, "status.replicas")) && e.push(a); -var o = M[r]; -o && !L(a, o) || (M[r] = a); +_.each(R.replicationControllers, function(a) { +var r = $e(a) || ""; +(!r || !R.deploymentConfigs[r] && _.get(a, "status.replicas")) && e.push(a); +var o = K[r]; +o && !O(a, o) || (K[r] = a); var i; -"Complete" === T(a, "deploymentStatus") && ((i = t[r]) && !L(a, i) || (t[r] = a)), Re(a) && _.set(n, [ r, a.metadata.name ], a); +"Complete" === N(a, "deploymentStatus") && ((i = t[r]) && !O(a, i) || (t[r] = a)), Ae(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) { -var n = u.sortByDeploymentVersion(e, !0); -P.replicationControllersByDeploymentConfig[t] = n, P.currentByDeploymentConfig[t] = _.head(n); -}), P.vanillaReplicationControllers = _.sortBy(e, "metadata.name"), ve(); +var n = d.sortByDeploymentVersion(e, !0); +R.replicationControllersByDeploymentConfig[t] = n, R.currentByDeploymentConfig[t] = _.head(n); +}), R.vanillaReplicationControllers = _.sortBy(e, "metadata.name"), we(); } -}, Te = function(e, t) { +}, Le = function(e, t) { if (_.get(e, "status.replicas")) return !0; -var n = u.getRevision(e); -return !n || !!t && u.getRevision(t) === n; -}, Ne = function() { -P.replicaSets && I && (P.replicaSetsByDeploymentUID = b.groupByControllerUID(P.replicaSets), P.currentByDeploymentUID = {}, _.each(P.replicaSetsByDeploymentUID, function(e, t) { +var n = d.getRevision(e); +return !n || !!t && d.getRevision(t) === n; +}, Ue = function() { +R.replicaSets && E && (R.replicaSetsByDeploymentUID = C.groupByControllerUID(R.replicaSets), R.currentByDeploymentUID = {}, _.each(R.replicaSetsByDeploymentUID, function(e, t) { if (t) { -var n = I[t], a = _.filter(e, function(e) { -return Te(e, n); -}), r = u.sortByRevision(a); -P.replicaSetsByDeploymentUID[t] = r, P.currentByDeploymentUID[t] = _.head(r); -} -}), P.vanillaReplicaSets = _.sortBy(P.replicaSetsByDeploymentUID[""], "metadata.name"), Ce()); -}, De = {}, Ae = function(e) { -e && V.allServices && _.each(e, function(e) { -var t = [], n = H(e), a = O(e); -_.each(De, function(e, n) { -e.matches(a) && t.push(V.allServices[n]); -}), V.servicesByObjectUID[n] = _.sortBy(t, "metadata.name"); -}); -}, $e = function() { -if (V.allServices) { -De = _.mapValues(V.allServices, function(e) { +var n = E[t], a = _.filter(e, function(e) { +return Le(e, n); +}), r = d.sortByRevision(a); +R.replicaSetsByDeploymentUID[t] = r, R.currentByDeploymentUID[t] = _.head(r); +} +}), R.vanillaReplicaSets = _.sortBy(R.replicaSetsByDeploymentUID[""], "metadata.name"), Pe()); +}, Oe = {}, Fe = function(e) { +e && W.allServices && _.each(e, function(e) { +var t = [], n = Y(e), a = x(e); +_.each(Oe, function(e, n) { +e.matches(a) && t.push(W.allServices[n]); +}), W.servicesByObjectUID[n] = _.sortBy(t, "metadata.name"); +}); +}, xe = function() { +if (W.allServices) { +Oe = _.mapValues(W.allServices, function(e) { return new LabelSelector(e.spec.selector); }); -var e = [ P.deploymentConfigs, P.vanillaReplicationControllers, P.deployments, P.vanillaReplicaSets, P.statefulSets, P.monopods ]; -_.each(e, Ae), Y(); +var e = [ R.deploymentConfigs, R.vanillaReplicationControllers, R.deployments, R.vanillaReplicaSets, R.statefulSets, R.monopods ]; +_.each(e, Fe), ae(); } -}, Be = function() { -var e = j.groupByService(P.routes, !0); -V.routesByService = _.mapValues(e, j.sortRoutesByScore), Y(); -}, Le = function() { -V.hpaByResource = d.groupHPAs(P.horizontalPodAutoscalers); -}, Ue = function(e) { -var t = N(e), n = P.buildConfigs[t]; +}, Me = function() { +var e = j.groupByService(R.routes, !0); +W.routesByService = _.mapValues(e, j.sortRoutesByScore), ae(); +}, Ve = function() { +W.hpaByResource = m.groupHPAs(R.horizontalPodAutoscalers); +}, qe = function(e) { +var t = A(e), n = R.buildConfigs[t]; if (n) { -P.recentPipelinesByBuildConfig[t] = P.recentPipelinesByBuildConfig[t] || [], P.recentPipelinesByBuildConfig[t].push(e); -var a = i.usesDeploymentConfigs(n); +R.recentPipelinesByBuildConfig[t] = R.recentPipelinesByBuildConfig[t] || [], R.recentPipelinesByBuildConfig[t].push(e); +var a = s.usesDeploymentConfigs(n); _.each(a, function(t) { -V.recentPipelinesByDeploymentConfig[t] = V.recentPipelinesByDeploymentConfig[t] || [], V.recentPipelinesByDeploymentConfig[t].push(e); -}), X(); -} -}, Oe = {}, Fe = function() { -Oe = i.groupBuildConfigsByOutputImage(P.buildConfigs); -}, xe = function(e) { -var t = H(e); -if (t) return _.get(V, [ "buildConfigsByObjectUID", t ], []); -}, Me = function(e) { -var t = [], n = xe(e); +W.recentPipelinesByDeploymentConfig[t] = W.recentPipelinesByDeploymentConfig[t] || [], W.recentPipelinesByDeploymentConfig[t].push(e); +}), oe(); +} +}, ze = {}, He = function() { +ze = s.groupBuildConfigsByOutputImage(R.buildConfigs); +}, Ge = function(e) { +var t = Y(e); +if (t) return _.get(W, [ "buildConfigsByObjectUID", t ], []); +}, Ke = function(e) { +var t = [], n = Ge(e); _.each(n, function(e) { -var n = _.get(V, [ "recentBuildsByBuildConfig", e.metadata.name ], []); +var n = _.get(W, [ "recentBuildsByBuildConfig", e.metadata.name ], []); t = t.concat(n); }); -var a = z(e); -_.set(V, [ "recentBuildsByDeploymentConfig", a ], t); -}, Ve = function(e, t) { -var n = H(t); -n && _.set(V, [ "buildConfigsByObjectUID", n ], e); -}, qe = function() { +var a = J(e); +_.set(W, [ "recentBuildsByDeploymentConfig", a ], t); +}, We = function(e, t) { +var n = Y(t); +n && _.set(W, [ "buildConfigsByObjectUID", n ], e); +}, Qe = function() { var e = []; -P.deploymentConfigsByPipeline = {}, V.pipelinesByDeploymentConfig = {}, _.each(P.buildConfigs, function(t) { -if (B(t)) { +R.deploymentConfigsByPipeline = {}, W.pipelinesByDeploymentConfig = {}, _.each(R.buildConfigs, function(t) { +if (U(t)) { e.push(t); -var n = i.usesDeploymentConfigs(t), a = z(t); -_.set(P, [ "deploymentConfigsByPipeline", a ], n), _.each(n, function(e) { -V.pipelinesByDeploymentConfig[e] = V.pipelinesByDeploymentConfig[e] || [], V.pipelinesByDeploymentConfig[e].push(t); +var n = s.usesDeploymentConfigs(t), a = J(t); +_.set(R, [ "deploymentConfigsByPipeline", a ], n), _.each(n, function(e) { +W.pipelinesByDeploymentConfig[e] = W.pipelinesByDeploymentConfig[e] || [], W.pipelinesByDeploymentConfig[e].push(t); }); } -}), P.pipelineBuildConfigs = _.sortBy(e, "metadata.name"), X(), ke(P.pipelineBuildConfigs), ee(); -}, ze = function() { -V.buildConfigsByObjectUID = {}, _.each(P.deploymentConfigs, function(e) { +}), R.pipelineBuildConfigs = _.sortBy(e, "metadata.name"), oe(), Te(R.pipelineBuildConfigs), ie(); +}, Je = function() { +W.buildConfigsByObjectUID = {}, _.each(R.deploymentConfigs, function(e) { var t = [], n = _.get(e, "spec.triggers"); _.each(n, function(n) { var a = _.get(n, "imageChangeParams.from"); if (a) { -var r = A(a, e.metadata.namespace), o = Oe[r]; +var r = L(a, e.metadata.namespace), o = ze[r]; _.isEmpty(o) || (t = t.concat(o)); } -}), t = _.sortBy(t, "metadata.name"), Ve(t, e), Me(e); +}), t = _.sortBy(t, "metadata.name"), We(t, e), Ke(e); }); -}, He = function() { -qe(), ze(); -}, Ge = function() { -_.each(P.deploymentConfigs, Me); -}, Ke = function() { -if (V.builds && P.buildConfigs) { -P.recentPipelinesByBuildConfig = {}, V.recentBuildsByBuildConfig = {}, V.recentPipelinesByDeploymentConfig = {}; +}, Ye = function() { +Qe(), Je(); +}, Ze = function() { +_.each(R.deploymentConfigs, Ke); +}, Xe = function() { +if (W.builds && R.buildConfigs) { +R.recentPipelinesByBuildConfig = {}, W.recentBuildsByBuildConfig = {}, W.recentPipelinesByDeploymentConfig = {}; var e = {}; -_.each(i.interestingBuilds(V.builds), function(t) { -var n = N(t); -B(t) ? Ue(t) : (e[n] = e[n] || [], e[n].push(t)); -}), P.recentPipelinesByBuildConfig = _.mapValues(P.recentPipelinesByBuildConfig, function(e) { -return i.sortBuilds(e, !0); -}), V.recentPipelinesByDeploymentConfig = _.mapValues(V.recentPipelinesByDeploymentConfig, function(e) { -return i.sortBuilds(e, !0); -}), V.recentBuildsByBuildConfig = _.mapValues(e, function(e) { -return i.sortBuilds(e, !0); -}), Ge(); -} -}, We = function() { -k.setQuotaNotifications(V.quotas, V.clusterQuotas, n.project); -}; -P.clearFilter = function() { -g.clear(), P.filterText = ""; +_.each(s.interestingBuilds(W.builds), function(t) { +var n = A(t); +U(t) ? qe(t) : (e[n] = e[n] || [], e[n].push(t)); +}), R.recentPipelinesByBuildConfig = _.mapValues(R.recentPipelinesByBuildConfig, function(e) { +return s.sortBuilds(e, !0); +}), W.recentPipelinesByDeploymentConfig = _.mapValues(W.recentPipelinesByDeploymentConfig, function(e) { +return s.sortBuilds(e, !0); +}), W.recentBuildsByBuildConfig = _.mapValues(e, function(e) { +return s.sortBuilds(e, !0); +}), Ze(); +} +}, et = function() { +k.setQuotaNotifications(W.quotas, W.clusterQuotas, n.project); +}; +R.clearFilter = function() { +h.clear(), R.filterText = ""; }, e.$watch(function() { -return P.filterText; +return R.filterText; }, _.debounce(function(t, n) { -t !== n && (V.filterKeywords = f.generateKeywords(t), e.$evalAsync(ie)); +t !== n && (W.filterKeywords = g.generateKeywords(t), e.$evalAsync(me)); }, 50, { maxWait: 250 })), e.$watch(function() { -return P.filterBy; +return R.filterBy; }, function(e, t) { -e !== t && (P.clearFilter(), ie()); -}), g.onActiveFiltersChanged(function() { -e.$evalAsync(ie); -}), P.startBuild = i.startBuild; -var Qe = function() { -if (V.bindingsByApplicationUID = {}, V.applicationsByBinding = {}, V.deleteableBindingsByApplicationUID = {}, !_.isEmpty(V.bindings)) { -var e = [ P.deployments, P.deploymentConfigs, P.vanillaReplicationControllers, P.vanillaReplicaSets, P.statefulSets ]; +e !== t && (R.clearFilter(), me()); +}), h.onActiveFiltersChanged(function() { +e.$evalAsync(me); +}), R.startBuild = s.startBuild; +var tt = function() { +if (W.bindingsByApplicationUID = {}, W.applicationsByBinding = {}, W.deleteableBindingsByApplicationUID = {}, !_.isEmpty(W.bindings)) { +var e = [ R.deployments, R.deploymentConfigs, R.vanillaReplicationControllers, R.vanillaReplicaSets, R.statefulSets ]; if (!_.some(e, function(e) { return !e; })) { -var t = w.getPodPresetSelectorsForBindings(V.bindings); +var t = i.getPodPresetSelectorsForBindings(W.bindings); _.each(e, function(e) { _.each(e, function(e) { -var n = H(e), a = new LabelSelector(_.get(e, "spec.selector")); -V.bindingsByApplicationUID[n] = [], V.deleteableBindingsByApplicationUID[n] = [], _.each(t, function(t, r) { -t.covers(a) && (V.bindingsByApplicationUID[n].push(V.bindings[r]), _.get(V.bindings[r], "metadata.deletionTimestamp") || V.deleteableBindingsByApplicationUID[n].push(V.bindings[r]), V.applicationsByBinding[r] = V.applicationsByBinding[r] || [], V.applicationsByBinding[r].push(e)); +var n = Y(e), a = new LabelSelector(_.get(e, "spec.selector")); +W.bindingsByApplicationUID[n] = [], W.deleteableBindingsByApplicationUID[n] = [], _.each(t, function(t, r) { +t.covers(a) && (W.bindingsByApplicationUID[n].push(W.bindings[r]), _.get(W.bindings[r], "metadata.deletionTimestamp") || W.deleteableBindingsByApplicationUID[n].push(W.bindings[r]), W.applicationsByBinding[r] = W.applicationsByBinding[r] || [], W.applicationsByBinding[r].push(e)); }); }); -}), P.bindingsByInstanceRef = _.reduce(P.bindingsByInstanceRef, function(e, t, n) { +}), R.bindingsByInstanceRef = _.reduce(R.bindingsByInstanceRef, function(e, t, n) { return e[n] = _.sortBy(t, function(e) { -var t = _.get(V.applicationsByBinding, [ e.metadata.name ]); +var t = _.get(W.applicationsByBinding, [ e.metadata.name ]); return _.get(_.head(t), [ "metadata", "name" ]) || e.metadata.name; }), e; }, {}); } } -}, Je = function() { -V.bindableServiceInstances = w.filterBindableServiceInstances(V.serviceInstances, V.serviceClasses), V.orderedServiceInstances = w.sortServiceInstances(V.serviceInstances, V.serviceClasses); -}, Ye = []; -S.get(n.project).then(_.spread(function(n, a) { -V.project = e.project = n, V.context = a; -var r = function() { -P.pods && p.fetchReferencedImageStreamImages(P.pods, V.imagesByDockerReference, V.imageStreamImageRefByDockerReference, a); -}; -Ye.push(l.watch("pods", a, function(e) { -P.pods = e.by("metadata.name"), Pe(), r(), _e(), Ae(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"), Ee(), Ae(P.vanillaReplicationControllers), Ae(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"), Ee(), Ae(P.deploymentConfigs), Ae(P.vanillaReplicationControllers), we(P.deploymentConfigs), Ce(), He(), Ge(), Qe(), ie(), h.log("deploymentconfigs (subscribe)", P.deploymentConfigs); -})), Ye.push(l.watch({ +}, nt = function() { +W.bindableServiceInstances = i.filterBindableServiceInstances(W.serviceInstances, W.serviceClasses, W.servicePlans), W.orderedServiceInstances = i.sortServiceInstances(W.serviceInstances, W.serviceClasses); +}, at = []; +w.get(n.project).then(_.spread(function(t, n) { +W.project = e.project = t, W.context = n; +var a = function() { +R.pods && f.fetchReferencedImageStreamImages(R.pods, W.imagesByDockerReference, W.imageStreamImageRefByDockerReference, n); +}; +at.push(u.watch("pods", n, function(e) { +R.pods = e.by("metadata.name"), De(), a(), Ie(), Fe(R.monopods), be(R.monopods), Ee(R.monopods), me(), v.log("pods (subscribe)", R.pods); +})), at.push(u.watch("replicationcontrollers", n, function(e) { +R.replicationControllers = e.by("metadata.name"), Be(), Fe(R.vanillaReplicationControllers), Fe(R.monopods), be(R.vanillaReplicationControllers), Ee(R.vanillaReplicationControllers), tt(), me(), v.log("replicationcontrollers (subscribe)", R.replicationControllers); +})), at.push(u.watch("deploymentconfigs", n, function(e) { +R.deploymentConfigs = e.by("metadata.name"), Be(), Fe(R.deploymentConfigs), Fe(R.vanillaReplicationControllers), Ee(R.deploymentConfigs), Pe(), Ye(), Ze(), tt(), me(), v.log("deploymentconfigs (subscribe)", R.deploymentConfigs); +})), at.push(u.watch({ group: "extensions", resource: "replicasets" -}, a, function(e) { -P.replicaSets = e.by("metadata.name"), Ne(), Ae(P.vanillaReplicaSets), Ae(P.monopods), pe(P.vanillaReplicaSets), we(P.vanillaReplicaSets), Qe(), ie(), h.log("replicasets (subscribe)", P.replicaSets); -})), Ye.push(l.watch({ +}, n, function(e) { +R.replicaSets = e.by("metadata.name"), Ue(), Fe(R.vanillaReplicaSets), Fe(R.monopods), be(R.vanillaReplicaSets), Ee(R.vanillaReplicaSets), tt(), me(), v.log("replicasets (subscribe)", R.replicaSets); +})), at.push(u.watch({ group: "apps", resource: "deployments" -}, a, function(e) { -I = e.by("metadata.uid"), P.deployments = _.sortBy(I, "metadata.name"), Ne(), Ae(P.deployments), Ae(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"), Ke(), h.log("builds (subscribe)", V.builds); -})), Ye.push(l.watch({ +}, n, function(e) { +E = e.by("metadata.uid"), R.deployments = _.sortBy(E, "metadata.name"), Ue(), Fe(R.deployments), Fe(R.vanillaReplicaSets), Ee(R.deployments), tt(), me(), v.log("deployments (subscribe)", R.deploymentsByUID); +})), at.push(u.watch("builds", n, function(e) { +W.builds = e.by("metadata.name"), Xe(), v.log("builds (subscribe)", W.builds); +})), at.push(u.watch({ group: "apps", resource: "statefulsets" -}, a, function(e) { -P.statefulSets = e.by("metadata.name"), Ae(P.statefulSets), Ae(P.monopods), pe(P.statefulSets), we(P.statefulSets), Qe(), ie(), h.log("statefulsets (subscribe)", P.statefulSets); +}, n, function(e) { +R.statefulSets = e.by("metadata.name"), Fe(R.statefulSets), Fe(R.monopods), be(R.statefulSets), Ee(R.statefulSets), tt(), me(), v.log("statefulsets (subscribe)", R.statefulSets); }, { -poll: R, +poll: I, pollInterval: 6e4 -})), Ye.push(l.watch("services", a, function(e) { -V.allServices = e.by("metadata.name"), $e(), h.log("services (subscribe)", V.allServices); +})), at.push(u.watch("services", n, function(e) { +W.allServices = e.by("metadata.name"), xe(), v.log("services (subscribe)", W.allServices); }, { -poll: R, +poll: I, pollInterval: 6e4 -})), Ye.push(l.watch("routes", a, function(e) { -P.routes = e.by("metadata.name"), Be(), h.log("routes (subscribe)", P.routes); +})), at.push(u.watch("routes", n, function(e) { +R.routes = e.by("metadata.name"), Me(), v.log("routes (subscribe)", R.routes); }, { -poll: R, +poll: I, pollInterval: 6e4 -})), Ye.push(l.watch("buildConfigs", a, function(e) { -P.buildConfigs = e.by("metadata.name"), Fe(), He(), Ke(), ie(), h.log("buildconfigs (subscribe)", P.buildConfigs); +})), at.push(u.watch("buildConfigs", n, function(e) { +R.buildConfigs = e.by("metadata.name"), He(), Ye(), Xe(), me(), v.log("buildconfigs (subscribe)", R.buildConfigs); }, { -poll: R, +poll: I, pollInterval: 6e4 -})), Ye.push(l.watch({ +})), at.push(u.watch({ group: "autoscaling", resource: "horizontalpodautoscalers", version: "v1" -}, a, function(e) { -P.horizontalPodAutoscalers = e.by("metadata.name"), Le(), h.log("autoscalers (subscribe)", P.horizontalPodAutoscalers); +}, n, function(e) { +R.horizontalPodAutoscalers = e.by("metadata.name"), Ve(), v.log("autoscalers (subscribe)", R.horizontalPodAutoscalers); }, { -poll: R, +poll: I, pollInterval: 6e4 -})), Ye.push(l.watch("imagestreams", a, function(e) { -E = e.by("metadata.name"), p.buildDockerRefMapForImageStreams(E, V.imageStreamImageRefByDockerReference), r(), h.log("imagestreams (subscribe)", E); +})), at.push(u.watch("imagestreams", n, function(e) { +T = e.by("metadata.name"), f.buildDockerRefMapForImageStreams(T, W.imageStreamImageRefByDockerReference), a(), v.log("imagestreams (subscribe)", T); }, { -poll: R, +poll: I, pollInterval: 6e4 -})), Ye.push(l.watch("resourcequotas", a, function(e) { -V.quotas = e.by("metadata.name"), We(); +})), at.push(u.watch("resourcequotas", n, function(e) { +W.quotas = e.by("metadata.name"), et(); }, { poll: !0, pollInterval: 6e4 -})), Ye.push(l.watch("appliedclusterresourcequotas", a, function(e) { -V.clusterQuotas = e.by("metadata.name"), We(); +})), at.push(u.watch("appliedclusterresourcequotas", n, function(e) { +W.clusterQuotas = e.by("metadata.name"), et(); }, { poll: !0, pollInterval: 6e4 })); -var o = t("canI"); -s.SERVICE_CATALOG_ENABLED && o({ -resource: "serviceinstances", -group: "servicecatalog.k8s.io" -}, "watch") && Ye.push(l.watch({ -group: "servicecatalog.k8s.io", -resource: "serviceinstances" -}, a, function(e) { -V.serviceInstances = e.by("metadata.name"), _.each(V.serviceInstances, function(e) { +var r, o, i = {}, s = {}; +c.SERVICE_CATALOG_ENABLED && D(q, "watch") && (r = function(e) { +var t = P.getServiceClassNameForInstance(e); +_.has(W, [ "serviceClasses", t ]) || i[t] || (i[t] = u.get(V, t, {}).then(function(e) { +W.serviceClasses[t] = e; +}).finally(function() { +delete s[t]; +})); +}, o = function(e) { +var t = P.getServicePlanNameForInstance(e); +_.has(W, [ "servicePlans", t ]) || s[t] || (s[t] = u.get(z, t, {}).then(function(e) { +W.servicePlans[t] = e; +}).finally(function() { +delete s[t]; +})); +}, at.push(u.watch(q, n, function(e) { +W.serviceInstances = e.by("metadata.name"), _.each(W.serviceInstances, function(e) { var t = k.getServiceInstanceAlerts(e); -ue(e, t); -}), Je(), we(V.serviceInstances), ie(); +he(e, t), r(e), o(e); +}), nt(), Ee(W.serviceInstances), me(); }, { -poll: R, +poll: I, pollInterval: 6e4 -})), s.SERVICE_CATALOG_ENABLED && o({ -resource: "serviceinstancecredentials", -group: "servicecatalog.k8s.io" -}, "watch") && Ye.push(l.watch({ -group: "servicecatalog.k8s.io", -resource: "serviceinstancecredentials" -}, a, function(e) { -V.bindings = e.by("metadata.name"), P.bindingsByInstanceRef = _.groupBy(V.bindings, "spec.instanceRef.name"), Qe(); +}))), c.SERVICE_CATALOG_ENABLED && D(M, "watch") && at.push(u.watch(M, n, function(e) { +W.bindings = e.by("metadata.name"), R.bindingsByInstanceRef = _.groupBy(W.bindings, "spec.instanceRef.name"), tt(); }, { -poll: R, +poll: I, pollInterval: 6e4 -})), l.list("limitranges", a, function(e) { -V.limitRanges = e.by("metadata.name"); -}), s.SERVICE_CATALOG_ENABLED && o({ -resource: "serviceinstances", -group: "servicecatalog.k8s.io" -}, "watch") && l.list({ -group: "servicecatalog.k8s.io", -resource: "serviceclasses" -}, {}, function(e) { -V.serviceClasses = e.by("metadata.name"), Je(), ie(); +})), u.list("limitranges", n, function(e) { +W.limitRanges = e.by("metadata.name"); }); -var i = c.SAMPLE_PIPELINE_TEMPLATE; -i && l.get("templates", i.name, { -namespace: i.namespace +var d = l.SAMPLE_PIPELINE_TEMPLATE; +d && u.get("templates", d.name, { +namespace: d.namespace }, { errorNotification: !1 }).then(function(t) { -P.samplePipelineURL = y.createFromTemplateURL(t, e.projectName); +R.samplePipelineURL = b.createFromTemplateURL(t, e.projectName); }), e.$on("$destroy", function() { -l.unwatchAll(Ye), $(window).off(".overview"); +u.unwatchAll(at), $(window).off(".overview"); }); })); } -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 && ("ServiceInstance" === _.get(r, "apiObject.kind") || 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)); -}, u = function() { -r.bindableServiceInstances = n.filterBindableServiceInstances(r.serviceInstances, r.serviceClasses), r.orderedServiceInstances = n.sortServiceInstances(r.serviceInstances, r.serviceClasses); +function ResourceServiceBindings(e, t, n, a, r) { +var o, i = this, s = e("enableTechPreviewFeature"); +i.bindings = [], i.bindableServiceInstances = [], i.serviceClasses = [], i.serviceInstances = [], i.showBindings = a.SERVICE_CATALOG_ENABLED && ("ServiceInstance" === _.get(i, "apiObject.kind") || s("pod_presets")); +var c = e("isIE")() || e("isEdge")(), l = [], u = e("canI"), d = i.serviceBindingsVersion = t.getPreferredVersion("servicebindings"), m = t.getPreferredVersion("clusterserviceclasses"), p = t.getPreferredVersion("serviceinstances"), f = t.getPreferredVersion("clusterserviceplans"), g = function() { +i.apiObject && i.bindings && (i.bindings = n.getBindingsForResource(i.bindings, i.apiObject)); +}, h = function() { +i.bindableServiceInstances = n.filterBindableServiceInstances(i.serviceInstances, i.serviceClasses, o), i.orderedServiceInstances = n.sortServiceInstances(i.serviceInstances, i.serviceClasses); }; -r.createBinding = function() { -r.overlayPanelVisible = !0, r.overlayPanelName = "bindService"; -}, r.closeOverlayPanel = function() { -r.overlayPanelVisible = !1; +i.createBinding = function() { +i.overlayPanelVisible = !0, i.overlayPanelName = "bindService"; +}, i.closeOverlayPanel = function() { +i.overlayPanelVisible = !1; }; -var d = function() { -t.unwatchAll(s), s = [], a.SERVICE_CATALOG_ENABLED && c({ -resource: "serviceinstancecredentials", -group: "servicecatalog.k8s.io" -}, "watch") && s.push(t.watch({ -group: "servicecatalog.k8s.io", -resource: "serviceinstancecredentials" -}, r.projectContext, function(e) { -r.bindings = e.by("metadata.name"), l(); +var v = function() { +r.unwatchAll(l), l = [], a.SERVICE_CATALOG_ENABLED && u(d, "watch") && l.push(r.watch(d, i.projectContext, function(e) { +i.bindings = e.by("metadata.name"), g(); }, { -poll: i, +poll: c, pollInterval: 6e4 -})), a.SERVICE_CATALOG_ENABLED && c({ -resource: "serviceinstances", -group: "servicecatalog.k8s.io" -}, "watch") && (s.push(t.watch({ -group: "servicecatalog.k8s.io", -resource: "serviceinstances" -}, r.projectContext, function(e) { -r.serviceInstances = e.by("metadata.name"), u(); +})), a.SERVICE_CATALOG_ENABLED && u(p, "watch") && (l.push(r.watch(p, i.projectContext, function(e) { +i.serviceInstances = e.by("metadata.name"), h(); }, { -poll: i, +poll: c, pollInterval: 6e4 -})), t.list({ -group: "servicecatalog.k8s.io", -resource: "serviceclasses" -}, {}, function(e) { -r.serviceClasses = e.by("metadata.name"), u(); +})), r.list(m, {}, function(e) { +i.serviceClasses = e.by("metadata.name"), h(); +}), r.list(f, {}, function(e) { +o = e.by("metadata.name"); })); }; -r.$onChanges = function(e) { -e.projectContext && r.showBindings && d(); -}, r.$onDestroy = function() { -t.unwatchAll(s); +i.$onChanges = function(e) { +e.projectContext && i.showBindings && v(); +}, i.$onDestroy = function() { +r.unwatchAll(l); }; } @@ -3724,44 +3707,35 @@ _.set(r, [ n, t.metadata.name ], t); } }; }), angular.module("openshiftConsole").factory("CatalogService", [ "$filter", "APIService", "Constants", "KeywordService", function(e, t, n, a) { -var r = e("tags"), o = !n.SERVICE_CATALOG_ENABLED && t.apiInfo({ -group: "servicecatalog.k8s.io", -resource: "serviceclasses" -}) && t.apiInfo({ -group: "servicecatalog.k8s.io", -resource: "serviceinstances" -}) && t.apiInfo({ -group: "servicecatalog.k8s.io", -resource: "serviceinstancecredentials" -}), i = {}; +var r = e("tags"), o = t.getPreferredVersion("servicebindings"), i = t.getPreferredVersion("clusterserviceclasses"), s = t.getPreferredVersion("serviceinstances"), c = t.getPreferredVersion("clusterserviceplans"), l = !n.DISABLE_SERVICE_CATALOG_LANDING_PAGE && t.apiInfo(o) && t.apiInfo(i) && t.apiInfo(s) && t.apiInfo(c), u = {}; _.each(n.CATALOG_CATEGORIES, function(e) { _.each(e.items, function(e) { -i[e.id] = e; +u[e.id] = e; var t = _.get(e, "subcategories", []); _.each(t, function(e) { _.each(e.items, function(e) { -i[e.id] = e; +u[e.id] = e; }); }); }); }); -var s = function(e, t) { +var d = function(e, t) { e = e.toLowerCase(); var n; for (n = 0; n < t.length; n++) if (e === t[n].toLowerCase()) return !0; return !1; -}, c = function(e, t) { +}, m = function(e, t) { var n = _.get(e, "categoryAliases", []), a = [ e.id ].concat(n); return _.some(a, function(e) { -return s(e, t); +return d(e, t); }); -}, l = function(e) { +}, p = function(e) { return e.from && "ImageStreamTag" === e.from.kind && -1 === e.from.name.indexOf(":") && !e.from.namespace; -}, u = e("displayName"), d = [ "metadata.name", 'metadata.annotations["openshift.io/display-name"]', "metadata.annotations.description" ]; +}, f = e("displayName"), g = [ "metadata.name", 'metadata.annotations["openshift.io/display-name"]', "metadata.annotations.description" ]; return { -SERVICE_CATALOG_ENABLED: o, +SERVICE_CATALOG_ENABLED: l, getCategoryItem: function(e) { -return i[e]; +return u[e]; }, categorizeImageStreams: function(e) { var t = {}; @@ -3773,16 +3747,16 @@ var t = _.get(e, "annotations.tags"); t && (n[e.name] = t.split(/\s*,\s*/)); }); var a = !1; -_.each(i, function(r) { +_.each(u, function(r) { (function(e) { return _.some(e.status.tags, function(e) { var t = n[e.tag] || []; -return c(r, t) && s("builder", t) && !s("hidden", t); +return m(r, t) && d("builder", t) && !d("hidden", t); }); })(e) && (t[r.id] = t[r.id] || [], t[r.id].push(e), a = !0); }), a || _.some(e.status.tags, function(e) { var t = n[e.tag] || []; -return s("builder", t) && !s("hidden", t); +return d("builder", t) && !d("hidden", t); }) && (t[""] = t[""] || [], t[""].push(e)); } }), t; @@ -3791,19 +3765,19 @@ categorizeTemplates: function(e) { var t = {}; return _.each(e, function(e) { var n = r(e), a = !1; -_.each(i, function(r) { -c(r, n) && (t[r.id] = t[r.id] || [], t[r.id].push(e), a = !0); +_.each(u, function(r) { +m(r, n) && (t[r.id] = t[r.id] || [], t[r.id].push(e), a = !0); }), a || (t[""] = t[""] || [], t[""].push(e)); }), t; }, -referencesSameImageStream: l, +referencesSameImageStream: p, filterImageStreams: function(e, t) { if (!t.length) return e; var n = []; return _.each(e, function(e) { -var a = _.get(e, "metadata.name", ""), r = u(e, !0), o = [], i = {}, s = {}; +var a = _.get(e, "metadata.name", ""), r = f(e, !0), o = [], i = {}, s = {}; _.each(e.spec.tags, function(e) { -if (l(e)) return i[e.name] = e.from.name, s[e.from.name] = s[e.from.name] || [], void s[e.from.name].push(e.name); +if (p(e)) return i[e.name] = e.from.name, s[e.from.name] = s[e.from.name] || [], void s[e.from.name].push(e.name); o.push(e); }); var c = _.keyBy(o, "name"); @@ -3820,15 +3794,15 @@ a && e.test(a) || delete c[t.name]; } else delete c[t.name]; }); }); -var d; -_.isEmpty(c) || ((d = angular.copy(e)).status.tags = _.filter(d.status.tags, function(e) { +var l; +_.isEmpty(c) || ((l = angular.copy(e)).status.tags = _.filter(l.status.tags, function(e) { var t = i[e.tag]; return t ? c[t] : c[e.tag]; -}), n.push(d)); +}), n.push(l)); }), n; }, filterTemplates: function(e, t) { -return a.filterForKeywords(e, d, t); +return a.filterForKeywords(e, g, t); } }; } ]), angular.module("openshiftConsole").factory("ModalsService", [ "$uibModal", function(e) { @@ -4279,7 +4253,11 @@ controller: !0 } }; }), angular.module("openshiftConsole").factory("ServiceInstancesService", [ "$filter", "$q", "$uibModal", "APIService", "BindingService", "CatalogService", "DataService", "Logger", "NotificationsService", function(e, t, n, a, r, o, i, s, c) { -var l = function(e, n) { +var l = a.getPreferredVersion("clusterserviceclasses"), u = a.getPreferredVersion("clusterserviceplans"), d = function(e) { +return _.get(e, "spec.serviceClassRef.name"); +}, m = function(e) { +return _.get(e, "spec.servicePlanRef.name"); +}, p = function(e, n) { if (angular.isDefined(n)) return t.when(n); var o = { namespace: e.metadata.namespace @@ -4287,7 +4265,7 @@ namespace: e.metadata.namespace return i.list(s, o).then(function(t) { return n = t.by("metadata.name"), r.getBindingsForResource(n, e); }); -}, u = function(t) { +}, f = function(t) { var n = { namespace: t.metadata.namespace }, r = a.getPreferredVersion("serviceinstances"); @@ -4308,14 +4286,14 @@ message: "An error occurred while deleting provisioned service " + t.metadata.na details: e("getErrorDetails")(n) }), s("An error occurred while deleting provisioned service " + t.metadata.name + ".", n); }); -}, d = function(t, n) { +}, g = function(t, n) { if (o.SERVICE_CATALOG_ENABLED) { var r = { namespace: t.metadata.namespace -}, u = a.getPreferredVersion("serviceinstancecredentials"); -l(t, n).then(function(t) { +}, l = a.getPreferredVersion("serviceinstancecredentials"); +p(t, n).then(function(t) { _.each(t, function(t) { -t.metadata.deletionTimestamp || i.delete(u, t.metadata.name, r).then(function() { +t.metadata.deletionTimestamp || i.delete(l, t.metadata.name, r).then(function() { c.addNotification({ type: "success", message: "Binding " + t.metadata.name + "' was marked for deletion." @@ -4332,6 +4310,19 @@ details: e("getErrorDetails")(n) } }; return { +getServiceClassNameForInstance: d, +fetchServiceClassForInstance: function(e) { +var t = d(e); +return i.get(l, t, {}); +}, +getServicePlanNameForInstance: m, +fetchServicePlanForInstance: function(e) { +var t = m(e); +return i.get(u, t, {}); +}, +isCurrentPlan: function(e, t) { +return m(e) === _.get(t, "metadata.name"); +}, deprovision: function(e, t) { var a, r = { kind: e.kind, @@ -4353,7 +4344,7 @@ return r; } } })).result.then(function() { -d(e, t), u(e); +g(e, t), f(e); }); } }; @@ -4743,7 +4734,7 @@ e.state && e.state.running && t++; i.unwatchAll(p), m(), $(window).off("resize.terminalsize"); }); })); -} ]), angular.module("openshiftConsole").controller("OverviewController", [ "$scope", "$filter", "$routeParams", "AlertMessageService", "APIService", "AppsService", "BuildsService", "CatalogService", "Constants", "DataService", "DeploymentsService", "HPAService", "HTMLService", "ImageStreamResolver", "KeywordService", "LabelFilter", "Logger", "MetricsService", "Navigate", "OwnerReferencesService", "PodsService", "ProjectsService", "BindingService", "ResourceAlertsService", "RoutesService", OverviewController ]), angular.module("openshiftConsole").controller("QuotaController", [ "$filter", "$routeParams", "$scope", "DataService", "ProjectsService", "Logger", function(e, t, n, a, r, o) { +} ]), angular.module("openshiftConsole").controller("OverviewController", [ "$scope", "$filter", "$routeParams", "AlertMessageService", "APIService", "AppsService", "BindingService", "BuildsService", "CatalogService", "Constants", "DataService", "DeploymentsService", "HPAService", "HTMLService", "ImageStreamResolver", "KeywordService", "LabelFilter", "Logger", "MetricsService", "Navigate", "OwnerReferencesService", "PodsService", "ProjectsService", "ResourceAlertsService", "RoutesService", "ServiceInstancesService", OverviewController ]), angular.module("openshiftConsole").controller("QuotaController", [ "$filter", "$routeParams", "$scope", "DataService", "ProjectsService", "Logger", function(e, t, n, a, r, o) { n.projectName = t.project, n.limitRanges = {}, n.limitsByType = {}, n.labelSuggestions = {}, n.alerts = n.alerts || {}, n.quotaHelp = "Limits resource usage within this project.", n.emptyMessageLimitRanges = "Loading...", n.limitRangeHelp = "Defines minimum and maximum constraints for runtime resources such as memory and CPU.", n.renderOptions = n.renderOptions || {}, n.renderOptions.hideFilterWidget = !0; var i = [], s = e("usageValue"); n.isAtLimit = function(e, t) { @@ -6222,85 +6213,75 @@ e.serviceInstances = s.getLabelSelector().select(e.unfilteredServiceInstances); }, m = function() { e.unfilteredServiceInstances = r.sortServiceInstances(e.unfilteredServiceInstances, e.serviceClasses); }; -l.get(n.project).then(_.spread(function(t, n) { -function a() { +e.getServiceClass = function(t) { +var n = _.get(t, "spec.serviceClassRef.name"); +return _.get(e, [ "serviceClasses", n ]); +}, l.get(n.project).then(_.spread(function(t, n) { +function r() { 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: "serviceinstancecredentials" -}, n, function(t) { +e.project = t, e.projectContext = n; +var o = a.getPreferredVersion("servicebindings"); +u.push(i.watch(o, n, function(t) { var n = t.by("metadata.name"); e.bindingsByInstanceRef = _.groupBy(n, "spec.instanceRef.name"); -})), u.push(i.watch({ -group: "servicecatalog.k8s.io", -resource: "serviceinstances" -}, 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" -}, {}, function(t) { +})); +var l = a.getPreferredVersion("serviceinstances"); +u.push(i.watch(l, n, function(t) { +e.emptyMessage = "No provisioned services to show", e.unfilteredServiceInstances = t.by("metadata.name"), m(), d(), r(), s.addLabelSuggestionsFromResources(e.unfilteredServiceInstances, e.labelSuggestions), s.setLabelSuggestions(e.labelSuggestions), c.log("provisioned services (subscribe)", e.unfilteredServiceInstances); +})); +var p = a.getPreferredVersion("clusterserviceclasses"); +i.list(p, {}, function(t) { e.serviceClasses = t.by("metadata.name"), m(), d(); }), s.onActiveFiltersChanged(function(t) { e.$evalAsync(function() { -e.serviceInstances = t.select(e.unfilteredServiceInstances), a(); +e.serviceInstances = t.select(e.unfilteredServiceInstances), r(); }); }), e.$on("$destroy", function() { i.unwatchAll(u); }); })); -} ]), angular.module("openshiftConsole").controller("ServiceInstanceController", [ "$scope", "$filter", "$routeParams", "DataService", "ProjectsService", "ServiceInstancesService", function(e, t, n, a, r, o) { -e.alerts = {}, e.projectName = n.project, e.serviceInstance = null, e.serviceClass = null, e.serviceClasses = null, e.breadcrumbs = [ { +} ]), angular.module("openshiftConsole").controller("ServiceInstanceController", [ "$scope", "$filter", "$routeParams", "APIService", "DataService", "ProjectsService", "ServiceInstancesService", function(e, t, n, a, r, o, i) { +e.alerts = {}, e.projectName = n.project, e.serviceInstance = null, e.serviceClass = null, e.breadcrumbs = [ { title: "Provisioned Services", link: "project/" + n.project + "/browse/service-instances" } ], e.deprovision = function() { -o.deprovision(e.serviceInstance); +i.deprovision(e.serviceInstance); }; -var i = [], s = function() { -e.serviceInstance && e.serviceClasses && e.breadcrumbs.push({ -title: t("serviceInstanceDisplayName")(e.serviceInstance, e.serviceClasses) +var s = [], c = t("serviceInstanceDisplayName"), l = a.getPreferredVersion("serviceinstances"), u = function() { +e.breadcrumbs.push({ +title: e.displayName }); -}, c = 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: e.serviceInstance.spec.planName +}, d = function() { +e.serviceClass || i.fetchServiceClassForInstance(e.serviceInstance).then(function(t) { +e.serviceClass = t, e.displayName = c(e.serviceInstance, t), u(); }); -} -}, l = function(t, n) { +}, m = function() { +i.isCurrentPlan(e.serviceInstance, e.plan) || i.fetchServicePlanForInstance(e.serviceInstance).then(function(t) { +e.plan = t; +}); +}, p = function(t, n) { e.loaded = !0, e.serviceInstance = t, "DELETED" === n && (e.alerts.deleted = { type: "warning", message: "This provisioned service has been deleted." -}), c(); +}), d(), m(); }; -r.get(n.project).then(_.spread(function(r, o) { -e.project = r, e.projectContext = o, a.get({ -group: "servicecatalog.k8s.io", -resource: "serviceinstances" -}, n.instance, o, { +o.get(n.project).then(_.spread(function(a, o) { +e.project = a, e.projectContext = o, r.get(l, n.instance, o, { errorNotification: !1 }).then(function(e) { -l(e), s(), i.push(a.watchObject({ -group: "servicecatalog.k8s.io", -resource: "serviceinstances" -}, n.instance, o, l)); +p(e), s.push(r.watchObject(l, n.instance, o, p)); }, function(n) { e.loaded = !0, e.alerts.load = { type: "error", -message: "The service details could not be loaded.", +message: "The provisioned service details could not be loaded.", details: t("getErrorDetails")(n) }; -}), a.list({ -group: "servicecatalog.k8s.io", -resource: "serviceclasses" -}, {}, function(t) { -e.serviceClasses = t.by("metadata.name"), c(), s(); }), e.$on("$destroy", function() { -a.unwatchAll(i); +r.unwatchAll(s); }); })); } ]), angular.module("openshiftConsole").controller("SecretsController", [ "$routeParams", "$scope", "DataService", "ProjectsService", function(e, t, n, a) { @@ -10323,7 +10304,7 @@ customNameHeader: "=?" templateUrl: "views/directives/traffic-table.html" }; }), angular.module("openshiftConsole").component("resourceServiceBindings", { -controller: [ "$filter", "DataService", "BindingService", "CatalogService", ResourceServiceBindings ], +controller: [ "$filter", "APIService", "BindingService", "CatalogService", "DataService", ResourceServiceBindings ], controllerAs: "$ctrl", bindings: { project: "<", @@ -12706,95 +12687,100 @@ templateUrl: "views/directives/route-service-bar-chart.html" }); }(), function() { angular.module("openshiftConsole").component("bindService", { -controller: [ "$scope", "$filter", "ApplicationsService", "DataService", "BindingService", function(e, t, n, a, r) { -var o, i, s, c, l, u, d = this, m = t("statusCondition"), p = t("enableTechPreviewFeature"), f = function() { +controller: [ "$scope", "$filter", "APIService", "ApplicationsService", "BindingService", "DataService", "ServiceInstancesService", function(e, t, n, a, r, o, i) { +var s, c, l, u, d, m, p = this, f = t("statusCondition"), g = t("enableTechPreviewFeature"), h = function() { var e, t; -_.each(d.serviceInstances, function(n) { -var a = "True" === _.get(m(n, "Ready"), "status"); +_.each(p.serviceInstances, function(n) { +var a = "True" === _.get(f(n, "Ready"), "status"); a && (!e || n.metadata.creationTimestamp > e.metadata.creationTimestamp) && (e = n), a || t && !(n.metadata.creationTimestamp > t.metadata.creationTimestamp) || (t = n); -}), d.serviceToBind = e || t; -}, g = function() { -d.serviceClasses && d.serviceInstances && (d.serviceInstances = r.filterBindableServiceInstances(d.serviceInstances, d.serviceClasses), d.orderedServiceInstances = r.sortServiceInstances(d.serviceInstances, d.serviceClasses), d.serviceToBind || f()); -}, h = function() { +}), p.serviceToBind = e || t; +}, v = function() { +p.serviceClasses && p.serviceInstances && (p.serviceInstances = r.filterBindableServiceInstances(p.serviceInstances, p.serviceClasses, p.servicePlans), p.orderedServiceInstances = r.sortServiceInstances(p.serviceInstances, p.serviceClasses), p.serviceToBind || h()); +}, y = function() { var e = { -namespace: _.get(d.target, "metadata.namespace") +namespace: _.get(p.target, "metadata.namespace") }; -n.getApplications(e).then(function(e) { -d.applications = e, d.bindType = d.applications.length ? "application" : "secret-only"; +a.getApplications(e).then(function(e) { +p.applications = e, p.bindType = p.applications.length ? "application" : "secret-only"; }); -}, v = function() { +}, b = function() { var e = { -namespace: _.get(d.target, "metadata.namespace") -}; -a.list({ -group: "servicecatalog.k8s.io", -resource: "serviceinstances" -}, e).then(function(e) { -d.serviceInstances = e.by("metadata.name"), g(); +namespace: _.get(p.target, "metadata.namespace") +}, t = n.getPreferredVersion("serviceinstances"); +o.list(t, e).then(function(e) { +p.serviceInstances = e.by("metadata.name"), v(); }); }; -o = { +s = { id: "bindForm", label: "Binding", view: "views/directives/bind-service/bind-service-form.html", valid: !0, allowClickNav: !0, onShow: function() { -d.nextTitle = i.hidden ? "Bind" : "Next >", d.podPresets && !c && (c = e.$watch("ctrl.selectionForm.$valid", function(e) { -o.valid = e; +p.nextTitle = c.hidden ? "Bind" : "Next >", p.podPresets && !u && (u = e.$watch("ctrl.selectionForm.$valid", function(e) { +s.valid = e; })); } -}, i = { +}, c = { id: "bindParameters", label: "Parameters", view: "views/directives/bind-service/bind-parameters.html", hidden: !0, allowClickNav: !0, onShow: function() { -d.nextTitle = "Bind", l || (l = e.$watch("ctrl.parametersForm.$valid", function(e) { -i.valid = e; +p.nextTitle = "Bind", d || (d = e.$watch("ctrl.parametersForm.$valid", function(e) { +c.valid = e; })); } -}, s = { +}, l = { id: "results", label: "Results", view: "views/directives/bind-service/results.html", valid: !0, allowClickNav: !1, onShow: function() { -c && (c(), c = void 0), l && (l(), l = void 0), d.nextTitle = "Close", d.wizardComplete = !0, d.bindService(); +u && (u(), u = void 0), d && (d(), d = void 0), p.nextTitle = "Close", p.wizardComplete = !0, p.bindService(); } }; -var y = function() { -if (d.serviceClasses) { -var e = "ServiceInstance" === d.target.kind ? d.target : d.serviceToBind; -e && (d.serviceClass = d.serviceClasses[e.spec.serviceClassName], d.serviceClassName = e.spec.serviceClassName, d.plan = r.getPlanForInstance(e, d.serviceClass), d.parameterSchema = _.get(d.plan, "serviceInstanceCredentialCreateParameterSchema"), d.parameterFormDefinition = _.get(d.plan, "externalMetadata.schemas.service_binding.create.openshift_form_definition"), i.hidden = !_.has(d.parameterSchema, "properties"), d.nextTitle = i.hidden ? "Bind" : "Next >", d.hideBack = i.hidden); +var C = function() { +if (p.serviceClasses && p.servicePlans) { +var e = "ServiceInstance" === p.target.kind ? p.target : p.serviceToBind; +if (e) { +var t = i.getServiceClassNameForInstance(e); +p.serviceClass = p.serviceClasses[t]; +var n = i.getServicePlanNameForInstance(e); +p.plan = p.servicePlans[n], p.parameterSchema = _.get(p.plan, "spec.serviceInstanceCredentialCreateParameterSchema"), p.parameterFormDefinition = _.get(p.plan, "spec.externalMetadata.schemas.service_binding.create.openshift_form_definition"), c.hidden = !_.has(p.parameterSchema, "properties"), p.nextTitle = c.hidden ? "Bind" : "Next >", p.hideBack = c.hidden; +} } }; -e.$watch("ctrl.serviceToBind", y), d.$onInit = function() { -d.serviceSelection = {}, d.projectDisplayName = t("displayName")(d.project), d.podPresets = p("pod_presets"), d.parameterData = {}, d.steps = [ o, i, s ], d.hideBack = i.hidden, a.list({ -group: "servicecatalog.k8s.io", -resource: "serviceclasses" -}, {}).then(function(e) { -d.serviceClasses = e.by("metadata.name"), y(), g(); -}), "ServiceInstance" === d.target.kind ? (d.bindType = "secret-only", d.appToBind = null, d.serviceToBind = d.target, d.podPresets && h()) : (d.bindType = "application", d.appToBind = d.target, v()); -}, d.$onChanges = function(e) { -e.project && !e.project.isFirstChange() && (d.projectDisplayName = t("displayName")(d.project)); -}, d.$onDestroy = function() { -c && (c(), c = void 0), l && (l(), l = void 0), u && a.unwatch(u); -}, d.bindService = function() { -var e = "ServiceInstance" === d.target.kind ? d.target : d.serviceToBind, t = "application" === d.bindType ? d.appToBind : void 0, n = { +e.$watch("ctrl.serviceToBind", C), p.$onInit = function() { +p.serviceSelection = {}, p.projectDisplayName = t("displayName")(p.project), p.podPresets = g("pod_presets"), p.parameterData = {}, p.steps = [ s, c, l ], p.hideBack = c.hidden; +var e = n.getPreferredVersion("clusterserviceclasses"); +o.list(e, {}).then(function(e) { +p.serviceClasses = e.by("metadata.name"), C(), v(); +}); +var a = n.getPreferredVersion("clusterserviceplans"); +o.list(a, {}).then(function(e) { +p.servicePlans = e.by("metadata.name"), C(); +}), "ServiceInstance" === p.target.kind ? (p.bindType = "secret-only", p.appToBind = null, p.serviceToBind = p.target, p.podPresets && y()) : (p.bindType = "application", p.appToBind = p.target, b()); +}, p.$onChanges = function(e) { +e.project && !e.project.isFirstChange() && (p.projectDisplayName = t("displayName")(p.project)); +}, p.$onDestroy = function() { +u && (u(), u = void 0), d && (d(), d = void 0), m && o.unwatch(m); +}, p.bindService = function() { +var e = "ServiceInstance" === p.target.kind ? p.target : p.serviceToBind, t = "application" === p.bindType ? p.appToBind : void 0, n = { namespace: _.get(e, "metadata.namespace") -}, o = r.getServiceClassForInstance(e, d.serviceClasses); -r.bindService(e, t, o, d.parameterData).then(function(e) { -d.binding = e, d.error = null, u = a.watchObject(r.bindingResource, _.get(d.binding, "metadata.name"), n, function(e) { -d.binding = e; +}, a = r.getServiceClassForInstance(e, p.serviceClasses); +r.bindService(e, t, a, p.parameterData).then(function(e) { +p.binding = e, p.error = null, m = o.watchObject(r.bindingResource, _.get(p.binding, "metadata.name"), n, function(e) { +p.binding = e; }); }, function(e) { -d.error = e; +p.error = e; }); -}, d.closeWizard = function() { -_.isFunction(d.onClose) && d.onClose(); +}, p.closeWizard = function() { +_.isFunction(p.onClose) && p.onClose(); }; } ], controllerAs: "ctrl", @@ -12807,50 +12793,47 @@ templateUrl: "views/directives/bind-service.html" }); }(), function() { angular.module("openshiftConsole").component("unbindService", { -controller: [ "$scope", "$filter", "DataService", function(e, t, n) { -var a, r, o = this, i = t("enableTechPreviewFeature"), s = t("serviceInstanceDisplayName"), c = function() { -var e = o.selectedBinding.metadata.name; -o.unboundApps = o.appsForBinding(e), n.delete({ -group: "servicecatalog.k8s.io", -resource: "serviceinstancecredentials" -}, e, r, { +controller: [ "$scope", "$filter", "APIService", "DataService", function(e, t, n, a) { +var r, o, i = this, s = t("enableTechPreviewFeature"), c = t("serviceInstanceDisplayName"), l = n.getPreferredVersion("servicebindings"), u = function() { +var e = i.selectedBinding.metadata.name; +i.unboundApps = i.appsForBinding(e), a.delete(l, e, o, { propagationPolicy: null }).then(_.noop, function(e) { -o.error = e; +i.error = e; }); -}, l = function() { -var t = _.head(o.steps); -t.valid = !1, a = e.$watch("ctrl.selectedBinding", function(e) { +}, d = function() { +var t = _.head(i.steps); +t.valid = !1, r = e.$watch("ctrl.selectedBinding", function(e) { t.valid = !!e; }); -}, u = function() { -a && (a(), a = void 0); -}, d = function() { -o.nextTitle = "Delete", l(); }, m = function() { -o.nextTitle = "Close", o.wizardComplete = !0, c(), u(); +r && (r(), r = void 0); +}, p = function() { +i.nextTitle = "Delete", d(); +}, f = function() { +i.nextTitle = "Close", i.wizardComplete = !0, u(), m(); }; -o.$onInit = function() { +i.$onInit = function() { var e; -e = "ServiceInstance" === o.target.kind ? i("pod_presets") ? "Applications" : "Bindings" : "Services", o.displayName = s(o.target), o.steps = [ { +e = "ServiceInstance" === i.target.kind ? s("pod_presets") ? "Applications" : "Bindings" : "Services", i.displayName = c(i.target), i.steps = [ { id: "deleteForm", label: e, view: "views/directives/bind-service/delete-binding-select-form.html", -onShow: d +onShow: p }, { id: "results", label: "Results", view: "views/directives/bind-service/delete-binding-result.html", -onShow: m -} ], r = { -namespace: _.get(o.target, "metadata.namespace") -}; -}, o.appsForBinding = function(e) { -return _.get(o.applicationsByBinding, e); -}, o.closeWizard = function() { -_.isFunction(o.onClose) && o.onClose(); -}, o.$onDestroy = function() { -u(); +onShow: f +} ], o = { +namespace: _.get(i.target, "metadata.namespace") +}; +}, i.appsForBinding = function(e) { +return _.get(i.applicationsByBinding, e); +}, i.closeWizard = function() { +_.isFunction(i.onClose) && i.onClose(); +}, i.$onDestroy = function() { +m(); }; } ], controllerAs: "ctrl", @@ -13281,7 +13264,7 @@ angular.module("openshiftConsole").component("serviceBinding", { controller: [ function() { var e = this, t = function() { if ("ServiceInstance" !== _.get(e.refApiObject, "kind")) { -var t = _.get(e.binding, "spec.instanceRef.name"), n = _.get(e.serviceInstances, [ t ]), a = _.get(n, "spec.serviceClassName"); +var t = _.get(e.binding, "spec.instanceRef.name"), n = _.get(e.serviceInstances, [ t ]), a = _.get(n, "spec.serviceClassRef.name"); e.serviceClass = _.get(e.serviceClasses, [ a ]); } }; @@ -13646,10 +13629,16 @@ controller: [ "$filter", "AuthorizationService", "BindingService", "ListRowUtils var o = this, i = e("isBindingFailed"), s = e("isBindingReady"); _.extend(o, a.ui); var c = e("serviceInstanceDisplayName"), l = function() { +var e = r.getServiceClassNameForInstance(o.apiObject); +return _.get(o, [ "state", "serviceClasses", e ]); +}, u = function() { +var e = r.getServicePlanNameForInstance(o.apiObject); +return _.get(o, [ "state", "servicePlans", e ]); +}, d = function() { _.get(o.apiObject, "metadata.deletionTimestamp") ? o.instanceStatus = "deleted" : i(o.apiObject) ? o.instanceStatus = "failed" : s(o.apiObject) ? o.instanceStatus = "ready" : o.instanceStatus = "pending"; }; o.$doCheck = function() { -l(), o.notifications = a.getNotifications(o.apiObject, o.state), o.displayName = c(o.apiObject, o.state.serviceClasses), o.isBindable = n.isServiceBindable(o.apiObject, o.state.serviceClasses), o.serviceClass = _.get(o, [ "state", "serviceClasses", o.apiObject.spec.serviceClassName ]); +d(), o.notifications = a.getNotifications(o.apiObject, o.state), o.serviceClass = l(), o.servicePlan = u(), o.displayName = c(o.apiObject, o.serviceClass), o.isBindable = n.isServiceBindable(o.apiObject, o.serviceClass, o.servicePlan); }, o.$onChanges = function(e) { e.bindings && (o.deleteableBindings = _.reject(o.bindings, "metadata.deletionTimestamp")); }, o.getSecretForBinding = function(e) { @@ -15270,12 +15259,18 @@ return function(e) { var t = _.get(e, "spec.alternateBackends", []); return !_.isEmpty(t); }; -}).filter("serviceInstanceDisplayName", function() { -return function(e, t) { -var n = e.spec.serviceClassName, a = e.metadata.name; -return _.get(t, [ n, "externalMetadata", "displayName" ]) || n || a; +}).filter("serviceClassDisplayName", function() { +return function(e) { +var t = _.get(e, "spec.externalMetadata.displayName"); +if (t) return t; +var n = _.get(e, "spec.externalName"); +return n || _.get(e, "metadata.name"); +}; +}).filter("serviceInstanceDisplayName", [ "serviceClassDisplayNameFilter", function(e) { +return function(t, n) { +return n ? e(n) : _.get(t, "metadata.name"); }; -}).filter("serviceInstanceStatus", [ "isServiceInstanceReadyFilter", function(e) { +} ]).filter("serviceInstanceStatus", [ "isServiceInstanceReadyFilter", function(e) { return function(t) { var n = "Pending", a = _.get(t, "status.conditions"); return _.find(a, { diff --git a/dist/scripts/templates.js b/dist/scripts/templates.js index a8f1a7ede9..310c6bda99 100644 --- a/dist/scripts/templates.js +++ b/dist/scripts/templates.js @@ -3658,8 +3658,10 @@ angular.module('openshiftConsoleTemplates', []).run(['$templateCache', function( "\n" + "\n" + "
\n" + - "{{serviceInstance | serviceInstanceDisplayName:serviceClasses}}\n" + - "{{serviceInstance.metadata.name}}\n" + + "{{displayName}}\n" + + "\n" + + "{{serviceInstance.metadata.name}}\n" + + "\n" + "
\n" + "created \n" + "
\n" + @@ -3684,7 +3686,7 @@ angular.module('openshiftConsoleTemplates', []).run(['$templateCache', function( "
\n" + "
\n" + "
\n" + - "

\n" + + "

\n" + "
\n" + "
Status:
\n" + "
\n" + @@ -3695,10 +3697,10 @@ angular.module('openshiftConsoleTemplates', []).run(['$templateCache', function( "
\n" + "{{serviceInstance | serviceInstanceConditionMessage}}\n" + "
\n" + - "
Description:
\n" + + "
Description:
\n" + "
\n" + - "

\n" + - "

\n" + + "

\n" + + "

\n" + "
\n" + "
\n" + "
\n" + @@ -5563,7 +5565,7 @@ angular.module('openshiftConsoleTemplates', []).run(['$templateCache', function( "{{$ctrl.binding.metadata.name}}\n" + "\n" + "\n" + - "{{$ctrl.serviceClass.externalMetadata.displayName || $ctrl.serviceClass.metadata.name}}\n" + + "{{$ctrl.serviceClass.spec.externalMetadata.displayName || $ctrl.serviceClass.metadata.name}}\n" + "\n" + "{{$ctrl.binding.spec.instanceRef.name}}\n" + "\n" + @@ -5814,7 +5816,7 @@ angular.module('openshiftConsoleTemplates', []).run(['$templateCache', function( "\n" + "
\n" + "
\n" + - "\n" + + "\n" + "\n" + "
" ); @@ -8974,7 +8976,7 @@ angular.module('openshiftConsoleTemplates', []).run(['$templateCache', function( "\n" + "\n" + "\n" + "
\n" + - "
\n" + + "
\n" + "There are no service bindings.\n" + "
\n" + "
\n" + @@ -12428,11 +12430,11 @@ angular.module('openshiftConsoleTemplates', []).run(['$templateCache', function( "

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

\n" + - "
\n" + - "View Documentation \n" + - "Get Support \n" + + "
\n" + + "

\n" + + "
\n" + + "View Documentation \n" + + "Get Support \n" + "
\n" + "
\n" + "
\n" + @@ -13142,7 +13144,9 @@ angular.module('openshiftConsoleTemplates', []).run(['$templateCache', function( "\n" + " 0\">\n" + "\n" + - "{{serviceInstance | serviceInstanceDisplayName:serviceClasses}}\n" + + "\n" + + "{{serviceInstance | serviceInstanceDisplayName : getServiceClass(serviceInstance)}}\n" + + "\n" + "{{serviceInstance.metadata.name}}\n" + "\n" + "
\n" + diff --git a/dist/scripts/vendor.js b/dist/scripts/vendor.js index e4abe2babd..d3b6b21fac 100644 --- a/dist/scripts/vendor.js +++ b/dist/scripts/vendor.js @@ -72763,14 +72763,14 @@ maxlength: 253, description: "Name must consist of lower-case letters, numbers, periods, and hyphens. It must start and end with a letter or a number." }).constant("IS_IOS", /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream), hawtioPluginLoader.addModule("openshiftCommonUI"), angular.module("openshiftCommonUI").run([ "$templateCache", function(e) { "use strict"; -e.put("src/components/binding/bindApplicationForm.html", '
\n
\n
\n \n \n Bindings create a secret containing the necessary information for an application to use a service.\n \n
\n
\n\n \n
\n
\n
\n
\n \n
\n \n Bindings can be created later from within a project.\n \n
\n
\n
\n \n
\n \n \n \n {{serviceInstance.metadata.name}}\n \n
\n
\n

\n \n \n There are no bindable services in this project\n \n

\n
\n
\n
\n
\n'), +e.put("src/components/binding/bindApplicationForm.html", '
\n
\n
\n \n \n Bindings create a secret containing the necessary information for an application to use a service.\n \n
\n
\n\n \n
\n
\n
\n
\n \n
\n \n Bindings can be created later from within a project.\n \n
\n
\n
\n \n
\n \n \n \n {{serviceInstance.metadata.name}}\n \n
\n
\n

\n \n \n There are no bindable services in this project\n \n

\n
\n
\n
\n
\n'), e.put("src/components/binding/bindResults.html", '
\n
\n \n Pending\n
\n

\n The binding is being created.\n

\n

This may take several minutes.

\n
\n
\n
\n
\n \n Success\n
\n

\n \n {{ctrl.serviceToBind}} has been bound to\n {{ctrl.applicationToBind}} successfully.\n \n \n The binding {{ctrl.serviceToBind}} has been created successfully.\n \n

\n

\n The binding operation created the secret\n {{ctrl.binding.spec.secretName}}\n {{ctrl.binding.spec.secretName}}\n that you may need to reference in your application.\n Its data will be available to your application as environment variables.\n

\n
\n
\n
\n \n Info\n The binding secret will only be available to new pods. You will need to redeploy your application.\n
\n
\n
\n
\n
\n \n Error\n
\n

\n The binding could not be created.\n

\n
\n
\n
\n \n {{ctrl.error.data.message | upperFirst}}\n \n \n An error occurred creating the binding.\n \n
\n
\n {{ctrl.binding | bindingFailedMessage}}\n
\n
\n'), -e.put("src/components/binding/bindServiceForm.html", '
\n
\n
\n \n Bindings create a secret containing the necessary information for an application to use this service.\n
\n
\n\n
\n
\n
\n \n
\n \n \n \n {{$select.selected.metadata.name}}\n – {{$select.selected.kind | humanizeKind : true}}\n \n \n \n \n \n \n
\n \n
\n Secrets can be referenced later from an application.\n
\n \n
\n Bindings can be created later from within a project.\n
\n
\n
\n
\n
\n'), +e.put("src/components/binding/bindServiceForm.html", '
\n
\n
\n \n Bindings create a secret containing the necessary information for an application to use this service.\n
\n
\n\n
\n
\n
\n \n
\n \n \n \n {{$select.selected.metadata.name}}\n – {{$select.selected.kind | humanizeKind : true}}\n \n \n \n \n \n \n
\n \n
\n Secrets can be referenced later from an application.\n
\n \n
\n Bindings can be created later from within a project.\n
\n
\n
\n
\n
\n'), e.put("src/components/create-project/createProject.html", '
\n
\n
\n \n \n \n \n
\n A unique name for the project.\n
\n
\n \n Name is required.\n \n
\n
\n \n Name must have at least two characters.\n \n
\n
\n \n Project names may only contain lower-case letters, numbers, and dashes.\n They may not start or end with a dash.\n \n
\n
\n \n This name is already in use. Please choose a different name.\n \n
\n
\n\n
\n \n \n
\n\n
\n \n \n
\n\n
\n \n \n Cancel\n \n
\n
\n
\n'), e.put("src/components/delete-project/delete-project-button.html", '
\n \x3c!-- Avoid whitespace inside the link --\x3e\n Delete Project {{projectName}}\n
\n'), e.put("src/components/delete-project/delete-project-modal.html", '
\n \x3c!-- Use a form so that the enter key submits when typing a project name to confirm. --\x3e\n
\n \n \n
\n
\n'), e.put("src/components/delete-project/delete-project.html", '{{label || \'Delete\'}}\n'), e.put("src/components/edit-project/editProject.html", '
\n
\n
\n \n \n
\n\n
\n \n \n
\n\n
\n \n \n Cancel\n \n
\n
\n
\n'), e.put("src/components/origin-modal-popup/origin-modal-popup.html", '
\n

\n {{$ctrl.modalTitle}}\n

\n
\n \n \n \n
\n'), e.put("src/components/toast-notifications/toast-notifications.html", '
\n \n
\n \n \n {{notification.type}}\n {{notification.message}}\n
\n \n \n
\n \n {{link.label}}\n {{link.label}}\n |\n \n
\n
\n
\n'), -e.put("src/components/truncate-long-text/truncateLongText.html", '\x3c!--\n Do not remove class `truncated-content` (here or below) even though it\'s not\n styled directly in origin-web-common. `truncated-content` is used by\n origin-web-console in certain contexts.\n--\x3e\n\n\n \n \n …\n \n See All\n \n \n
\n Collapse\n \n
\n \n Collapse\n \n \n
\n
\n'); +e.put("src/components/truncate-long-text/truncateLongText.html", '\x3c!--\n Do not remove class `truncated-content` (here or below) even though it\'s not\n styled directly in origin-web-common. `truncated-content` is used by\n origin-web-console in certain contexts.\n\n highlightKeywords and linkify are mutually exclusive options\n--\x3e\n\n \n \n\n\x3c!-- To avoid truncating in middle of a link, we only optionally apply linkify to expanded content --\x3e\n\n \n \n …\n \n See All\n \n \n Collapse\n \n \n \n\n'); } ]), angular.module("openshiftCommonUI").component("bindApplicationForm", { controllerAs: "ctrl", bindings: { @@ -72808,7 +72808,6 @@ templateUrl: "src/components/binding/bindResults.html" controllerAs: "ctrl", bindings: { serviceClass: "<", -serviceClassName: "<", showPodPresets: "<", applications: "<", formName: "=", @@ -73139,7 +73138,7 @@ useWordBoundary: "=", expandable: "=", hideCollapse: "=", keywords: "=highlightKeywords", -prettifyJson: "=" +linkify: "=?" }, templateUrl: "src/components/truncate-long-text/truncateLongText.html", link: function(t) { @@ -73180,6 +73179,14 @@ configmaps: { version: "v1", resource: "configmaps" }, +clusterserviceclasses: { +group: "servicecatalog.k8s.io", +resource: "serviceclasses" +}, +clusterserviceplans: { +group: "servicecatalog.k8s.io", +resource: "serviceplans" +}, deployments: { group: "apps", version: "v1beta1", @@ -73280,11 +73287,7 @@ serviceaccounts: { version: "v1", resource: "serviceaccounts" }, -serviceclasses: { -group: "servicecatalog.k8s.io", -resource: "serviceclasses" -}, -serviceinstancecredentials: { +servicebindings: { group: "servicecatalog.k8s.io", resource: "serviceinstancecredentials" }, @@ -73449,7 +73452,21 @@ return _.isRegExp(e) ? e.source : _.escapeRegExp(e); }).join("|"), a = "", s = 0, l = i ? "g" : "ig", c = new RegExp(o, l); null !== (r = c.exec(t)); ) s < r.index && (a += _.escape(t.substring(s, r.index))), a += "" + _.escape(r[0]) + "", s = c.lastIndex; return s < t.length && (a += _.escape(t.substring(s))), a; }; -} ]), angular.module("openshiftCommonUI").filter("linkify", [ "HTMLService", function(e) { +} ]), angular.module("openshiftCommonUI").filter("imageForIconClass", [ "isAbsoluteURLFilter", function(e) { +return function(t) { +if (!t) return ""; +var n = _.get(window, [ "OPENSHIFT_CONSTANTS", "LOGOS", t ]); +if (!n) return ""; +var i = _.get(window, "OPENSHIFT_CONSTANTS.LOGO_BASE_URL"); +return !i || e(n) ? n : (i.endsWith("/") || (i += "/"), i + n); +}; +} ]), angular.module("openshiftCommonUI").filter("isAbsoluteURL", function() { +return function(e) { +if (!e) return !1; +var t = new URI(e), n = t.protocol(); +return t.is("absolute") && ("http" === n || "https" === n); +}; +}), angular.module("openshiftCommonUI").filter("linkify", [ "HTMLService", function(e) { return function(t, n, i) { return e.linkify(t, n, i); }; @@ -73519,6 +73536,7 @@ return e && e.metadata && e.metadata.labels ? e.metadata.labels[t] : null; }).filter("humanizeKind", [ "startCaseFilter", function(e) { return function(e, t) { if (!e) return e; +if ("ServiceInstance" === e) return t ? "Provisioned Service" : "provisioned service"; var n = _.startCase(e); return t ? n : n.toLowerCase(); }; @@ -74027,25 +74045,14 @@ return e; } } }; -}), angular.module("openshiftCommonServices").service("BindingService", [ "$filter", "$q", "AuthService", "DataService", "DNS1123_SUBDOMAIN_VALIDATION", function(e, t, n, i, r) { -var o = { -group: "servicecatalog.k8s.io", -resource: "serviceinstancecredentials" -}, a = function(e, t) { -var n = _.get(e, "spec.serviceClassName"); -return _.get(t, [ n ]); -}, s = function(e, t) { -var n = _.get(e, "spec.planName"); -return _.find(t.plans, { -name: n -}); -}, l = e("generateName"), c = function(e) { +}), angular.module("openshiftCommonServices").service("BindingService", [ "$filter", "$q", "APIService", "AuthService", "DataService", "DNS1123_SUBDOMAIN_VALIDATION", function(e, t, n, i, r, o) { +var a = n.getPreferredVersion("servicebindings"), s = e("generateName"), l = function(e) { var t = _.truncate(e, { -length: r.maxlength - 5 - 1, +length: o.maxlength - 5 - 1, omission: "" }); -return l(t, 5); -}, u = function(e, t, n) { +return s(t, 5); +}, c = function(e, t, n) { var i = { apiVersion: "v1", kind: "Secret", @@ -74064,8 +74071,8 @@ type: "Opaque", stringData: {} }; return i.stringData.parameters = JSON.stringify(t), i; -}, d = function(e, t, n) { -var n, i = e.metadata.name, r = c(e.metadata.name + "-credentials-"), o = { +}, u = function(e, t, n) { +var i = e.metadata.name, r = l(e.metadata.name + "-credentials-"), o = { kind: "ServiceInstanceCredential", apiVersion: "servicecatalog.k8s.io/v1alpha1", metadata: { @@ -74091,14 +74098,13 @@ matchLabels: a name: r, selector: a }), o; -}, h = function(t, n) { +}, d = function(t, n, i) { +if (!t || !n || !i) return !1; if (_.get(t, "metadata.deletionTimestamp")) return !1; if (e("isServiceInstanceFailed")(t, "Failed")) return !1; -var i = a(t, n); -if (!i) return !!t; -var r = s(t, i), o = _.get(r, "bindable"); -return !0 === o || !1 !== o && i.bindable; -}, f = function(e) { +var r = _.get(i, "spec.bindable"); +return !0 === r || !1 !== r && n.spec.bindable; +}, h = function(e) { var t = {}; return _.each(e, function(e) { var n = _.get(e, "spec.alphaPodPresetTemplate.selector"); @@ -74106,39 +74112,44 @@ n && (t[e.metadata.name] = new LabelSelector(n)); }), t; }; return { -bindingResource: o, -getServiceClassForInstance: a, -getPlanForInstance: s, -bindService: function(e, t, n, r) { -var a; -_.isEmpty(r) || (a = c(e.metadata.name + "-bind-parameters-")); -var s = d(e, t, a), l = { +bindingResource: a, +getServiceClassForInstance: function(e, t) { +if (!t) return null; +var n = _.get(e, "spec.serviceClassRef.name"); +return n ? t[n] : null; +}, +bindService: function(e, t, n, i) { +var o; +_.isEmpty(i) || (o = l(e.metadata.name + "-bind-parameters-")); +var s = u(e, t, o), d = { namespace: e.metadata.namespace -}, h = i.create(o, null, s, l); -return a ? h.then(function(e) { -var t = u(a, r, e); -return i.create("secrets", null, t, l).then(function() { +}, h = r.create(a, null, s, d); +return o ? h.then(function(e) { +var t = c(o, i, e); +return r.create("secrets", null, t, d).then(function() { return e; }); }) : h; }, -isServiceBindable: h, -getPodPresetSelectorsForBindings: f, +isServiceBindable: d, +getPodPresetSelectorsForBindings: h, getBindingsForResource: function(e, t) { if ("ServiceInstance" === _.get(t, "kind")) return _.filter(e, [ "spec.instanceRef.name", _.get(t, "metadata.name") ]); -var n = f(e), i = new LabelSelector(_.get(t, "spec.selector")), r = []; +var n = h(e), i = new LabelSelector(_.get(t, "spec.selector")), r = []; return _.each(n, function(t, n) { t.covers(i) && r.push(e[n]); }), r; }, -filterBindableServiceInstances: function(e, t) { -return e || t ? _.filter(e, function(e) { -return h(e, t); +filterBindableServiceInstances: function(e, t, n) { +return e && t && n ? _.filter(e, function(e) { +var i = _.get(e, "spec.serviceClassRef.name"), r = _.get(e, "spec.servicePlanRef.name"); +return d(e, t[i], n[r]); }) : null; }, sortServiceInstances: function(e, t) { return e || t ? _.sortBy(e, function(e) { -return _.get(t, [ e.spec.serviceClassName, "externalMetadata", "displayName" ]) || e.spec.serviceClassName; +var n = _.get(e, "spec.serviceClassRef.name"); +return _.get(t, [ n, "spec", "externalMetadata", "displayName" ]) || e.spec.externalServiceClassName; }, function(e) { return _.get(e, "metadata.name", ""); }) : null; @@ -77267,19 +77278,19 @@ e.exports = '
\n \n \n \x3c!-- Wait until users leave the field to avoid flashing errors as they type. --\x3e\n
\n
\n \n Application name is required.\n \n
\n
\n \n Application name consists of lower-case letters, numbers, and dashes. It must start with a letter and can\'t end with a -.\n \n
\n
\n \n Application name must be at least 2 characters.\n \n
\n
\n \n Application name can\'t be more than 24 characters.\n \n
\n
\n
\n
\n\n
\n \n
\n \n \n
\n \n Git repository is required.\n \n
\n
\n \n This might not be a valid Git URL. Check that it is the correct URL to a remote Git repository.\n \n
\n
\n
\n\n \x3c!--\n Only show the link for existing projects. It will be broken for new\n projects. Use class `invisible` when the project list is still loading\n so the dialog doesn\'t resize.\n --\x3e\n
\n If you have a private Git repository or need to change application defaults, view\n advanced options.\n
\n \n
\n
\n'; }, function(e, t) { -e.exports = '
\n
\n
\n \n
\n
\n
\n {{$ctrl.imageStream.name}}\n {{$ctrl.istag.name}}\n
\n
\n \n {{tag}}\n \n
\n
\n
\n
\n

\n

\n Sample Repository:\n \x3c!-- TODO: Use Git link filter, needs to be added to origin-web-common --\x3e\n \n

\n
\n
\n'; +e.exports = '
\n
\n
\n \n \n
\n
\n
\n {{$ctrl.imageStream.name}}\n {{$ctrl.istag.name}}\n
\n
\n \n {{tag}}\n \n
\n
\n
\n
\n

\n

\n Sample Repository:\n \x3c!-- TODO: Use Git link filter, needs to be added to origin-web-common --\x3e\n \n

\n
\n
\n'; }, function(e, t) { e.exports = '
\n
\n
\n \n Pending\n
\n

\n {{$ctrl.name}} is being created in {{$ctrl.selectedProject | displayName}}.\n

\n
\n
\n
\n
\n
\n \n Success\n
\n

\n {{$ctrl.name}} has been created in {{$ctrl.selectedProject | displayName}} successfully.\n

\n
\n
\n
\n
\n \n \n
\n
\n

\n Continue to the project overview to check the status of your application as it builds and deploys.\n

\n
\n
\n
\n \n
\n

\n {{$ctrl.name}} failed to create in {{$ctrl.selectedProject | displayName}}.\n

\n
\n
\n
\n \n {{$ctrl.error.data.message | upperFirst}}\n \n \n An error occurred creating the application.\n \n
\n \x3c!-- TODO: Improve error message presentation --\x3e\n
    \n
  • \n {{failure.data.message}}\n
  • \n
\n
\n
\n'; }, function(e, t) { -e.exports = '
\n
\n
\n \n \n \n
\n
\n'; +e.exports = '
\n
\n
\n \n \n \n
\n
\n'; }, function(e, t) { -e.exports = '
\n \n \n
\n'; +e.exports = '
\n \n \n
\n'; }, function(e, t) { e.exports = '
\n
\n
\n \n \n \n \n
\n {{$ctrl.error}}\n
\n
\n
\n'; }, function(e, t) { -e.exports = '
\n
\n
\n \n \n
\n
\n
\n {{$ctrl.serviceName}}\n
\n
\n \n {{tag}}\n \n
\n \n
\n
\n
\n

\n \n Plan {{$ctrl.selectedPlan.externalMetadata.displayName}}\n \n \n {{$ctrl.selectedPlan.description}}\n

\n

\n

\n
\n
\n'; +e.exports = '
\n
\n
\n \n \n
\n
\n
\n {{$ctrl.serviceName}}\n
\n
\n \n {{tag}}\n \n
\n \n
\n
\n
\n

\n \n Plan {{$ctrl.selectedPlan.spec.externalMetadata.displayName}}\n \n \n {{$ctrl.selectedPlan.spec.description}}\n

\n

\n

\n
\n
\n'; }, function(e, t) { -e.exports = '
\n
\n
\n

Select a Plan

\n
\n \n
\n
\n
\n
\n'; +e.exports = '
\n
\n
\n

Select a Plan

\n
\n \n
\n
\n
\n
\n'; }, function(e, t) { e.exports = '
\n
\n
\n
\n \n Pending\n
\n

\n {{$ctrl.serviceClass.name}} is being provisioned in {{$ctrl.projectDisplayName}}.\n

\n

\n The binding will be created after the service has been provisioned.\n This may take several minutes.\n

\n
\n
\n

Continue to the project overview to check the status of your service.

\n
\n
\n
\n
\n \n Error\n
\n

\n {{$ctrl.serviceClass.name}} failed to provision in {{$ctrl.projectDisplayName}}.\n

\n
\n
\n
\n \n {{$ctrl.error.message}}\n \n \n An error occurred provisioning the service.\n \n
\n
\n
\n
\n \n Success\n
\n

\n {{$ctrl.serviceClass.name}} has been added to {{$ctrl.projectDisplayName}} successfully.\n

\n
\n
\n
\n
\n \n \n

Continue to the project overview.

\n
\n
\n

Continue to the project overview to bind this service to your application. Binding this service creates a secret containing the information necessary for your application to use the service.

\n
\n
\n

- or -

\n

Browse resources for {{$ctrl.serviceClass.name}}:

\n \n
\n
\n'; }, function(e, t) { @@ -77369,6 +77380,7 @@ t.orderService = { bindings: { baseProjectUrl: "@", serviceClass: "<", +servicePlans: "<", handleClose: "<" }, controller: i.OrderServiceController, @@ -77437,6 +77449,7 @@ t.servicesView = { bindings: { baseProjectUrl: "@", catalogItems: "<", +servicePlans: "<", onDeployImageSelected: "<", onFromFileSelected: "<", onCreateFromProject: "<" @@ -77489,42 +77502,42 @@ subCategories: [ { id: "java", label: "Java", tags: [ "java" ], -icon: "font-icon icon-openjdk" +icon: "icon-openjdk" }, { id: "javascript", tags: [ "javascript", "nodejs", "js" ], label: "JavaScript", -icon: "font-icon icon-js" +icon: "icon-js" }, { id: "dotnet", label: ".NET", tags: [ "dotnet" ], -icon: "font-icon icon-dotnet" +icon: "icon-dotnet" }, { id: "perl", label: "Perl", tags: [ "perl" ], -icon: "font-icon icon-perl" +icon: "icon-perl" }, { id: "ruby", label: "Ruby", tags: [ "ruby" ], -icon: "font-icon icon-ruby" +icon: "icon-ruby" }, { id: "php", label: "PHP", tags: [ "php" ], -icon: "font-icon icon-php" +icon: "icon-php" }, { id: "python", label: "Python", tags: [ "python" ], -icon: "font-icon icon-python" +icon: "icon-python" }, { id: "golang", label: "Go", tags: [ "golang", "go" ], -icon: "font-icon icon-go-gopher" +icon: "icon-go-gopher" } ] }, { id: "databases", @@ -77533,71 +77546,42 @@ subCategories: [ { id: "mongodb", label: "Mongo", tags: [ "mongodb" ], -icon: "font-icon icon-mongodb" +icon: "icon-mongodb" }, { id: "mysql", label: "mySQL", tags: [ "mysql" ], -icon: "font-icon icon-mysql-database" +icon: "icon-mysql-database" }, { id: "postgresql", label: "Postgres", tags: [ "postgresql" ], -icon: "font-icon icon-postgresql" +icon: "icon-postgresql" }, { id: "mariadb", label: "MariaDB", tags: [ "mariadb" ], -icon: "font-icon icon-mariadb" +icon: "icon-mariadb" } ] }, { id: "middleware", label: "Middleware", subCategories: [ { -id: "amq", -label: "A-MQ", -tags: [ "amq" ], -icon: "font-icon icon-jboss" -}, { -id: "processserver", -label: "BPM Suite", -tags: [ "processserver" ], -icon: "font-icon icon-jboss" -}, { -id: "decisionserver", -label: "BRMS", -tags: [ "decisionserver" ], -icon: "font-icon icon-jboss" +id: "integration", +label: "Integration", +tags: [ "amq", "fuse", "jboss-fuse", "sso" ] }, { -id: "datagrid", -label: "Data Grid", -tags: [ "datagrid" ], -icon: "font-icon icon-jboss" +id: "process-automation", +label: "Process Automation", +tags: [ "decisionserver", "processserver" ] }, { -id: "datavirt", -label: "Data Virt", -tags: [ "datavirt" ], -icon: "font-icon icon-jboss" +id: "analytics-data", +label: "Analytics & Data", +tags: [ "datagrid", "datavirt" ] }, { -id: "eap", -label: "EAP", -tags: [ "eap" ], -icon: "font-icon icon-jboss" -}, { -id: "fuse", -label: "Fuse", -tags: [ "fuse", "jboss-fuse" ], -icon: "font-icon icon-jboss" -}, { -id: "tomcat", -label: "Tomcat", -tags: [ "tomcat" ], -icon: "font-icon icon-jboss" -}, { -id: "sso", -label: "SSO", -tags: [ "sso" ], -icon: "font-icon icon-jboss" +id: "runtimes", +label: "Runtimes & Frameworks", +tags: [ "eap", "httpd", "tomcat" ] } ] }, { id: "cicd", @@ -77606,7 +77590,7 @@ subCategories: [ { id: "jenkins", label: "Jenkins", tags: [ "jenkins" ], -icon: "font-icon icon-jenkins" +icon: "icon-jenkins" }, { id: "pipelines", label: "Pipelines", @@ -77909,17 +77893,16 @@ function e(e, t, n, i, r, o) { this.vendors = [], this.$filter = e, this.$q = t, this.constants = n, this.apiService = i, this.dataService = r, this.logger = o; } return e.prototype.getCatalogItems = function(e) { -var t = this, n = this.$q.defer(), i = {}, r = 0, o = 0, a = [], s = { -group: "servicecatalog.k8s.io", -resource: "serviceclasses" -}; -return this.apiService.apiInfo(s) && (++r, this.dataService.list(s, {}).then(function(e) { +var t = this, n = this.$q.defer(), i = {}, r = 0, o = 0, a = [], s = this.apiService.getPreferredVersion("clusterserviceclasses"); +this.apiService.apiInfo(s) && (++r, this.dataService.list(s, {}).then(function(e) { i.serviceClasses = e.by("metadata.name"); }, function() { a.push("service classes"); }).finally(function() { t.returnCatalogItems(n, i, ++o, r, a); -})), ++r, this.dataService.list("imagestreams", { +})), ++r; +var l = this.apiService.getPreferredVersion("imagestreams"); +if (this.dataService.list(l, { namespace: "openshift" }).then(function(e) { i.imageStreams = e.by("metadata.name"); @@ -77927,7 +77910,10 @@ i.imageStreams = e.by("metadata.name"); a.push("builder images"); }).finally(function() { t.returnCatalogItems(n, i, ++o, r, a); -}), e && (++r, this.dataService.list("templates", { +}), e) { +++r; +var c = this.apiService.getPreferredVersion("templates"); +this.dataService.list(c, { namespace: "openshift" }, null, { partialObjectMetadataList: !0 @@ -77937,7 +77923,14 @@ i.templates = e.by("metadata.name"); a.push("templates"); }).finally(function() { t.returnCatalogItems(n, i, ++o, r, a); -})), n.promise; +}); +} +return n.promise; +}, e.prototype.getServicePlans = function() { +var e = this.apiService.getPreferredVersion("clusterserviceplans"); +return this.apiService.apiInfo(e) ? this.dataService.list(e, {}) : this.$q.when(null); +}, e.prototype.groupPlansByServiceClassName = function(e) { +return r.groupBy(e, "spec.serviceClassRef.name"); }, e.prototype.getProjectCatalogItems = function(e, t, n, i) { var r = this; void 0 === t && (t = !0), void 0 === n && (n = !0), void 0 === i && (i = !1); @@ -77993,6 +77986,8 @@ return t.builderSpecTagName ? t : null; return new l(e, this); }, e.prototype.getPublisherSynonym = function(e) { return r.get(this.constants, [ "PUBLISHER_SYNONYMS", e ]) || e; +}, e.prototype.getImageForIconClass = function(e) { +return this.$filter("imageForIconClass")(e); }, e.prototype.categorizeItems = function(e) { var t, n, o = this; this.categories = i.copy(this.constants.SERVICE_CATALOG_CATEGORIES), this.createAllAndOtherMainCategories(); @@ -78064,27 +78059,30 @@ function e(e, t) { this.resource = e, this.catalogSrv = t, this.imageUrl = this.getImage(), this.iconClass = this.getIcon(), this.name = this.getName(), this.description = this.getDescription(), this.longDescription = this.getLongDescription(), this.tags = this.getTags(), this.kind = "ServiceClass", this.vendor = this.getVendor(); } return e.prototype.getImage = function() { -return r.get(this.resource, "externalMetadata.imageUrl") || ""; +var e = r.get(this.resource, "spec.externalMetadata.imageUrl"); +if (e) return e; +var t = r.get(this.resource, [ "spec", "externalMetadata", "console.openshift.io/iconClass" ]); +return this.catalogSrv.getImageForIconClass(t); }, e.prototype.getIcon = function() { -var e = r.get(this.resource, [ "externalMetadata", "console.openshift.io/iconClass" ]) || "fa fa-clone"; +var e = r.get(this.resource, [ "spec", "externalMetadata", "console.openshift.io/iconClass" ]) || "fa fa-clone"; return e = -1 !== e.indexOf("icon-") ? "font-icon " + e : e; }, e.prototype.getName = function() { -return r.get(this.resource, "externalMetadata.displayName") || this.resource.metadata.name; +return r.get(this.resource, "spec.externalMetadata.displayName") || this.resource.metadata.name; }, e.prototype.getDescription = function() { return r.get(this.resource, "description") || ""; }, e.prototype.getLongDescription = function() { -return r.get(this.resource, "externalMetadata.longDescription") || ""; +return r.get(this.resource, "spec.externalMetadata.longDescription") || ""; }, e.prototype.getTags = function() { -return r.get(this.resource, "tags") || []; +return r.get(this.resource, "spec.tags") || []; }, e.prototype.getVendor = function() { -var e = r.get(this.resource, "externalMetadata.providerDisplayName"); +var e = r.get(this.resource, "spec.externalMetadata.providerDisplayName"); return this.catalogSrv.getPublisherSynonym(e); }, e; }(); t.ServiceItem = a; var s = function() { function e(e, t) { -this.resource = e, this.catalogSrv = t, this.builderSpecTagName = this.getBuilderSpecTagName(), this.builderSpecTagName && (this.tags = this.getTags(), this.iconClass = this.getIcon(), this.name = this.getName(), this.description = this.getDescription(), this.longDescription = this.getLongDescription(), this.kind = "ImageStream", this.vendor = this.getVendor()); +this.resource = e, this.catalogSrv = t, this.builderSpecTagName = this.getBuilderSpecTagName(), this.builderSpecTagName && (this.tags = this.getTags(), this.imageUrl = this.getImage(), this.iconClass = this.getIcon(), this.name = this.getName(), this.description = this.getDescription(), this.longDescription = this.getLongDescription(), this.kind = "ImageStream", this.vendor = this.getVendor()); } return e.prototype.getBuilderSpecTagName = function() { var e, t = this; @@ -78096,6 +78094,9 @@ return t.tag === e.name; })), e ? e.name : null) : null; }, e.prototype.getTags = function() { return this.catalogSrv.$filter("imageStreamTagTags")(this.resource, this.builderSpecTagName); +}, e.prototype.getImage = function() { +var e = this.catalogSrv.$filter("imageStreamTagIconClass")(this.resource, this.builderSpecTagName); +return this.catalogSrv.getImageForIconClass(e); }, e.prototype.getIcon = function() { var e = this.catalogSrv.$filter("imageStreamTagIconClass")(this.resource, this.builderSpecTagName); return e = -1 !== e.indexOf("icon-") ? "font-icon " + e : e; @@ -78116,7 +78117,8 @@ function e(e, t) { this.resource = e, this.catalogSrv = t, this.imageUrl = this.getImage(), this.iconClass = this.getIcon(), this.name = this.getName(), this.description = this.getDescription(), this.longDescription = this.getLongDescription(), this.tags = this.getTags(), this.kind = "Template", this.vendor = this.getVendor(); } return e.prototype.getImage = function() { -return ""; +var e = r.get(this.resource, "metadata.annotations.iconClass"); +return this.catalogSrv.getImageForIconClass(e); }, e.prototype.getIcon = function() { var e = r.get(this.resource, "metadata.annotations.iconClass", "fa fa-clone"); return e = -1 !== e.indexOf("icon-") ? "font-icon " + e : e; @@ -78163,7 +78165,7 @@ e.exports = '\n'; }, function(e, t) { -e.exports = '
\n
\n \n \n \n \n \n \n
\n
\n
\n
\n
\n
\n
\n
\n'; +e.exports = '
\n
\n \n \n \n \n \n \n
\n
\n
\n
\n
\n
\n
\n
\n'; }, function(e, t) { e.exports = '
\n \n \n
\n
\n
\n
\n \n
\n'; }, function(e, t) { @@ -78175,7 +78177,7 @@ e.exports = '\n
\n \n \n \n {{$select.selected | displayName}}\n \n \x3c!-- refresh-delay must be set using ng-attr-refresh-delay to work as a dynamic value --\x3e\n \n \n \n \n \n \n \n \n
\n \n You are not authorized to add to this project.\n \n
\n
\n \n Please select or create a project.\n \n
\n
\n\n\n\n
\n \n
\n \n
A unique name for the project.
\n
\n \n Name must have at least two characters.\n \n
\n
\n \n Project names may only contain lower-case letters, numbers, and dashes.\n They may not start or end with a dash.\n \n
\n
\n \n This name is already in use. Please choose a different name.\n \n
\n
\n
\n\n
\n \n \n
\n\n
\n \n \n
\n
\n'; }, function(e, t) { -e.exports = '
\n
\n
\n
\n
\n
\n

Browse Catalog

\n
\n \n \n
\n
\n \n\n
\n \x3c!-- Do not show sub-category items for \'All\' or \'Other\' main categories --\x3e\n \n\n \x3c!-- Show catalog item for \'All\' and \'Other\' main categories --\x3e\n
\n
\n
There are no catalog items.
\n \n \n \n
\n \n
\n
\n \n
\n
\n {{item.name}}\n
\n
\n
\n
\n
\n
\n
\n'; +e.exports = '
\n
\n
\n
\n
\n
\n

Browse Catalog

\n
\n \n \n
\n
\n \n\n
\n \x3c!-- Do not show sub-category items for \'All\' or \'Other\' main categories --\x3e\n \n\n \x3c!-- Show catalog item for \'All\' and \'Other\' main categories --\x3e\n
\n
\n
There are no catalog items.
\n \n \n \n
\n \n
\n
\n \n
\n
\n {{item.name}}\n
\n
\n
\n
\n
\n
\n
\n'; }, function(e, t, n) { "use strict"; t.__esModule = !0; @@ -78371,10 +78373,10 @@ h.clearValidityWatcher(), h.ctrl.nextTitle = "Create", h.reviewStep.allowed = !0 }, this.showResults = function() { h.clearValidityWatcher(), h.ctrl.nextTitle = "Close", h.ctrl.wizardDone = !0, h.createApp(); }, this.onProjectUpdate = function() { -!h.instancesSupported || h.isNewProject() ? (h.ctrl.serviceInstances = [], h.updateBindability()) : h.ctrl.showPodPresets && (h.ctrl.updating = !0, h.DataService.list({ -group: "servicecatalog.k8s.io", -resource: "serviceinstances" -}, { +if (!h.instancesSupported || h.isNewProject()) h.ctrl.serviceInstances = [], h.updateBindability(); else if (h.ctrl.showPodPresets) { +h.ctrl.updating = !0; +var e = h.APIService.getPreferredVersion("serviceinstances"); +h.DataService.list(e, { namespace: h.ctrl.selectedProject.metadata.name }, null, { errorNotification: !1 @@ -78382,9 +78384,11 @@ errorNotification: !1 h.ctrl.serviceInstances = r.filter(r.toArray(e.by("metadata.name")), h.isServiceBindable), h.sortServiceInstances(), h.ctrl.updating = !1, h.updateBindability(); }, function(e) { h.Logger.warn("Failed to list instances in namespace " + h.ctrl.selectedProject.metadata.name, e), h.ctrl.updating = !1, h.ctrl.serviceInstances = [], h.updateBindability(); -})); +}); +} }, this.isServiceBindable = function(e) { -return h.BindingService.isServiceBindable(e, h.ctrl.serviceClasses); +var t, n = h.BindingService.getServiceClassForInstance(e, h.ctrl.serviceClasses), i = r.get(e, "spec.servicePlanRef.name"); +return i && (t = h.ctrl.servicePlans[i]), h.BindingService.isServiceBindable(e, n, t); }, this.$scope = e, this.$filter = t, this.$location = n, this.$q = i, this.BuilderAppService = o, this.ProjectsService = a, this.DataService = s, this.APIService = l, this.BindingService = c, this.Logger = u, this.ctrl.serviceToBind = null, this.ctrl.showPodPresets = r.get(d, [ "ENABLE_TECH_PREVIEW_FEATURE", "pod_presets" ], !1); } return e.prototype.$onInit = function() { @@ -78428,10 +78432,7 @@ allowClickNav: !1, onShow: this.showResults }, this.ctrl.steps = [ this.infoStep, this.configStep, this.bindStep, this.reviewStep ], this.ctrl.versions = this.getVersions(), this.ctrl.istag = r.head(this.ctrl.versions), this.ctrl.nameMaxLength = 24, this.ctrl.namePattern = /^[a-z]([-a-z0-9]*[a-z0-9])?$/, this.ctrl.repositoryPattern = /^[a-z][a-z0-9+.-@]*:(\/\/)?[0-9a-z_-]+/, this.ctrl.wizardDone = !1, this.ctrl.serviceToBind = null, this.ctrl.updating = !1, this.ctrl.serviceInstances = [], this.selectedProjectWatch = this.$scope.$watch(function() { return e.ctrl.selectedProject; -}, this.onProjectUpdate), this.getServiceClasses(), this.instancesSupported = !!this.APIService.apiInfo({ -group: "servicecatalog.k8s.io", -resource: "serviceinstances" -}); +}, this.onProjectUpdate), this.getServiceClassesAndPlans(), this.instancesSupported = !!this.APIService.apiInfo(this.APIService.getPreferredVersion("serviceinstances")); }, e.prototype.closePanel = function() { i.isFunction(this.ctrl.handleClose) && this.ctrl.handleClose(); }, e.prototype.$onDestroy = function() { @@ -78534,16 +78535,19 @@ t.ctrl.binding = e; }, function(e) { t.ctrl.bindComplete = !0, t.ctrl.bindError = e; }); -}, e.prototype.getServiceClasses = function() { -var e = this, t = { -group: "servicecatalog.k8s.io", -resource: "serviceclasses" -}; -this.APIService.apiInfo(t) && (this.ctrl.updating = !1, this.DataService.list(t, {}).then(function(t) { +}, e.prototype.getServiceClassesAndPlans = function() { +var e = this, t = this.APIService.getPreferredVersion("clusterserviceclasses"), n = this.APIService.getPreferredVersion("clusterserviceplans"); +if (this.APIService.apiInfo(t) && this.APIService.apiInfo(n)) { +this.ctrl.updating = !0; +var i = []; +i.push(this.DataService.list(t, {}).then(function(t) { e.ctrl.serviceClasses = t.by("metadata.name"); -}).finally(function() { +})), i.push(this.DataService.list(n, {}).then(function(t) { +e.ctrl.servicePlans = t.by("metadata.name"); +})), this.$q.all(i).finally(function() { e.ctrl.updating = !1; -})); +}); +} }, e; }(); a.$inject = [ "$scope", "$filter", "$location", "$q", "BuilderAppService", "ProjectsService", "DataService", "APIService", "BindingService", "Logger", "Constants" ], t.CreateFromBuilderController = a; @@ -78551,16 +78555,18 @@ a.$inject = [ "$scope", "$filter", "$location", "$q", "BuilderAppService", "Proj "use strict"; t.__esModule = !0; var i = function() { -function e(e, t) { -var n = this; +function e(e, t, n) { +var i = this; this.ctrl = this, this.closeOrderingPanel = function() { -n.RecentlyViewed.addItem(n.ctrl.selectedItem.resource.metadata.uid), n.ctrl.orderingPanelVisible = !1; -}, this.$scope = e, this.RecentlyViewed = t; +i.RecentlyViewed.addItem(i.ctrl.selectedItem.resource.metadata.uid), i.ctrl.orderingPanelVisible = !1; +}, this.$scope = e, this.Catalog = t, this.RecentlyViewed = n, this.plansByServiceClassName = {}; } return e.prototype.$onInit = function() { var e = this; -this.ctrl.searchText = "", this.ctrl.orderingPanelVisible = !1, this.$scope.$on("open-overlay-panel", function(t, n) { -if ("Template" !== n.kind) e.ctrl.selectedItem = n, e.ctrl.orderingPanelVisible = !0; else { +this.ctrl.searchText = "", this.ctrl.orderingPanelVisible = !1, this.Catalog.getServicePlans().then(function(t) { +t && (t = t.by("metadata.name"), e.plansByServiceClassName = e.Catalog.groupPlansByServiceClassName(t)); +}), this.$scope.$on("open-overlay-panel", function(t, n) { +if (e.ctrl.servicePlansForItem = null, "Template" !== n.kind) "ServiceClass" === n.kind && (e.ctrl.servicePlansForItem = e.plansByServiceClassName[n.resource.metadata.name]), e.ctrl.selectedItem = n, e.ctrl.orderingPanelVisible = !0; else { var i = e.ctrl.onTemplateSelected(); i && i(n.resource); } @@ -78569,7 +78575,7 @@ i && i(n.resource); this.ctrl.orderingPanelVisible && this.closeOrderingPanel(); }, e; }(); -i.$inject = [ "$scope", "RecentlyViewedServiceItems" ], t.LandingPageController = i; +i.$inject = [ "$scope", "Catalog", "RecentlyViewedServiceItems" ], t.LandingPageController = i; }, function(e, t, n) { "use strict"; t.__esModule = !0; @@ -78629,7 +78635,7 @@ status: "True" } return e.prototype.$onInit = function() { var e = this; -this.ctrl.iconClass = this.ctrl.serviceClass.iconClass || "fa fa-clone", this.ctrl.imageUrl = this.ctrl.serviceClass.imageUrl, this.ctrl.serviceName = this.ctrl.serviceClass.name, this.ctrl.description = this.ctrl.serviceClass.description, this.ctrl.longDescription = this.ctrl.serviceClass.longDescription, this.ctrl.plans = r.get(this, "ctrl.serviceClass.resource.plans", []), this.ctrl.applications = [], this.ctrl.parameterData = {}, this.ctrl.bindParameterData = {}, this.ctrl.forms = {}, this.ctrl.appToBind = null, this.ctrl.configStepValid = !0, this.infoStep = { +this.ctrl.iconClass = this.ctrl.serviceClass.iconClass || "fa fa-clone", this.ctrl.imageUrl = this.ctrl.serviceClass.imageUrl, this.ctrl.serviceName = this.ctrl.serviceClass.name, this.ctrl.description = this.ctrl.serviceClass.description, this.ctrl.longDescription = this.ctrl.serviceClass.longDescription, this.ctrl.applications = [], this.ctrl.parameterData = {}, this.ctrl.bindParameterData = {}, this.ctrl.forms = {}, this.ctrl.appToBind = null, this.ctrl.configStepValid = !0, this.infoStep = { id: "info", label: "Information", view: "order-service/order-service-info.html", @@ -78642,7 +78648,7 @@ onShow: this.showInfo id: "plans", label: "Plan", view: "order-service/order-service-plans.html", -hidden: this.ctrl.plans.length < 2, +hidden: r.size(this.ctrl.servicePlans) < 2, allowed: !0, valid: !0, allowClickNav: !0, @@ -78684,7 +78690,7 @@ valid: !0, prevEnabled: !1, allowClickNav: !1, onShow: this.showResults -}, this.ctrl.steps = [ this.infoStep, this.planStep, this.configStep, this.bindStep, this.bindParametersStep, this.reviewStep ], this.ctrl.nameTaken = !1, this.ctrl.wizardDone = !1, this.ctrl.bindType = "none", this.selectPlan(r.head(this.ctrl.plans)), this.ctrl.planIndex = 0, this.ctrl.updating = !0, this.selectedProjectWatch = this.$scope.$watch(function() { +}, this.ctrl.steps = [ this.infoStep, this.planStep, this.configStep, this.bindStep, this.bindParametersStep, this.reviewStep ], this.ctrl.nameTaken = !1, this.ctrl.wizardDone = !1, this.ctrl.bindType = "none", this.ctrl.orderedPlans = r.orderBy(this.ctrl.servicePlans, [ "spec.externalMetadata.displayName", "metadata.name" ]), this.selectPlan(r.head(this.ctrl.orderedPlans)), this.ctrl.planIndex = 0, this.ctrl.updating = !0, this.selectedProjectWatch = this.$scope.$watch(function() { return e.ctrl.selectedProject; }, this.onProjectUpdate), this.bindTypeWatch = this.$scope.$watch("$ctrl.bindType", function(t, n) { t !== n && (e.updateBindParametersStepVisibility(), e.ctrl.nextTitle = e.bindParametersStep.hidden ? "Create" : "Next >", e.reviewStep.allowed = e.bindParametersStep.hidden && e.bindStep.valid); @@ -78728,21 +78734,21 @@ this.DataService.unwatchAll(this.watches), this.selectedProjectWatch(), this.bin i.isFunction(this.ctrl.handleClose) && this.ctrl.handleClose(); }, e.prototype.updateBindability = function() { if (!this.ctrl.wizardDone) { -var e = r.get(this.ctrl.selectedPlan, "bindable"); -this.bindStep.hidden = !0 !== e && (!1 === e || !r.get(this.ctrl.serviceClass, "resource.bindable")), this.updateBindParametersStepVisibility(), this.ctrl.configPageShown && (this.reviewStep.allowed = this.bindStep.hidden, this.bindStep.hidden ? this.ctrl.nextTitle = "Create" : this.ctrl.nextTitle = "Next >"); +var e = r.get(this.ctrl.selectedPlan, "spec.bindable"); +this.bindStep.hidden = !0 !== e && (!1 === e || !r.get(this.ctrl.serviceClass, "resource.spec.bindable")), this.updateBindParametersStepVisibility(), this.ctrl.configPageShown && (this.reviewStep.allowed = this.bindStep.hidden, this.bindStep.hidden ? this.ctrl.nextTitle = "Create" : this.ctrl.nextTitle = "Next >"); } }, e.prototype.updateBindParametersStepVisibility = function() { this.bindParametersStep.hidden = this.bindStep.hidden || "none" === this.ctrl.bindType || !r.has(this.ctrl, "bindParameterSchema.properties"), this.bindParametersStep.allowed = this.bindStep.valid; }, e.prototype.updateParameterSchema = function(e) { -this.ctrl.parameterSchema = r.get(e, "instanceCreateParameterSchema"), this.ctrl.parameterFormDefinition = r.get(this, "ctrl.selectedPlan.externalMetadata.schemas.service_instance.create.openshift_form_definition"), this.ctrl.bindParameterSchema = r.get(e, "serviceInstanceCredentialCreateParameterSchema"); +this.ctrl.parameterSchema = r.get(e, "spec.instanceCreateParameterSchema"), this.ctrl.parameterFormDefinition = r.get(this, "ctrl.selectedPlan.spec.externalMetadata.schemas.service_instance.create.openshift_form_definition"), this.ctrl.bindParameterSchema = r.get(e, "spec.serviceInstanceCredentialCreateParameterSchema"), this.ctrl.bindParameterFormDefinition = r.get(this, "ctrl.selectedPlan.spec.externalMetadata.schemas.service_binding.create.openshift_form_definition"); }, e.prototype.getParameters = function() { return r.omitBy(this.ctrl.parameterData, function(e) { return "" === e; }); -}, e.prototype.getServiceClassName = function() { -return r.get(this, "ctrl.serviceClass.resource.metadata.name"); +}, e.prototype.getExternalServiceClassName = function() { +return r.get(this, "ctrl.serviceClass.resource.spec.externalName"); }, e.prototype.generateSecretName = function() { -var e = r.truncate(this.getServiceClassName() + "-parameters", { +var e = r.truncate(this.getExternalServiceClassName() + "-parameters", { length: this.DNS1123_SUBDOMAIN_VALIDATION.maxlength - 5 - 1, omission: "" }); @@ -78768,7 +78774,7 @@ parameters: JSON.stringify(t) } }; }, e.prototype.makeServiceInstance = function(e) { -var t = this.getServiceClassName(), n = { +var t = this.getExternalServiceClassName(), n = { kind: "ServiceInstance", apiVersion: "servicecatalog.k8s.io/v1alpha1", metadata: { @@ -78776,8 +78782,8 @@ namespace: this.ctrl.selectedProject.metadata.name, generateName: t + "-" }, spec: { -serviceClassName: t, -planName: this.ctrl.selectedPlan.name +externalServiceClassName: t, +externalServicePlanName: this.ctrl.selectedPlan.spec.externalName } }; return e && (n.spec.parametersFrom = [ { diff --git a/dist/styles/main.css b/dist/styles/main.css index c4e57b4bee..34642ac298 100644 --- a/dist/styles/main.css +++ b/dist/styles/main.css @@ -767,6 +767,7 @@ select[multiple].input-lg,textarea.input-lg{height:auto} .form-horizontal .form-group-sm .control-label{padding-top:3px;font-size:11px} } .btn{display:inline-block;margin-bottom:0;font-weight:600;text-align:center;vertical-align:middle;touch-action:manipulation;cursor:pointer;border:1px solid transparent;white-space:nowrap;padding:2px 6px;font-size:13px;line-height:1.66666667;border-radius:1px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none} +.bootstrap-switch,.datepicker table{-webkit-user-select:none;-moz-user-select:none} .btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:dotted thin!important;outline:-webkit-focus-ring-color auto 5px!important;outline-offset:-2px!important} .btn.focus,.btn:focus,.btn:hover{color:#4d5258;text-decoration:none} .btn.active,.btn:active{outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)} @@ -1198,11 +1199,10 @@ a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#c00;background-color:#ebcccc} a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#c00;border-color:#c00} .panel-heading>.dropdown .dropdown-toggle,.panel-title,.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit} -.btn-flat-default,.panel{border:1px solid transparent} .list-group-item-heading{margin-top:0;margin-bottom:5px} .list-group-item-text{margin-bottom:0;line-height:1.3} .carousel-inner>.item>a>img,.carousel-inner>.item>img,.close{line-height:1} -.panel{margin-bottom:21px;background-color:#fff;border-radius:1px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)} +.panel{margin-bottom:21px;background-color:#fff;border:1px solid transparent;border-radius:1px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)} .panel-title,.panel>.list-group,.panel>.panel-collapse>.list-group,.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0} .panel-body{padding:15px} .panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:0px;border-top-left-radius:0px} @@ -2375,7 +2375,7 @@ td>.progress:first-child:last-child{margin-bottom:0;margin-top:3px} .datepicker-dropdown.datepicker-orient-bottom:after{top:-6px} .datepicker-dropdown.datepicker-orient-top:before{bottom:-7px;border-bottom:0;border-top:7px solid #bbb} .datepicker-dropdown.datepicker-orient-top:after{bottom:-6px;border-bottom:0;border-top:6px solid #fff} -.datepicker table{margin:0;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none} +.datepicker table{margin:0;-webkit-touch-callout:none;-khtml-user-select:none;-ms-user-select:none;user-select:none} .datepicker table tr td,.datepicker table tr th{text-align:center;width:30px;height:30px;border:none} .datepicker table tr td.new,.datepicker table tr td.old{color:#9c9c9c} .datepicker table tr td.day:hover,.datepicker table tr td.focused{background:#f1f1f1;cursor:pointer} @@ -2511,7 +2511,8 @@ select.bs-select-hidden,select.selectpicker{display:none!important} .bs-donebutton .btn-group button{width:100%} .bs-searchbox+.bs-actionsbox{padding:0 8px 4px} .bs-searchbox .form-control{margin-bottom:0;width:100%;float:none} -.bootstrap-switch{display:inline-block;direction:ltr;cursor:pointer;border-radius:1px;border:1px solid #bbb;position:relative;text-align:left;overflow:hidden;line-height:8px;z-index:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;vertical-align:middle;-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s} +.bootstrap-switch{display:inline-block;direction:ltr;cursor:pointer;border-radius:1px;border:1px solid #bbb;position:relative;text-align:left;overflow:hidden;line-height:8px;z-index:0;-ms-user-select:none;user-select:none;vertical-align:middle;-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s} +.c3 text,.log-line-number{-moz-user-select:none;-webkit-user-select:none} .bootstrap-switch .bootstrap-switch-container{display:inline-block;top:0;border-radius:1px;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)} .bootstrap-switch .bootstrap-switch-handle-off,.bootstrap-switch .bootstrap-switch-handle-on,.bootstrap-switch .bootstrap-switch-label{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;cursor:pointer;display:inline-block!important;height:100%;padding:2px 6px;font-size:13px;line-height:21px} .ie9.layout-pf-alt-fixed .nav-pf-vertical-alt,.ie9.layout-pf-fixed .nav-pf-secondary-nav,.ie9.layout-pf-fixed .nav-pf-tertiary-nav,.ie9.layout-pf-fixed .nav-pf-vertical,.list-group-item-header{box-sizing:content-box} @@ -2545,7 +2546,7 @@ select.bs-select-hidden,select.selectpicker{display:none!important} .bootstrap-touchspin .input-group-btn-vertical i{position:absolute;font-weight:400} .c3 svg{font:10px sans-serif} .c3 line,.c3 path{fill:none;stroke:#000} -.c3 text{-webkit-user-select:none;-moz-user-select:none;user-select:none} +.c3 text{user-select:none} .c3-bars path,.c3-event-rect,.c3-legend-item-tile,.c3-xgrid-focus,.c3-ygrid{shape-rendering:crispEdges} .c3-chart-arc text{fill:#fff;font-size:13px} .c3-grid text{fill:#aaa} @@ -4103,6 +4104,7 @@ div.hopscotch-bubble .hopscotch-nav-button.prev{color:#030303} .landing-search-form .search-pf-input-group .pficon-close{font-size:17px;padding-top:.3em} .landing-search-form .dropdown-menu{margin-top:0;width:100%} .landing-search-form .dropdown-menu>li>a.catalog-search-match{display:flex;line-height:1.5;padding:3px 10px 3px 5px;white-space:normal} +.order-service-details .order-service-description-block .description,.pre-wrap{white-space:pre-wrap} .landing-search-form .dropdown-menu .active>a.catalog-search-match,.landing-search-form .dropdown-menu :focus{background-color:#def3ff!important;border-color:#bee1f4!important;color:inherit!important} .landing-search-form .dropdown-menu .active>a.catalog-search-match.no-matches{background-color:transparent!important;border-color:transparent!important} .landing-side-bar{background-color:#292e34;color:#fff;z-index:1029} @@ -4116,8 +4118,10 @@ div.hopscotch-bubble .hopscotch-nav-button.prev{color:#030303} .order-service-details .order-service-details-top .service-icon{margin-right:15px} .order-service-details .order-service-details-top .service-icon .icon{font-size:60px} .order-service-details .order-service-details-top .service-icon .image img{max-height:52px;max-width:52px} +.order-service-details .order-service-details-top .service-icon .image img[src$=".svg"]{height:52px} @media (min-width:450px){.order-service-details .order-service-details-top .service-icon .icon{font-size:64px} .order-service-details .order-service-details-top .service-icon .image img{max-height:60px;max-width:60px} +.order-service-details .order-service-details-top .service-icon .image img[src$=".svg"]{height:60px} } .order-service-details .order-service-details-top .service-title{font-size:18px;font-weight:600;display:-webkit-box;line-height:1.4em;max-height:4.2em;overflow:hidden;padding:0!important;-webkit-box-orient:vertical;-webkit-line-clamp:3} @media (min-width:450px){.order-service-details .order-service-details-top .service-title{font-size:22px} @@ -4125,7 +4129,6 @@ div.hopscotch-bubble .hopscotch-nav-button.prev{color:#030303} .order-service-details .order-service-details-top .service-title-area{flex:1 1 0%;word-wrap:break-word;word-break:break-word;overflow-wrap:break-word;min-width:0} .order-service-details .order-service-details-top .sub-title{font-size:20px;font-weight:600;color:#72767b} .order-service-details .order-service-description-block{margin-top:15px} -.order-service-details .order-service-description-block .description{white-space:pre-wrap} .order-service-details .order-service-description-block .learn-more-link{font-size:11px;white-space:nowrap} .order-service-details .order-service-documentation-url{margin-top:4px} .order-service-details .order-service-tags{margin-top:5px} @@ -4277,7 +4280,7 @@ body.overlay-open,body.overlay-open .landing,body.overlay-open .landing-side-bar .saas-offerings-container .sass-list-expander-container{margin-bottom:10px;text-align:center} .saas-offerings-container .spinner-container{padding-top:60px;padding-bottom:60px} .services-view,services-view{display:flex;flex:1 1 auto} -.services-view .vendor-info-icon,services-view .vendor-info-icon{font-size:10px;vertical-align:middle;padding-left:2px} +.services-view .vendor-info-icon,services-view .vendor-info-icon{font-size:10px;padding-left:2px;vertical-align:middle} .services-view .services-item{animation:catalogItemFade .2s ease-out;color:#363636;min-height:140px;overflow:hidden;padding:0 10px 20px;position:relative;text-align:center;width:50%;word-break:break-word;z-index:99} @media (min-width:480px){.services-view .services-item{width:33.3333%} } @@ -4306,14 +4309,14 @@ body.overlay-open,body.overlay-open .landing,body.overlay-open .landing-side-bar @media (min-width:480px){.services-view .services-sub-category .services-sub-category-tab:focus .services-sub-category-tab-image img,.services-view .services-sub-category .services-sub-category-tab:hover .services-sub-category-tab-image img,.services-view .services-sub-category.active .services-sub-category-tab .services-sub-category-tab-image img{opacity:1} .services-view .services-no-sub-categories{display:flex;flex:1 1 auto;padding:15px 20px 12px} .services-view .services-no-sub-categories .services-items{left:0;margin:0 0 8px;right:0} -.services-view .services-sub-categories{align-content:flex-start;align-items:flex-start;display:flex;flex:1 1 auto;flex-wrap:wrap;padding:15px 20px 12px;position:relative} -.services-view .services-sub-categories .services-items{left:20px;margin:10px 0;position:absolute;right:20px} +.services-view .services-sub-categories{align-content:flex-start;align-items:flex-start;display:flex;flex:1 1 auto;flex-wrap:wrap;margin:15px 20px 12px;padding:0;position:relative} +.services-view .services-sub-categories .services-items{left:0;margin:10px 0;position:absolute;right:0} .services-view .services-sub-category{background-color:#fff;display:inline-block;margin:0 3px 3px 0} .services-view .services-sub-category.active .services-sub-category-tab{color:#363636!important} .services-view .services-sub-category.active .services-sub-category-tab:after{animation:catalogItemFade .2s ease-out;border-bottom-color:#fff;border-bottom-style:solid;border-bottom-width:10px;border-left:10px solid transparent;border-right:10px solid transparent;bottom:-13px;content:"";display:block;left:50%;margin-left:-10px;opacity:1;position:absolute} -.services-view .services-sub-category .services-sub-category-tab{color:#8b8d8f;display:flex;font-size:14px;font-weight:600;flex-direction:column;height:90px;justify-content:center;min-width:100px;padding:0 15px;position:relative;text-align:center} +.services-view .services-sub-category .services-sub-category-tab{color:#8b8d8f;display:flex;font-size:14px;font-weight:600;flex-direction:column;height:110px;justify-content:center;line-height:1.3;padding:0 5px;position:relative;text-align:center;width:120px} .services-view .services-sub-category .services-sub-category-tab:focus,.services-view .services-sub-category .services-sub-category-tab:hover{color:#0088ce;text-decoration:none} -.services-view .services-sub-category .services-sub-category-tab-icon,.services-view .services-sub-category .services-sub-category-tab-image{margin:0 0 5px} +.services-view .services-sub-category .services-sub-category-tab-icon,.services-view .services-sub-category .services-sub-category-tab-image{margin:0 0 10px} .services-view .services-sub-category .services-sub-category-tab-icon{font-size:36px} .services-view .services-sub-category .services-sub-category-tab-image{height:36px;position:relative} .services-view .services-sub-category .services-sub-category-tab-image img{bottom:0;left:0;margin:auto;max-height:36px;max-width:36px;opacity:.5;position:absolute;right:0;top:0} @@ -4348,7 +4351,7 @@ body.overlay-open,body.overlay-open .landing,body.overlay-open .landing-side-bar .services-view .services-view-container.mobile-categories-view .services-categories .active .services-back-link{display:none!important} .services-view .services-view-container.mobile-categories-view .services-items,.services-view .services-view-container.mobile-categories-view .services-sub-categories,.services-view .services-view-container.mobile-items-view .add-methods,.services-view .services-view-container.mobile-items-view .services-categories,.services-view .services-view-container.mobile-items-view .services-sub-categories>li.active:after,.services-view .services-view-container.mobile-items-view .services-sub-category:not(.active),.services-view .services-view-container.mobile-items-view .services-sub-category>a:after,.services-view .services-view-container.mobile-subcategories-view .add-methods,.services-view .services-view-container.mobile-subcategories-view .services-categories>li.active:after{display:none} .services-view .services-view-container.mobile-items-view .services-sub-categories>li.active,.services-view .services-view-container.mobile-subcategories-view .services-categories>li.active{background-color:transparent} -.services-view .services-view-container.mobile-items-view .services-sub-categories>li.active>a.services-category-heading,.services-view .services-view-container.mobile-items-view .services-sub-categories>li.active>a.services-sub-category-tab,.services-view .services-view-container.mobile-subcategories-view .services-categories>li.active>a.services-category-heading,.services-view .services-view-container.mobile-subcategories-view .services-categories>li.active>a.services-sub-category-tab{left:50%;position:absolute;transform:translateX(-50%);width:auto} +.services-view .services-view-container.mobile-items-view .services-sub-categories>li.active>a.services-category-heading,.services-view .services-view-container.mobile-items-view .services-sub-categories>li.active>a.services-sub-category-tab,.services-view .services-view-container.mobile-subcategories-view .services-categories>li.active>a.services-category-heading,.services-view .services-view-container.mobile-subcategories-view .services-categories>li.active>a.services-sub-category-tab{position:absolute;text-align:center} .services-view .services-view-container.mobile-items-view .services-sub-categories>li.active>a.services-category-heading:focus,.services-view .services-view-container.mobile-items-view .services-sub-categories>li.active>a.services-category-heading:hover,.services-view .services-view-container.mobile-items-view .services-sub-categories>li.active>a.services-sub-category-tab:focus,.services-view .services-view-container.mobile-items-view .services-sub-categories>li.active>a.services-sub-category-tab:hover,.services-view .services-view-container.mobile-subcategories-view .services-categories>li.active>a.services-category-heading:focus,.services-view .services-view-container.mobile-subcategories-view .services-categories>li.active>a.services-category-heading:hover,.services-view .services-view-container.mobile-subcategories-view .services-categories>li.active>a.services-sub-category-tab:focus,.services-view .services-view-container.mobile-subcategories-view .services-categories>li.active>a.services-sub-category-tab:hover{color:#fff;cursor:default} .services-view .services-view-container.mobile-items-view .services-sub-categories>li.active>a.services-back-link,.services-view .services-view-container.mobile-subcategories-view .services-categories>li.active>a.services-back-link{display:inline-block;font-size:10px;margin-left:15px;padding-left:15px;width:auto} .services-view .services-view-container.mobile-items-view .services-sub-categories>li.active>a.services-back-link:after,.services-view .services-view-container.mobile-subcategories-view .services-categories>li.active>a.services-back-link:after{content:'\f104';display:block;font-family:FontAwesome;position:absolute;left:5px;top:50%;transform:translateY(-50%)} @@ -4361,10 +4364,9 @@ body.overlay-open,body.overlay-open .landing,body.overlay-open .landing-side-bar .services-view .services-view-container .services-categories>li>a,.services-view .services-view-container .services-sub-categories>li>a{color:#fff;display:inline-block;line-height:1;padding:10px 20px;position:relative;width:100%} .services-view .services-view-container .services-categories>li>a::after,.services-view .services-view-container .services-sub-categories>li>a::after{content:'\f061';color:#fff;display:block;font-family:FontAwesome;position:absolute;right:20px;top:50%;transform:translateY(-50%)} .services-view .services-view-container .services-categories>li>a:focus,.services-view .services-view-container .services-categories>li>a:hover,.services-view .services-view-container .services-sub-categories>li>a:focus,.services-view .services-view-container .services-sub-categories>li>a:hover{color:#0088ce;text-decoration:none} -.services-view .services-view-container .services-categories>li>a .services-sub-category-tab-icon,.services-view .services-view-container .services-sub-categories>li>a .services-sub-category-tab-icon{display:none!important} +.services-view .services-view-container .services-categories>li>a .services-sub-category-tab-icon,.services-view .services-view-container .services-categories>li>a .services-sub-category-tab-image,.services-view .services-view-container .services-sub-categories>li>a .services-sub-category-tab-icon,.services-view .services-view-container .services-sub-categories>li>a .services-sub-category-tab-image{display:none!important} } .services-view .spinner-container{background:#fff;display:flex;flex:1 1 auto;padding-top:100px;padding-bottom:100px} -.pre-wrap{white-space:pre-wrap} .visible-xlg-inline-block{display:none!important} @media (max-width:767px){.td-long-string{word-wrap:break-word;word-break:break-word;overflow-wrap:break-word;min-width:0} } @@ -4380,6 +4382,7 @@ body.overlay-open,body.overlay-open .landing,body.overlay-open .landing-side-bar .btn-file{position:relative;overflow:hidden} .btn-file input[type=file]{position:absolute;top:0;right:0;min-width:100%;min-height:100%;font-size:100px;text-align:right;filter:alpha(opacity=0);opacity:0;cursor:inherit;display:block} .osc-form .icon,.service-table,.service-table thead tr th,.show-drag-and-drop-zone{text-align:center} +.btn-flat-default{border:1px solid transparent} .btn-flat-default:focus,.btn-flat-default:hover{background-color:#f7f7f7;border-color:#e7e7e7} .btn-remove{color:#333;display:inline-block;font-size:15px;line-height:1;opacity:.65;padding:5px 7px;vertical-align:middle} .btn-remove:focus,.btn-remove:hover{color:inherit;opacity:1;text-decoration:none} @@ -5691,7 +5694,7 @@ alerts+.chromeless .log-loading-msg{margin-top:130px} .log-line{color:#d1d1d1} .log-line:hover{background-color:#22262b;color:#ededed} .log-line-number:before{content:attr(data-line-number)} -.log-line-number{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;border-right:1px #272b30 solid;padding-right:10px;vertical-align:top;white-space:nowrap;width:60px;color:#72767b} +.log-line-number{-ms-user-select:none;border-right:1px #272b30 solid;padding-right:10px;vertical-align:top;white-space:nowrap;width:60px;color:#72767b} .log-line-text{padding:0 10px;white-space:pre-wrap;width:100%} .appended-icon,.project-date [am-time-ago],.projects-list [am-time-ago]{white-space:nowrap} .log-line-text::-moz-selection{color:#101214;background:#e5e5e5}