diff --git a/app/index.html b/app/index.html index 309350449a..0d3b18cbb5 100644 --- a/app/index.html +++ b/app/index.html @@ -185,6 +185,7 @@

JavaScript Required

+ diff --git a/app/scripts/directives/logViewer.js b/app/scripts/directives/logViewer.js index bd5e31f6b1..cb27e8a537 100644 --- a/app/scripts/directives/logViewer.js +++ b/app/scripts/directives/logViewer.js @@ -8,9 +8,10 @@ angular.module('openshiftConsole') '$window', '$filter', '$q', - 'AuthService', + 'AggregatedLoggingService', 'APIService', 'APIDiscovery', + 'AuthService', 'DataService', 'HTMLService', 'ModalsService', @@ -21,9 +22,10 @@ angular.module('openshiftConsole') $window, $filter, $q, - AuthService, + AggregatedLoggingService, APIService, APIDiscovery, + AuthService, DataService, HTMLService, ModalsService, @@ -434,16 +436,19 @@ angular.module('openshiftConsole') if(!(projectName && containerName && name && url)) { return; } - $scope.$watchGroup(['context.project.metadata.name', 'options.container', 'name'], function() { - angular.extend($scope, { - kibanaArchiveUrl: $sce.trustAsResourceUrl(logLinks.archiveUri({ - baseURL: url, - namespace: $scope.context.project.metadata.name, - namespaceUid: $scope.context.project.metadata.uid, - podname: name, - containername: $scope.options.container, - backlink: URI.encode($window.location.href) - }, $filter('annotation')($scope.context.project,'loggingDataPrefix'))) + + AggregatedLoggingService.isOperationsUser().then(function(canViewOperationsLogs) { + $scope.$watchGroup(['context.project.metadata.name', 'options.container', 'name'], function() { + angular.extend($scope, { + kibanaArchiveUrl: logLinks.archiveUri({ + baseURL: url, + namespace: $scope.context.project.metadata.name, + namespaceUid: $scope.context.project.metadata.uid, + podname: name, + containername: $scope.options.container, + backlink: URI.encode($window.location.href) + }, $filter('annotation')($scope.context.project,'loggingDataPrefix'), canViewOperationsLogs) + }); }); }); }); diff --git a/app/scripts/services/aggregatedLoggingService.js b/app/scripts/services/aggregatedLoggingService.js new file mode 100644 index 0000000000..548a7e148e --- /dev/null +++ b/app/scripts/services/aggregatedLoggingService.js @@ -0,0 +1,43 @@ +'use strict'; + +angular.module("openshiftConsole") + .factory("AggregatedLoggingService", function($q, Logger, DataService) { + + // cache previous request + var userAllowed; + + // Create SelfSubjectAccessReview request againt authorization API to check whether + // current user can view pods/log from 'default' project. + // Users who can view such logs are 'operations' users + var isOperationsUser = function() { + if (userAllowed !== undefined) { + // Using cached data. + Logger.log("AggregatedLoggingService, using cached user"); + return $q.when(userAllowed); + } + Logger.log("AggregatedLoggingService, loading whether user is Operations user"); + var ssar = { + apiVersion: 'authorization.k8s.io/v1', + kind: 'SelfSubjectAccessReview', + spec: { + resourceAttributes: { + resource: 'pods/log', + namespace: 'default', + verb: 'view' + } + } + }; + return DataService.create({ group: 'authorization.k8s.io', version: 'v1', resource: 'selfsubjectaccessreviews'}, + null, ssar, {namespace: 'default'}).then( + function(data) { + userAllowed = data.status.allowed; + return userAllowed; + }, function() { + return false; + }); + }; + + return { + isOperationsUser: isOperationsUser + }; + }); diff --git a/app/scripts/services/logLinks.js b/app/scripts/services/logLinks.js index 4ed46dba2b..f4db91a4c9 100644 --- a/app/scripts/services/logLinks.js +++ b/app/scripts/services/logLinks.js @@ -73,7 +73,10 @@ angular.module('openshiftConsole') ].join('')); - var archiveUri = function(opts, prefix) { + var archiveUri = function(opts, prefix, canViewOperationsLogs) { + if(canViewOperationsLogs && (!prefix || prefix.startsWith('project.'))) { + prefix = 'project'; + } prefix = prefix || 'project.' + opts.namespace + '.' + opts.namespaceUid; opts.index = prefix + '.*'; diff --git a/app/views/directives/logs/_log-viewer.html b/app/views/directives/logs/_log-viewer.html index 1b6bcefeb9..74a8a2584f 100644 --- a/app/views/directives/logs/_log-viewer.html +++ b/app/views/directives/logs/_log-viewer.html @@ -47,16 +47,8 @@

Logs are not available.

{{emptyStateMessage}}

-
-
- - - -
+
+ View Archive
diff --git a/dist/scripts/scripts.js b/dist/scripts/scripts.js index 4ca8743051..0eaaae1925 100644 --- a/dist/scripts/scripts.js +++ b/dist/scripts/scripts.js @@ -1,20 +1,20 @@ "use strict"; function OverviewController(e, t, n, r, a, o, i, s, c, l, u, d, m, p, f, g, v, h, y, b, S, C, w, P, j, k, I, R, E, T, N) { -function D(e) { +function A(e) { var t = e.metadata.ownerReferences; return t ? _(t).filter({ kind: "OfflineVirtualMachine" }).map("uid").first() : null; } -function A() { +function D() { if (B.offlineVirtualMachines && B.virtualMachines && B.pods) { var e = _(B.pods).values().filter(function(e) { return !!_.get(e, 'metadata.labels["kubevirt.io/vmUID"]'); }).keyBy('metadata.labels["kubevirt.io/vmUID"]').value(), t = _(B.virtualMachines).values().filter(function(e) { -return !!D(e); +return !!A(e); }).keyBy(function(e) { -return D(e); +return A(e); }).value(), n = []; _.each(B.offlineVirtualMachines, function(r) { var a = r.metadata.uid, o = t[a]; @@ -130,14 +130,14 @@ return _.isEmpty(be.pipelinesByDeploymentConfig[t]); B.deploymentConfigsNoPipeline = _.sortBy(e, "metadata.name"), B.pipelineViewHasOtherResources = !(_.isEmpty(B.deploymentConfigsNoPipeline) && _.isEmpty(B.vanillaReplicationControllers) && _.isEmpty(B.deployments) && _.isEmpty(B.vanillaReplicaSets) && _.isEmpty(B.statefulSets) && _.isEmpty(B.monopods)); }, Ne = function() { B.disableFilter = "pipeline" === B.viewBy && _.isEmpty(B.pipelineBuildConfigs); -}, De = function(e) { +}, Ae = function(e) { return b.getLabelSelector().select(e); -}, Ae = [ "metadata.name", "spec.clusterServiceClassExternalName" ], $e = function(e) { -return y.filterForKeywords(e, Ae, be.filterKeywords); +}, De = [ "metadata.name", "spec.clusterServiceClassExternalName" ], $e = function(e) { +return y.filterForKeywords(e, De, be.filterKeywords); }, Be = function(e) { switch (B.filterBy) { case "label": -return De(e); +return Ae(e); case "name": return $e(e); @@ -157,7 +157,7 @@ B.filteredDeploymentConfigs = Be(B.deploymentConfigs), B.filteredReplicationCont B.viewBy = localStorage.getItem(Oe) || "app", e.$watch(function() { return B.viewBy; }, function(e) { -localStorage.setItem(Oe, e), Ne(), Ae = "app" === B.viewBy ? [ "metadata.name", "metadata.labels.app" ] : [ "metadata.name" ], Le(), "pipeline" === B.viewBy ? b.setLabelSuggestions(he) : b.setLabelSuggestions(ve); +localStorage.setItem(Oe, e), Ne(), De = "app" === B.viewBy ? [ "metadata.name", "metadata.labels.app" ] : [ "metadata.name" ], Le(), "pipeline" === B.viewBy ? b.setLabelSuggestions(he) : b.setLabelSuggestions(ve); }), d.DISABLE_OVERVIEW_METRICS || (C.isAvailable(!0).then(function(e) { be.showMetrics = e; }), e.$on("metrics-connection-failed", function(e, t) { @@ -240,7 +240,7 @@ _.isEmpty(e) || (b.addLabelSuggestionsFromResources(e, he), "pipeline" === B.vie }, nt = function(e) { return "Succeeded" !== e.status.phase && "Failed" !== e.status.phase && (!H(e, "openshift.io/deployer-pod-for.name") && (!O(e, "openshift.io/build.name") && "slave" !== H(e, "jenkins"))); }, rt = function() { -be.podsByOwnerUID = j.groupByOwnerUID(B.pods), B.monopods = _.filter(be.podsByOwnerUID[""], nt), A(); +be.podsByOwnerUID = j.groupByOwnerUID(B.pods), B.monopods = _.filter(be.podsByOwnerUID[""], nt), D(); }, at = function(e) { return !!_.get(e, "status.replicas") || (!O(e, "deploymentConfig") || x(e)); }, ot = function(e) { @@ -495,13 +495,13 @@ poll: V, pollInterval: 6e4 })), e.KUBEVIRT_ENABLED) { Rt.push(m.watch(N.offlineVirtualMachine, r, function(e) { -B.offlineVirtualMachines = e.by("metadata.name"), A(), Le(); +B.offlineVirtualMachines = e.by("metadata.name"), D(), Le(); }, { poll: V, pollInterval: 6e4 })); Rt.push(m.watch(N.virtualMachine, r, function(e) { -B.virtualMachines = e.by("metadata.name"), A(), Le(); +B.virtualMachines = e.by("metadata.name"), D(), Le(); }, { poll: V, pollInterval: 6e4 @@ -1553,6 +1553,36 @@ getMetricsURL: function() { return n.when(t); } }; +} ]), angular.module("openshiftConsole").factory("AggregatedLoggingService", [ "$q", "Logger", "DataService", function(e, t, n) { +var r; +return { +isOperationsUser: function() { +if (void 0 !== r) return t.log("AggregatedLoggingService, using cached user"), e.when(r); +t.log("AggregatedLoggingService, loading whether user is Operations user"); +var a = { +apiVersion: "authorization.k8s.io/v1", +kind: "SelfSubjectAccessReview", +spec: { +resourceAttributes: { +resource: "pods/log", +namespace: "default", +verb: "view" +} +} +}; +return n.create({ +group: "authorization.k8s.io", +version: "v1", +resource: "selfsubjectaccessreviews" +}, null, a, { +namespace: "default" +}).then(function(e) { +return r = e.status.allowed; +}, function() { +return !1; +}); +} +}; } ]), angular.module("openshiftConsole").service("ApplicationGenerator", [ "DataService", "APIService", "Logger", "$parse", "$q", function(e, t, n, r, a) { var o = {}, i = function(e) { return _.isArray(e) ? e : _.map(e, function(e, t) { @@ -4971,7 +5001,7 @@ name: e.containerName }), n = I(t); e.containerState = n; }); -}, N = e("annotation"), D = function(e, t) { +}, N = e("annotation"), A = function(e, t) { if (r.loaded = !0, r.pod = e, r.dcName = N(e, "deploymentConfig"), r.rcName = N(e, "deployment"), r.deploymentVersion = N(e, "deploymentVersion"), r.logCanRun = !_.includes([ "New", "Pending", "Unknown" ], e.status.phase), S(), delete r.controllerRef, !r.dcName) { var n = m.getControllerReferences(e); r.controllerRef = _.find(n, function(e) { @@ -4987,10 +5017,10 @@ f.get(n.project).then(_.spread(function(t, a) { b = a, r.project = t, r.projectContext = a, s.get(r.podsVersion, n.pod, a, { errorNotification: !1 }).then(function(e) { -D(e); +A(e); var t = {}; t[e.metadata.name] = e, r.logOptions.container = n.container || e.spec.containers[0].name, r.containerTerminals = R(), E(e), l.fetchReferencedImageStreamImages(t, r.imagesByDockerReference, r.imageStreamImageRefByDockerReference, b), h.push(s.watchObject(r.podsVersion, n.pod, a, function(e, t) { -D(e, t), T(r.containerTerminals), E(e); +A(e, t), T(r.containerTerminals), E(e); })); }, function(t) { r.loaded = !0, r.alerts.load = { @@ -5191,12 +5221,12 @@ n.filteredStatefulSets = c.filterForKeywords(_.values(n.statefulSets), P, j); C = _.filter(n.pods, function(e) { return !n.filters.hideOlderResources || "Succeeded" !== e.status.phase && "Failed" !== e.status.phase; }), n.filteredPods = c.filterForKeywords(C, P, j); -}, D = r("isIncompleteBuild"), A = r("buildConfigForBuild"), B = r("isRecentBuild"), V = function() { +}, A = r("isIncompleteBuild"), D = r("buildConfigForBuild"), B = r("isRecentBuild"), V = function() { moment().subtract(5, "m"); y = _.filter(n.builds, function(e) { if (!n.filters.hideOlderResources) return !0; -if (D(e)) return !0; -var t = A(e); +if (A(e)) return !0; +var t = D(e); return t ? n.latestBuildByConfig[t].metadata.name === e.metadata.name : B(e); }), n.filteredBuilds = c.filterForKeywords(y, P, j); }, L = r("deploymentStatus"), O = r("deploymentIsInProgress"), U = function() { @@ -5408,7 +5438,7 @@ return e ? r + (y(e, "description") || "") : ""; } } }); -var D = function(e, t, n, a) { +var A = function(e, t, n, a) { var o = { title: "Confirm Removal", alerts: {}, @@ -5455,7 +5485,7 @@ project: n, subjectKinds: N, canUpdateRolebindings: b("rolebindings", "update", v), confirmRemove: function(n, a, i, s) { -var l = null, u = D(n, a, i, r.user.metadata.name); +var l = null, u = A(n, a, i, r.user.metadata.name); _.isEqual(n, r.user.metadata.name) && d.isLastRole(r.user.metadata.name, r.roleBindings) && (l = !0), o.open({ templateUrl: "views/modals/confirm.html", controller: "ConfirmModalController", @@ -6194,7 +6224,7 @@ o.unwatchAll(j); }); })); } ]), angular.module("openshiftConsole").controller("ReplicaSetController", [ "$scope", "$filter", "$routeParams", "APIService", "AuthorizationService", "BreadcrumbsService", "DataService", "DeploymentsService", "HPAService", "ImageStreamResolver", "keyValueEditorUtils", "kind", "Logger", "MetricsService", "ModalsService", "Navigate", "OwnerReferencesService", "PodsService", "ProjectsService", "StorageService", function(e, t, n, r, a, o, i, s, c, l, u, d, m, p, f, g, v, h, y, b) { -var S = !1, C = t("annotation"), w = t("humanizeKind")(d), P = t("hasDeployment"), j = r.getPreferredVersion("builds"), k = r.getPreferredVersion("imagestreams"), I = r.getPreferredVersion("horizontalpodautoscalers"), R = r.getPreferredVersion("limitranges"), E = r.getPreferredVersion("pods"), T = r.getPreferredVersion("replicasets"), N = r.getPreferredVersion("replicationcontrollers"), D = r.getPreferredVersion("resourcequotas"), A = r.getPreferredVersion("appliedclusterresourcequotas"); +var S = !1, C = t("annotation"), w = t("humanizeKind")(d), P = t("hasDeployment"), j = r.getPreferredVersion("builds"), k = r.getPreferredVersion("imagestreams"), I = r.getPreferredVersion("horizontalpodautoscalers"), R = r.getPreferredVersion("limitranges"), E = r.getPreferredVersion("pods"), T = r.getPreferredVersion("replicasets"), N = r.getPreferredVersion("replicationcontrollers"), A = r.getPreferredVersion("resourcequotas"), D = r.getPreferredVersion("appliedclusterresourcequotas"); switch (d) { case "ReplicaSet": e.resource = T, e.healthCheckURL = g.healthCheckURL(n.project, "ReplicaSet", n.replicaSet, "extensions"); @@ -6342,12 +6372,12 @@ pollInterval: 6e4 })), i.list(R, u).then(function(t) { e.limitRanges = t.by("metadata.name"), U(); }); -B.push(i.watch(D, u, function(t) { +B.push(i.watch(A, u, function(t) { e.quotas = t.by("metadata.name"); }, { poll: !0, pollInterval: 6e4 -})), B.push(i.watch(A, u, function(t) { +})), B.push(i.watch(D, u, function(t) { e.clusterQuotas = t.by("metadata.name"); }, { poll: !0, @@ -7260,7 +7290,7 @@ return _.map(e, "metadata.name"); }); e.webhookSecrets = m.groupSecretsByType(t).webhook, e.webhookSecrets.unshift(""), e.secrets.secretsByType = _.each(r, function(e) { e.unshift(""); -}), D(), P = S(t.by("metadata.name")), e.valueFromObjects = w.concat(P); +}), A(), P = S(t.by("metadata.name")), e.valueFromObjects = w.concat(P); }); var n = function(e, n) { e.type = n && n.kind ? n.kind : "None"; @@ -7407,7 +7437,7 @@ var t = [].concat(e.triggers.imageChangeTriggers, e.triggers.builderImageChangeT return t = _.filter(t, function(e) { return _.has(e, "disabled") && !e.disabled || e.present; }), t = t.concat(T(e.triggers.webhookTriggers)), t = _.map(t, "data"); -}, D = function() { +}, A = function() { switch (e.secrets.picked = { gitSecret: e.buildConfig.spec.source.sourceSecret ? [ e.buildConfig.spec.source.sourceSecret ] : [ { name: "" @@ -7437,7 +7467,7 @@ name: "" mountPath: "" } ]; } -}, A = function(e, t, n) { +}, D = function(e, t, n) { t.name ? e[n] = t : delete e[n]; }, $ = function(t, n) { var r = "Custom" === e.strategyType ? "secretSource" : "secret", a = _.filter(n, function(e) { @@ -7458,7 +7488,7 @@ break; case "JenkinsPipeline": "path" === e.jenkinsfileOptions.type ? delete e.updatedBuildConfig.spec.strategy.jenkinsPipelineStrategy.jenkinsfile : delete e.updatedBuildConfig.spec.strategy.jenkinsPipelineStrategy.jenkinsfilePath; } -switch (e.sources.images && !_.isEmpty(e.sourceImages) && (e.updatedBuildConfig.spec.source.images[0].paths = R(e.imageSourcePaths), e.updatedBuildConfig.spec.source.images[0].from = E(e.imageOptions.fromSource)), "None" === e.imageOptions.from.type ? delete b(e.updatedBuildConfig).from : b(e.updatedBuildConfig).from = E(e.imageOptions.from), "None" === e.imageOptions.to.type ? delete e.updatedBuildConfig.spec.output.to : e.updatedBuildConfig.spec.output.to = E(e.imageOptions.to), b(e.updatedBuildConfig).env = p.compactEntries(e.envVars), A(e.updatedBuildConfig.spec.source, _.head(e.secrets.picked.gitSecret), "sourceSecret"), A(b(e.updatedBuildConfig), _.head(e.secrets.picked.pullSecret), "pullSecret"), A(e.updatedBuildConfig.spec.output, _.head(e.secrets.picked.pushSecret), "pushSecret"), e.strategyType) { +switch (e.sources.images && !_.isEmpty(e.sourceImages) && (e.updatedBuildConfig.spec.source.images[0].paths = R(e.imageSourcePaths), e.updatedBuildConfig.spec.source.images[0].from = E(e.imageOptions.fromSource)), "None" === e.imageOptions.from.type ? delete b(e.updatedBuildConfig).from : b(e.updatedBuildConfig).from = E(e.imageOptions.from), "None" === e.imageOptions.to.type ? delete e.updatedBuildConfig.spec.output.to : e.updatedBuildConfig.spec.output.to = E(e.imageOptions.to), b(e.updatedBuildConfig).env = p.compactEntries(e.envVars), D(e.updatedBuildConfig.spec.source, _.head(e.secrets.picked.gitSecret), "sourceSecret"), D(b(e.updatedBuildConfig), _.head(e.secrets.picked.pullSecret), "pullSecret"), D(e.updatedBuildConfig.spec.output, _.head(e.secrets.picked.pushSecret), "pushSecret"), e.strategyType) { case "Source": case "Docker": $(e.updatedBuildConfig.spec.source, e.secrets.picked.sourceSecrets); @@ -8124,13 +8154,13 @@ g.hideNotification("create-builder-list-config-maps-error"), g.hideNotification( }); }; e.$on("$destroy", N); -var D = i.getPreferredVersion("configmaps"), A = i.getPreferredVersion("limitranges"), $ = i.getPreferredVersion("imagestreams"), B = i.getPreferredVersion("imagestreamtags"), V = i.getPreferredVersion("secrets"), L = i.getPreferredVersion("resourcequotas"), O = i.getPreferredVersion("appliedclusterresourcequotas"); +var A = i.getPreferredVersion("configmaps"), D = i.getPreferredVersion("limitranges"), $ = i.getPreferredVersion("imagestreams"), B = i.getPreferredVersion("imagestreamtags"), V = i.getPreferredVersion("secrets"), L = i.getPreferredVersion("resourcequotas"), O = i.getPreferredVersion("appliedclusterresourcequotas"); v.get(a.project).then(_.spread(function(t, n) { e.project = t, a.sourceURI && (e.sourceURIinParams = !0), e.hasClusterResourceOverrides = d.hasClusterResourceOverrides(t); var i = function() { e.cpuProblems = d.validatePodLimits(e.limitRanges, "cpu", [ e.container ], t), e.memoryProblems = d.validatePodLimits(e.limitRanges, "memory", [ e.container ], t); }; -c.list(A, n).then(function(t) { +c.list(D, n).then(function(t) { e.limitRanges = t.by("metadata.name"), _.isEmpty(e.limitRanges) || e.$watch("container", i, !0); }); var v, y, C = function() { @@ -8182,7 +8212,7 @@ return r.buildConfig.sourceUrl === _.get(r, "image.metadata.annotations.sampleRe e.metricsWarning = !t; }); var o = [], i = []; -e.valueFromObjects = [], c.list(D, n, null, { +e.valueFromObjects = [], c.list(A, n, null, { errorNotification: !1 }).then(function(t) { o = R(t.by("metadata.name")), e.valueFromObjects = o.concat(i); @@ -9992,9 +10022,9 @@ details: e("getErrorDetails")(n) } function w() { var e = { -started: "Creating resources in project " + A(p.input.selectedProject), -success: "Creating resources in project " + A(p.input.selectedProject), -failure: "Failed to create some resources in project " + A(p.input.selectedProject) +started: "Creating resources in project " + D(p.input.selectedProject), +success: "Creating resources in project " + D(p.input.selectedProject), +failure: "Failed to create some resources in project " + D(p.input.selectedProject) }, t = {}; d.add(e, t, p.input.selectedProject.metadata.name, function() { var e = n.defer(); @@ -10029,9 +10059,9 @@ hasErrors: r } function P() { var e = { -started: "Updating resources in project " + A(p.input.selectedProject), -success: "Updated resources in project " + A(p.input.selectedProject), -failure: "Failed to update some resources in project " + A(p.input.selectedProject) +started: "Updating resources in project " + D(p.input.selectedProject), +success: "Updated resources in project " + D(p.input.selectedProject), +failure: "Failed to update some resources in project " + D(p.input.selectedProject) }, t = {}; d.add(e, t, p.input.selectedProject.metadata.name, function() { var e = n.defer(); @@ -10114,7 +10144,7 @@ type: "error" }).length ? (_.each(E, function(e) { e.id = _.uniqueId("from-file-alert-"), c.addNotification(e); }), p.disableInputs = !1) : E.length ? (R(E), p.disableInputs = !1) : y(); -}, D = function() { +}, A = function() { if (_.has(p.input.selectedProject, "metadata.uid")) return n.when(p.input.selectedProject); var t = p.input.selectedProject.metadata.name, r = p.input.selectedProject.metadata.annotations["new-display-name"], a = e("description")(p.input.selectedProject); return m.create(t, r, a); @@ -10129,7 +10159,7 @@ var e = []; p.errorOccurred = !1, _.forEach(p.resourceList, function(t) { if (!g(t)) return p.errorOccurred = !0, !1; e.push(S(t)); -}), D().then(function(t) { +}), A().then(function(t) { p.input.selectedProject = t, n.all(e).then(function() { p.errorOccurred || (1 === p.createResources.length && "Template" === p.resourceList[0].kind ? v() : _.isEmpty(p.updateResources) ? l.getLatestQuotaAlerts(p.createResources, { namespace: p.input.selectedProject.metadata.name @@ -10147,7 +10177,7 @@ details: I(e) }, p.cancel = function() { T(), s.toProjectOverview(p.input.selectedProject.metadata.name); }; -var A = e("displayName"); +var D = e("displayName"); p.$on("importFileFromYAMLOrJSON", p.create), p.$on("$destroy", T); } ] }; @@ -11026,11 +11056,11 @@ _.size(h) <= 100 ? (y = e("orderByDisplayName")(h), T = _.map(y, function(e) { return n(e, !1); })) : T = [ n(h[t], !0) ], E.empty(), E.append(T), E.append($('')), E.append($('')), E.selectpicker("refresh"); } -}, D = function() { +}, A = function() { return f.list().then(function(e) { h = e.by("metadata.name"); }); -}, A = function() { +}, D = function() { k(R); var e = a.project; if (i.currentProjectName !== e) { @@ -11047,7 +11077,7 @@ n.all([ r, a ]).then(function() { i.catalogItems = c.sortCatalogItems(_.concat(t, o)); }); } -}), D().then(function() { +}), A().then(function() { i.currentProjectName && h && (h[i.currentProjectName] || (h[i.currentProjectName] = { metadata: { name: i.currentProjectName @@ -11087,7 +11117,7 @@ m.toProjectCatalog(i.currentProjectName, n); }); i.closeOrderingPanel = function() { v.addItem(_.get(i.selectedItem, "resource.metadata.uid")), i.orderingPanelVisible = !1; -}, A(), i.$on("$routeChangeSuccess", A), E.change(function() { +}, D(), i.$on("$routeChangeSuccess", D), E.change(function() { var e = $(this).val(), t = "" === e ? "projects" : g(e); I(t); }), i.$on("$destroy", function() { @@ -12083,7 +12113,7 @@ Available: "#d1d1d1" } }; R[t.id] ? R[t.id].load(a) : ((n = B(e)).data = a, r(function() { -A || (R[t.id] = c3.generate(n)); +D || (R[t.id] = c3.generate(n)); })); } } @@ -12099,7 +12129,7 @@ var n, a = c.getSparklineData(t), o = e.chartPrefix + "sparkline"; E[o] ? E[o].load(a) : ((n = V(e)).data = a, e.chartDataColors && (n.color = { pattern: e.chartDataColors }), r(function() { -A || (E[o] = c3.generate(n)); +D || (E[o] = c3.generate(n)); })); } } @@ -12110,7 +12140,7 @@ function h() { return 60 * m.options.timeRange.value * 1e3; } function y() { -return Math.floor(h() / D) + "ms"; +return Math.floor(h() / A) + "ms"; } function b(e, t, n) { var r, a = { @@ -12125,12 +12155,12 @@ containerName: e.containerMetric ? m.options.selectedContainer.name : "pod" }) : null; } function S() { -A || (L = 0, _.each(m.metrics, function(e) { +D || (L = 0, _.each(m.metrics, function(e) { g(e), f(e); })); } function C(e) { -if (!A) if (L++, m.noData) m.metricsError = { +if (!D) if (L++, m.noData) m.metricsError = { status: _.get(e, "status", 0), details: _.get(e, "data.errorMsg") || _.get(e, "statusText") || "Status code " + _.get(e, "status", 0) }; else if (!(L < 2)) { @@ -12159,7 +12189,7 @@ isNaN(r) && (r = 0), e.convert && (r = e.convert(r)), t.used = d3.round(r, e.usa function j(e, t) { m.noData = !1; var n = _.initial(t.data); -e.data ? e.data = _.chain(e.data).takeRight(D).concat(n).value() : e.data = n; +e.data ? e.data = _.chain(e.data).takeRight(A).concat(n).value() : e.data = n; } function k() { if (w()) { @@ -12175,7 +12205,7 @@ P(n, a, e); })); } }), t = t.concat(r), a.all(r).then(function(e) { -A || angular.forEach(e, function(e) { +D || angular.forEach(e, function(e) { e && j(_.find(n.datasets, { id: e.metricID }), e); @@ -12187,7 +12217,7 @@ m.loaded = !0; } } m.includedMetrics = m.includedMetrics || [ "cpu", "memory", "network" ]; -var I, R = {}, E = {}, T = n("resources.limits.memory"), N = n("resources.limits.cpu"), D = 30, A = !1; +var I, R = {}, E = {}, T = n("resources.limits.memory"), N = n("resources.limits.cpu"), A = 30, D = !1; m.uniqueID = c.uniqueID(), m.metrics = [], _.includes(m.includedMetrics, "memory") && m.metrics.push({ label: "Memory", units: "MiB", @@ -12291,7 +12321,7 @@ I && (t.cancel(I), I = null), O && (O(), O = null), angular.forEach(R, function( e.destroy(); }), R = null, angular.forEach(E, function(e) { e.destroy(); -}), E = null, A = !0; +}), E = null, D = !0; }); } }; @@ -12353,7 +12383,7 @@ return e[0]; function u(e) { P || (N = 0, t.showAverage = _.size(t.pods) > 5 || w, _.each(t.metrics, function(n) { var r, a = o(e, n), i = n.descriptor; -w && n.compactCombineWith && (i = n.compactCombineWith, n.lastValue && (T[i].lastValue = (T[i].lastValue || 0) + n.lastValue)), S[i] ? (S[i].load(a), t.showAverage ? S[i].legend.hide() : S[i].legend.show()) : ((r = D(n)).data = a, S[i] = c3.generate(r)); +w && n.compactCombineWith && (i = n.compactCombineWith, n.lastValue && (T[i].lastValue = (T[i].lastValue || 0) + n.lastValue)), S[i] ? (S[i].load(a), t.showAverage ? S[i].legend.hide() : S[i].legend.show()) : ((r = A(n)).data = a, S[i] = c3.generate(r)); })); } function d() { @@ -12483,7 +12513,7 @@ t.metricsURL = e; }), t.options = { rangeOptions: s.getTimeRangeOptions() }, t.options.timeRange = _.head(t.options.rangeOptions), t.options.selectedContainer = _.head(t.containers); -var D = function(e) { +var A = function(e) { var n = s.getDefaultSparklineConfig(e.chartID, e.units, w); return _.set(n, "legend.show", !w && !t.showAverage), n; }; @@ -12492,21 +12522,21 @@ I = {}, j = null, delete t.metricsError, y(); }, !0), b = e(y, s.getDefaultUpdateInterval(), !1), t.updateInView = function(e) { R = !e, e && (!k || Date.now() > k + s.getDefaultUpdateInterval()) && y(); }; -var A = a.$on("metrics.charts.resize", function() { +var D = a.$on("metrics.charts.resize", function() { s.redraw(S); }); t.$on("$destroy", function() { -b && (e.cancel(b), b = null), A && (A(), A = null), angular.forEach(S, function(e) { +b && (e.cancel(b), b = null), D && (D(), D = null), angular.forEach(S, function(e) { e.destroy(); }), S = null, P = !0; }); } }; -} ]), angular.module("openshiftConsole").directive("logViewer", [ "$sce", "$timeout", "$window", "$filter", "$q", "AuthService", "APIService", "APIDiscovery", "DataService", "HTMLService", "ModalsService", "logLinks", "BREAKPOINTS", function(e, t, n, r, a, o, i, s, c, l, u, d) { -var m = $(window), p = $('').get(0), f = function(e, t) { -var n = p.cloneNode(!0); +} ]), angular.module("openshiftConsole").directive("logViewer", [ "$sce", "$timeout", "$window", "$filter", "$q", "AggregatedLoggingService", "APIService", "APIDiscovery", "AuthService", "DataService", "HTMLService", "ModalsService", "logLinks", "BREAKPOINTS", function(e, t, n, r, a, o, i, s, c, l, u, d, m) { +var p = $(window), f = $('').get(0), g = function(e, t) { +var n = f.cloneNode(!0); n.firstChild.setAttribute("data-line-number", e); -var r = ansi_up.escape_for_html(t), a = ansi_up.ansi_to_html(r), o = l.linkify(a, "_blank", !0); +var r = ansi_up.escape_for_html(t), a = ansi_up.ansi_to_html(r), o = u.linkify(a, "_blank", !0); return n.lastChild.innerHTML = o, n; }; return { @@ -12525,70 +12555,70 @@ chromeless: "=?", empty: "=?", run: "=?" }, -controller: [ "$scope", function(t) { -var o, l, u, p = document.documentElement; -t.logViewerID = _.uniqueId("log-viewer"), t.empty = !0; -var g, v; -"ReplicationController" === t.object.kind ? (g = "deploymentconfigs/log", v = r("annotation")(t.object, "deploymentConfig")) : (g = i.kindToResource(t.object.kind) + "/log", v = t.object.metadata.name); +controller: [ "$scope", function(e) { +var t, c, u, d = document.documentElement; +e.logViewerID = _.uniqueId("log-viewer"), e.empty = !0; +var f, v; +"ReplicationController" === e.object.kind ? (f = "deploymentconfigs/log", v = r("annotation")(e.object, "deploymentConfig")) : (f = i.kindToResource(e.object.kind) + "/log", v = e.object.metadata.name); var h, y = function() { -t.$apply(function() { -var e = o.getBoundingClientRect(); -t.fixedHeight ? t.showScrollLinks = e && e.height > t.fixedHeight : t.showScrollLinks = e && (e.top < 0 || e.bottom > p.clientHeight); +e.$apply(function() { +var n = t.getBoundingClientRect(); +e.fixedHeight ? e.showScrollLinks = n && n.height > e.fixedHeight : e.showScrollLinks = n && (n.top < 0 || n.bottom > d.clientHeight); }); }, b = !1, S = function() { -b ? b = !1 : t.$evalAsync(function() { -t.autoScrollActive = !1; +b ? b = !1 : e.$evalAsync(function() { +e.autoScrollActive = !1; }); }, C = function() { -l ? $(l).on("scroll", S) : m.on("scroll", S); +c ? $(c).on("scroll", S) : p.on("scroll", S); }, w = function() { -t.fixedHeight || u.affix({ +e.fixedHeight || u.affix({ target: window, offset: { -top: t.followAffixTop || 0 +top: e.followAffixTop || 0 } }); }, P = function() { -return $("#" + t.logViewerID + " .log-view-output"); -}, j = function(e) { +return $("#" + e.logViewerID + " .log-view-output"); +}, j = function(t) { var n = P(), r = n.offset().top; if (!(r < 0)) { -var a = $(".ellipsis-pulser").outerHeight(!0), o = t.fixedHeight ? t.fixedHeight : Math.floor($(window).height() - r - a); -t.chromeless || t.fixedHeight || (o -= 40), e ? n.animate({ +var a = $(".ellipsis-pulser").outerHeight(!0), o = e.fixedHeight ? e.fixedHeight : Math.floor($(window).height() - r - a); +e.chromeless || e.fixedHeight || (o -= 40), t ? n.animate({ "min-height": o + "px" -}, "fast") : n.css("min-height", o + "px"), t.fixedHeight && n.css("max-height", o); +}, "fast") : n.css("min-height", o + "px"), e.fixedHeight && n.css("max-height", o); } }, k = function() { if (!h) { -var e = function() { -clearInterval(h), h = null, t.$evalAsync(function() { -t.sized = !0; +var t = function() { +clearInterval(h), h = null, e.$evalAsync(function() { +e.sized = !0; }); }, n = 0; h = setInterval(function() { -n > 10 ? e() : (n++, P().is(":visible") && (j(), e())); +n > 10 ? t() : (n++, P().is(":visible") && (j(), t())); }, 100); } }, I = _.debounce(function() { j(!0), y(), S(); }, 100); -m.on("resize", I); +p.on("resize", I); var R, E = function() { -b = !0, d.scrollBottom(l); +b = !0, m.scrollBottom(c); }, T = document.createDocumentFragment(), N = _.debounce(function() { -o.appendChild(T), T = document.createDocumentFragment(), t.autoScrollActive && E(), t.showScrollLinks || y(); +t.appendChild(T), T = document.createDocumentFragment(), e.autoScrollActive && E(), e.showScrollLinks || y(); }, 100, { maxWait: 300 -}), D = function(e) { -var t = a.defer(); +}), A = function(e) { +var n = a.defer(); return R ? (R.onClose(function() { -t.resolve(); -}), R.stop()) : t.resolve(), e || (N.cancel(), o && (o.innerHTML = ""), T = document.createDocumentFragment()), t.promise; -}, A = function() { -D().then(function() { -t.$evalAsync(function() { -if (t.run) { -angular.extend(t, { +n.resolve(); +}), R.stop()) : n.resolve(), e || (N.cancel(), t && (t.innerHTML = ""), T = document.createDocumentFragment()), n.promise; +}, D = function() { +A().then(function() { +e.$evalAsync(function() { +if (e.run) { +angular.extend(e, { loading: !0, autoScrollActive: !0, largeLog: !1, @@ -12596,87 +12626,89 @@ limitReached: !1, showScrollLinks: !1, state: "" }); -var e = angular.extend({ +var t = angular.extend({ follow: !0, tailLines: 5e3, limitBytes: 10485760 -}, t.options), n = 0, r = "", a = function(e) { +}, e.options), n = 0, r = "", a = function(e) { return /\n$/.test(e); }, o = function(e) { return e.match(/^.*(\n|$)/gm); }, i = function(e) { var t = r + e; -a(e) ? (r = "", n++, T.appendChild(f(n, t)), N()) : r = t; +a(e) ? (r = "", n++, T.appendChild(g(n, t)), N()) : r = t; }, s = function(e) { var t = o(e); _.each(t, i); }; -(R = c.createStream(g, v, t.context, e)).onMessage(function(r, a, o) { -t.$evalAsync(function() { -t.empty = !1, "logs" !== t.state && (t.state = "logs", k()); -}), r && (e.limitBytes && o >= e.limitBytes && (t.$evalAsync(function() { -t.limitReached = !0, t.loading = !1; -}), D(!0)), s(r), !t.largeLog && n >= e.tailLines && t.$evalAsync(function() { -t.largeLog = !0; +(R = l.createStream(f, v, e.context, t)).onMessage(function(r, a, o) { +e.$evalAsync(function() { +e.empty = !1, "logs" !== e.state && (e.state = "logs", k()); +}), r && (t.limitBytes && o >= t.limitBytes && (e.$evalAsync(function() { +e.limitReached = !0, e.loading = !1; +}), A(!0)), s(r), !e.largeLog && n >= t.tailLines && e.$evalAsync(function() { +e.largeLog = !0; })); }), R.onClose(function() { -R = null, t.$evalAsync(function() { -t.loading = !1, t.autoScrollActive = !1, 0 !== n || t.emptyStateMessage || (t.state = "empty", t.emptyStateMessage = "The logs are no longer available or could not be loaded."); +R = null, e.$evalAsync(function() { +e.loading = !1, e.autoScrollActive = !1, 0 !== n || e.emptyStateMessage || (e.state = "empty", e.emptyStateMessage = "The logs are no longer available or could not be loaded."); }); }), R.onError(function() { -R = null, t.$evalAsync(function() { -angular.extend(t, { +R = null, e.$evalAsync(function() { +angular.extend(e, { loading: !1, autoScrollActive: !1 -}), 0 === n ? (t.state = "empty", t.emptyStateMessage = "The logs are no longer available or could not be loaded.") : t.errorWhileRunning = !0; +}), 0 === n ? (e.state = "empty", e.emptyStateMessage = "The logs are no longer available or could not be loaded.") : e.errorWhileRunning = !0; }); }), R.start(); } }); }); }; -if (s.getLoggingURL(t.context.project).then(function(a) { -var o = _.get(t.context, "project.metadata.name"), i = _.get(t.options, "container"); -o && i && v && a && t.$watchGroup([ "context.project.metadata.name", "options.container", "name" ], function() { -angular.extend(t, { -kibanaArchiveUrl: e.trustAsResourceUrl(d.archiveUri({ -baseURL: a, -namespace: t.context.project.metadata.name, -namespaceUid: t.context.project.metadata.uid, +if (s.getLoggingURL(e.context.project).then(function(t) { +var a = _.get(e.context, "project.metadata.name"), i = _.get(e.options, "container"); +a && i && v && t && o.isOperationsUser().then(function(a) { +e.$watchGroup([ "context.project.metadata.name", "options.container", "name" ], function() { +angular.extend(e, { +kibanaArchiveUrl: m.archiveUri({ +baseURL: t, +namespace: e.context.project.metadata.name, +namespaceUid: e.context.project.metadata.uid, podname: v, -containername: t.options.container, +containername: e.options.container, backlink: URI.encode(n.location.href) -}, r("annotation")(t.context.project, "loggingDataPrefix"))) +}, r("annotation")(e.context.project, "loggingDataPrefix"), a) +}); }); }); }), this.cacheScrollableNode = function(e) { -l = e; +c = e; }, this.cacheLogNode = function(e) { -o = e; +t = e; }, this.cacheAffixable = function(e) { u = $(e); }, this.start = function() { C(), w(); -}, angular.extend(t, { +}, angular.extend(e, { ready: !0, loading: !0, autoScrollActive: !0, state: !1, onScrollBottom: function() { -d.scrollBottom(l); +m.scrollBottom(c); }, onScrollTop: function() { -t.autoScrollActive = !1, d.scrollTop(l), $("#" + t.logViewerID + "-affixedFollow").affix("checkPosition"); +e.autoScrollActive = !1, m.scrollTop(c), $("#" + e.logViewerID + "-affixedFollow").affix("checkPosition"); }, toggleAutoScroll: function() { -t.autoScrollActive = !t.autoScrollActive, t.autoScrollActive && E(); +e.autoScrollActive = !e.autoScrollActive, e.autoScrollActive && E(); }, -goChromeless: d.chromelessLink, -restartLogs: A -}), t.$on("$destroy", function() { -D(), m.off("resize", I), m.off("scroll", S), l && $(l).off("scroll", S); -}), "deploymentconfigs/logs" === g && !v) return t.state = "empty", void (t.emptyStateMessage = "Logs are not available for this replication controller because it was not generated from a deployment configuration."); -t.$watchGroup([ "name", "options.container", "run" ], A); +goChromeless: m.chromelessLink, +restartLogs: D +}), e.$on("$destroy", function() { +A(), p.off("resize", I), p.off("scroll", S), c && $(c).off("scroll", S); +}), "deploymentconfigs/logs" === f && !v) return e.state = "empty", void (e.emptyStateMessage = "Logs are not available for this replication controller because it was not generated from a deployment configuration."); +e.$watchGroup([ "name", "options.container", "run" ], D); } ], require: "logViewer", link: function(e, n, r, a) { @@ -12690,7 +12722,7 @@ type: "text/plain;charset=utf-8" saveAs(a, r); }; e.canSave = !!new Blob(), e.saveLog = function() { -e.largeLog ? u.confirmSaveLog(e.object).then(o) : o(); +e.largeLog ? d.confirmSaveLog(e.object).then(o) : o(); }; } }; @@ -14874,7 +14906,7 @@ cancelButtonText: "Cancel" } } }).result.then(T); -}, D = function(e) { +}, A = function(e) { b = e.quotaAlerts || []; var t = _.filter(b, { type: "error" @@ -14891,7 +14923,7 @@ namespace: n.input.selectedProject.metadata.name }), i = function(e) { return n.nameTaken = e.nameTaken, r; }; -t.then(i, i).then(D, D); +t.then(i, i).then(A, A); }, function(e) { n.disableInputs = !1, "AlreadyExists" === e.data.reason ? n.projectNameTaken = !0 : l.addNotification({ id: "deploy-image-create-project-error", @@ -15363,7 +15395,7 @@ namespace: e.namespace S[a.project] && delete S[a.project][e.uid], b[a.project] && delete b[a.project][e.uid], E(e); }, N = function() { b[a.project] = {}, S[a.project] = {}; -}, D = function(e) { +}, A = function(e) { return _.reduce(e, function(e, t) { return e[t.metadata.uid] = { actions: null, @@ -15376,7 +15408,7 @@ firstTimestamp: t.firstTimestamp, event: t }, e; }, {}); -}, A = function(e) { +}, D = function(e) { return _.reduce(e, function(e, t) { return u.isImportantAPIEvent(t) && !u.isCleared(t.metadata.uid) && (e[t.metadata.uid] = t), e; }, {}); @@ -15398,7 +15430,7 @@ m && (l.unwatch(m), m = null); }, U = function() { d && d(), d = null; }, F = function(e) { -b[a.project] = D(A(e.by("metadata.name"))), V(); +b[a.project] = A(D(e.by("metadata.name"))), V(); }, x = function(e, t) { var n = t.namespace || a.project, r = t.id ? n + "/" + t.id : _.uniqueId("notification_") + Date.now(); t.showInDrawer && !u.isCleared(r) && (S[n] = S[n] || {}, S[n][r] = { @@ -16683,8 +16715,8 @@ a.addSearch(e); }), r.open(a.toString(), "_blank"); } }, -archiveUri: function(e, t) { -return t = t || "project." + e.namespace + "." + e.namespaceUid, e.index = t + ".*", "/" !== e.baseURL.substr(-1) && (e.baseURL += "/"), a(e); +archiveUri: function(e, t, n) { +return !n || t && !t.startsWith("project.") || (t = "project"), t = t || "project." + e.namespace + "." + e.namespaceUid, e.index = t + ".*", "/" !== e.baseURL.substr(-1) && (e.baseURL += "/"), a(e); } }; } ]), angular.module("javaLinkExtension", [ "openshiftConsole" ]).run([ "AuthService", "BaseHref", "DataService", "extensionRegistry", function(e, t, n, r) { diff --git a/dist/scripts/templates.js b/dist/scripts/templates.js index 61e1a25f36..1ac18cd2ac 100644 --- a/dist/scripts/templates.js +++ b/dist/scripts/templates.js @@ -7751,14 +7751,8 @@ angular.module('openshiftConsoleTemplates', []).run(['$templateCache', function( "

\n" + "{{emptyStateMessage}}\n" + "

\n" + - "
\n" + - "
\n" + - "\n" + - "\n" + - "\n" + - "
\n" + + "
\n" + + "View Archive\n" + "
\n" + "
\n" + "\n" + diff --git a/dist/scripts/vendor.js b/dist/scripts/vendor.js index e2bf61fb87..f22ba64654 100644 --- a/dist/scripts/vendor.js +++ b/dist/scripts/vendor.js @@ -74439,7 +74439,7 @@ return isNaN(Number(e)) ? e : Number(e); } function i(e) { if ("string" != typeof e) throw new TypeError("Invalid argument expected string"); -if (!r.test(e)) throw new Error("Invalid argument not valid semver"); +if (!r.test(e)) throw new Error("Invalid argument not valid semver ('" + e + "' received)"); } var r = /^v?(?:\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+))?(?:-[\da-z\-]+(?:\.[\da-z\-]+)*)?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i; return function(e, r) {