From 61c974a03e8f7b5e02ca4bfc1383cffc64381314 Mon Sep 17 00:00:00 2001 From: Jessica Forrester Date: Tue, 24 Feb 2015 17:35:31 -0500 Subject: [PATCH] Builds page - group builds by build config and show more details for build configs --- assets/app/index.html | 1 + assets/app/scripts/controllers/builds.js | 20 +++ assets/app/scripts/directives/util.js | 11 ++ assets/app/scripts/filters/resources.js | 11 ++ assets/app/scripts/filters/util.js | 10 ++ assets/app/scripts/services/data.js | 49 +++-- assets/app/views/builds.html | 161 +++++++++++++++-- pkg/assets/bindata.go | 220 ++++++++++++++++++++--- 8 files changed, 436 insertions(+), 47 deletions(-) create mode 100644 assets/app/scripts/directives/util.js diff --git a/assets/app/index.html b/assets/app/index.html index 32bf3dcde8c3..d693724e3bf4 100644 --- a/assets/app/index.html +++ b/assets/app/index.html @@ -131,6 +131,7 @@ + diff --git a/assets/app/scripts/controllers/builds.js b/assets/app/scripts/controllers/builds.js index 6500aae6165e..4293b2a47e32 100644 --- a/assets/app/scripts/controllers/builds.js +++ b/assets/app/scripts/controllers/builds.js @@ -11,9 +11,13 @@ angular.module('openshiftConsole') .controller('BuildsController', function ($scope, DataService, $filter, LabelFilter) { $scope.builds = {}; $scope.unfilteredBuilds = {}; + $scope.buildConfigs = {}; $scope.labelSuggestions = {}; $scope.alerts = $scope.alerts || {}; $scope.emptyMessage = "Loading..."; + + $scope.buildsByBuildConfig = {}; + var watches = []; watches.push(DataService.watch("builds", $scope, function(builds) { @@ -23,7 +27,23 @@ angular.module('openshiftConsole') $scope.builds = LabelFilter.getLabelSelector().select($scope.unfilteredBuilds); $scope.emptyMessage = "No builds to show"; updateFilterWarning(); + + $scope.buildsByBuildConfig = {}; + angular.forEach($scope.builds, function(build, buildName) { + var buildConfigName = ""; + if (build.metadata.labels) { + buildConfigName = build.metadata.labels.buildconfig || ""; + } + $scope.buildsByBuildConfig[buildConfigName] = $scope.buildsByBuildConfig[buildConfigName] || {}; + $scope.buildsByBuildConfig[buildConfigName][buildName] = build; + }); + console.log("builds (subscribe)", $scope.unfilteredBuilds); + })); + + watches.push(DataService.watch("buildConfigs", $scope, function(buildConfigs) { + $scope.buildConfigs = buildConfigs.by("metadata.name"); + console.log("buildConfigs (subscribe)", $scope.buildConfigs); })); var updateFilterWarning = function() { diff --git a/assets/app/scripts/directives/util.js b/assets/app/scripts/directives/util.js new file mode 100644 index 000000000000..5edf46c4fd24 --- /dev/null +++ b/assets/app/scripts/directives/util.js @@ -0,0 +1,11 @@ +angular.module('openshiftConsole') + .directive('selectOnFocus', function() { + return { + restrict: 'A', + link: function($scope, element, attrs) { + $(element).focus(function () { + $(this).select(); + }); + } + }; + }); \ No newline at end of file diff --git a/assets/app/scripts/filters/resources.js b/assets/app/scripts/filters/resources.js index 233159911a0f..2da49ecf1260 100644 --- a/assets/app/scripts/filters/resources.js +++ b/assets/app/scripts/filters/resources.js @@ -55,4 +55,15 @@ angular.module('openshiftConsole') } return null; }; + }) + .filter('webhookURL', function(DataService) { + return function(buildConfig, type, secret, project) { + return DataService.url({ + type: "buildConfigHooks", + id: buildConfig, + namespace: project, + secret: secret, + hookType: type, + }); + }; }); \ No newline at end of file diff --git a/assets/app/scripts/filters/util.js b/assets/app/scripts/filters/util.js index 3f57abac7f9b..bf83c0a0d232 100644 --- a/assets/app/scripts/filters/util.js +++ b/assets/app/scripts/filters/util.js @@ -30,4 +30,14 @@ angular.module('openshiftConsole') } return amount + (unit != "" ? " " + unit : ""); } + }) + .filter('helpLink', function() { + return function(type) { + switch(type) { + case "webhooks": + return "http://docs.openshift.org/latest/using_openshift/builds.html#webhook-triggers" + default: + return "http://docs.openshift.org/latest/welcome/index.html"; + } + }; }); \ No newline at end of file diff --git a/assets/app/scripts/services/data.js b/assets/app/scripts/services/data.js index 3d4061a31dd2..d24c340fd2ed 100644 --- a/assets/app/scripts/services/data.js +++ b/assets/app/scripts/services/data.js @@ -535,6 +535,8 @@ angular.module('openshiftConsole') var URL_NAMESPACED_WATCH_LIST = URL_ROOT_TEMPLATE + "watch/namespaces/{namespace}/{type}{?q*}"; var URL_NAMESPACED_GET_LIST = URL_ROOT_TEMPLATE + "namespaces/{namespace}/{type}{?q*}"; var URL_NAMESPACED_GET_OBJECT = URL_ROOT_TEMPLATE + "namespaces/{namespace}/{type}/{id}{?q*}"; + // TODO is there a better way to get this template instead of building it, introspection? + var BUILD_HOOKS_URL = URL_ROOT_TEMPLATE + "{type}/{id}/{secret}/{hookType}{?q*}"; // Set the api version the console is currently able to talk to API_CFG.openshift.version = "v1beta1"; @@ -549,6 +551,8 @@ angular.module('openshiftConsole') // https://github.com/openshift/origin/issues/230 var SERVER_TYPE_MAP = { builds: API_CFG.openshift, + buildConfigs: API_CFG.openshift, + buildConfigHooks: API_CFG.openshift, deploymentConfigs: API_CFG.openshift, images: API_CFG.openshift, oAuthAccessTokens: API_CFG.openshift, @@ -580,27 +584,48 @@ angular.module('openshiftConsole') delete params.namespace; } var template; + var templateOptions = { + protocol: protocol, + serverUrl: SERVER_TYPE_MAP[type].hostPort, + apiPrefix: SERVER_TYPE_MAP[type].prefix, + apiVersion: SERVER_TYPE_MAP[type].version, + type: type, + id: id, + namespace: namespace + }; if (isWebsocket) { template = namespaceInPath ? URL_NAMESPACED_WATCH_LIST : URL_WATCH_LIST; } else if (id) { - template = namespaceInPath ? URL_NAMESPACED_GET_OBJECT : URL_GET_OBJECT; + if (type == "buildConfigHooks") { + templateOptions.secret = params.secret; + templateOptions.hookType = params.hookType; + params = angular.copy(params); + delete params.secret; + delete params.hookType; + template = BUILD_HOOKS_URL; + } + else + { + template = namespaceInPath ? URL_NAMESPACED_GET_OBJECT : URL_GET_OBJECT; + } } else { template = namespaceInPath ? URL_NAMESPACED_GET_LIST : URL_GET_LIST; } - // TODO where do we specify what the server URL and api version should be - return URI.expand(template, { - protocol: protocol, - serverUrl: SERVER_TYPE_MAP[type].hostPort, - apiPrefix: SERVER_TYPE_MAP[type].prefix, - apiVersion: SERVER_TYPE_MAP[type].version, - type: type, - id: id, - namespace: namespace, - q: params - }); + templateOptions.q = params; + return URI.expand(template, templateOptions); + }; + + DataService.prototype.url = function(options) { + if (options && options.type) { + var opts = angular.copy(options); + delete opts.type; + delete opts.id; + return this._urlForType(options.type, options.id, null, false, opts).toString(); + } + return null; }; return new DataService(); diff --git a/assets/app/views/builds.html b/assets/app/views/builds.html index 7819a8651a4c..ae7d3931611e 100644 --- a/assets/app/views/builds.html +++ b/assets/app/views/builds.html @@ -3,25 +3,160 @@

Builds

-
+
{{emptyMessage}}
-
-

{{build.metadata.labels.buildconfig}} ({{build.metadata.name}})

-
Created:
-
Status: {{build.status}}
-
Build strategy: {{build.parameters.strategy.type}}
-
- Builder image: {{build.parameters.strategy.stiStrategy.builderImage}} +
+

{{buildConfigName}}

+
Build strategy: {{buildConfig.parameters.strategy.type}}
+
+
+ Builder image: {{buildConfig.parameters.strategy.stiStrategy.image}} +
+
+
+ Builder image: {{buildConfig.parameters.strategy.dockerStrategy.image}} +
+
+
+ Builder image: {{buildConfig.parameters.strategy.customStrategy.image}} +
-
-
Source repo: {{build.parameters.source.git.uri}}
- +
+
Source repo: {{buildConfig.parameters.source.git.uri}}
+
+
+
+
+ Output image: {{buildConfig.parameters.output.to.name}} +
+
+
+ Output image: {{buildConfig.parameters.output.dockerImageReference}} +
+
+
+ Triggers: +
    +
  • + + + GitHub webhook URL: + + + + Generic webhook URL: + + + + Image change on image repository {{trigger.imageChange.from.name}}:{{trigger.imageChange.tag}} + + {{trigger.type}} + +
  • +
  • Manual: osc start-build {{buildConfigName}} -n {{project.metadata.name}}
  • +
+
+
+

{{build.metadata.name}}

+
Created:
+
+ Status: {{build.status}} + + + + + +
+
+
Build strategy: {{build.parameters.strategy.type}}
+
+
+
+ Builder image: {{build.parameters.strategy.stiStrategy.image}} +
+
+
+ Builder image: {{build.parameters.strategy.dockerStrategy.image}} +
+
+
+ Builder image: {{build.parameters.strategy.customStrategy.image}} +
+
+
+
+
+ Source repo: {{build.parameters.source.git.uri}} +
+
+ +
+
+
+
+
+ Output image: {{buildConfig.parameters.output.to.name}} +
+
+
+
+ Output image: {{build.parameters.output.dockerImageReference}} +
+
+
+
+ +
+

+ {{buildConfigName}} + + + + +

+
+

{{build.metadata.name}}

+
Created:
+
+ Status: {{build.status}} + + + + + +
+
Build strategy: {{build.parameters.strategy.type}}
+
+
+ Builder image: {{build.parameters.strategy.stiStrategy.image}} +
+
+
+ Builder image: {{build.parameters.strategy.dockerStrategy.image}} +
+
+
+ Builder image: {{build.parameters.strategy.customStrategy.image}} +
+
+
+
Source repo: {{build.parameters.source.git.uri}}
+ +
+
+
+
+ Output image: {{build.parameters.output.to.name}} +
+
+
+ Output image: {{build.parameters.output.dockerImageReference}} +
+
-
Output image: {{build.parameters.output.imageTag}}
-
Output image registry: {{build.parameters.output.registry}}
diff --git a/pkg/assets/bindata.go b/pkg/assets/bindata.go index 41b1f745391a..f6aacbfbac0a 100644 --- a/pkg/assets/bindata.go +++ b/pkg/assets/bindata.go @@ -13063,10 +13063,12 @@ f._watchCallbacks(a, b).fire(f._data(a, b), e.type, e.object); }, g.prototype._watchOpOnClose = function(a, b, c) { !c.wasClean && this._watchCallbacks(a, b).has() && this._startWatchOp(a, b, this._resourceVersion(a, b)); }; -var i = "{protocol}://{+serverUrl}{+apiPrefix}/{apiVersion}/", j = i + "watch/{type}{?q*}", k = i + "{type}{?q*}", l = i + "{type}/{id}{?q*}", m = i + "watch/namespaces/{namespace}/{type}{?q*}", n = i + "namespaces/{namespace}/{type}{?q*}", o = i + "namespaces/{namespace}/{type}/{id}{?q*}"; +var i = "{protocol}://{+serverUrl}{+apiPrefix}/{apiVersion}/", j = i + "watch/{type}{?q*}", k = i + "{type}{?q*}", l = i + "{type}/{id}{?q*}", m = i + "watch/namespaces/{namespace}/{type}{?q*}", n = i + "namespaces/{namespace}/{type}{?q*}", o = i + "namespaces/{namespace}/{type}/{id}{?q*}", p = i + "{type}/{id}/{secret}/{hookType}{?q*}"; e.openshift.version = "v1beta1", e.k8s.version = "v1beta3", e.openshift.namespacePath = !1, e.k8s.namespacePath = !0; -var p = { +var q = { builds:e.openshift, +buildConfigs:e.openshift, +buildConfigHooks:e.openshift, deploymentConfigs:e.openshift, images:e.openshift, oAuthAccessTokens:e.openshift, @@ -13081,19 +13083,24 @@ limitranges:e.k8s return g.prototype._urlForType = function(a, b, c, d, e) { var f, e = e || {}; f = d ? "http:" === window.location.protocol ? "ws" :"wss" :"http:" === window.location.protocol ? "http" :"https"; -var g = e.namespace && p[a].namespacePath, h = null; +var g = e.namespace && q[a].namespacePath, h = null; g && (h = e.namespace, e = angular.copy(e), delete e.namespace); -var i; -return i = d ? g ? m :j :b ? g ? o :l :g ? n :k, URI.expand(i, { +var i, r = { protocol:f, -serverUrl:p[a].hostPort, -apiPrefix:p[a].prefix, -apiVersion:p[a].version, +serverUrl:q[a].hostPort, +apiPrefix:q[a].prefix, +apiVersion:q[a].version, type:a, id:b, -namespace:h, -q:e -}); +namespace:h +}; +return d ? i = g ? m :j :b ? "buildConfigHooks" == a ? (r.secret = e.secret, r.hookType = e.hookType, e = angular.copy(e), delete e.secret, delete e.hookType, i = p) :i = g ? o :l :i = g ? n :k, r.q = e, URI.expand(i, r); +}, g.prototype.url = function(a) { +if (a && a.type) { +var b = angular.copy(a); +return delete b.type, delete b.id, this._urlForType(a.type, a.id, null, !1, b).toString(); +} +return null; }, new g(); } ]), angular.module("openshiftConsole").provider("RedirectLoginService", function() { var a = !0, b = "", c = "", d = ""; @@ -13477,10 +13484,15 @@ a.max[c] = a.max[c] || ""; b.unwatchAll(c); }); } ]), angular.module("openshiftConsole").controller("BuildsController", [ "$scope", "DataService", "$filter", "LabelFilter", function(a, b, c, d) { -a.builds = {}, a.unfilteredBuilds = {}, a.labelSuggestions = {}, a.alerts = a.alerts || {}, a.emptyMessage = "Loading..."; +a.builds = {}, a.unfilteredBuilds = {}, a.buildConfigs = {}, a.labelSuggestions = {}, a.alerts = a.alerts || {}, a.emptyMessage = "Loading...", a.buildsByBuildConfig = {}; var e = []; e.push(b.watch("builds", a, function(b) { -a.unfilteredBuilds = b.by("metadata.name"), d.addLabelSuggestionsFromResources(a.unfilteredBuilds, a.labelSuggestions), d.setLabelSuggestions(a.labelSuggestions), a.builds = d.getLabelSelector().select(a.unfilteredBuilds), a.emptyMessage = "No builds to show", f(), console.log("builds (subscribe)", a.unfilteredBuilds); +a.unfilteredBuilds = b.by("metadata.name"), d.addLabelSuggestionsFromResources(a.unfilteredBuilds, a.labelSuggestions), d.setLabelSuggestions(a.labelSuggestions), a.builds = d.getLabelSelector().select(a.unfilteredBuilds), a.emptyMessage = "No builds to show", f(), a.buildsByBuildConfig = {}, angular.forEach(a.builds, function(b, c) { +var d = ""; +b.metadata.labels && (d = b.metadata.labels.buildconfig || ""), a.buildsByBuildConfig[d] = a.buildsByBuildConfig[d] || {}, a.buildsByBuildConfig[d][c] = b; +}), console.log("builds (subscribe)", a.unfilteredBuilds); +})), e.push(b.watch("buildConfigs", a, function(b) { +a.buildConfigs = b.by("metadata.name"), console.log("buildConfigs (subscribe)", a.buildConfigs); })); var f = function() { d.getLabelSelector().isEmpty() || !$.isEmptyObject(a.builds) || $.isEmptyObject(a.unfilteredBuilds) ? delete a.alerts.builds :a.alerts.builds = { @@ -13713,6 +13725,15 @@ $(b).tooltip(); } } }; +}), angular.module("openshiftConsole").directive("selectOnFocus", function() { +return { +restrict:"A", +link:function(a, b) { +$(b).focus(function() { +$(this).select(); +}); +} +}; }), angular.module("openshiftConsole").filter("dateRelative", function() { return function(a) { return moment(a).fromNow(); @@ -13757,7 +13778,17 @@ if ("OPENSHIFT_BUILD_NAME" === e[0]) return b[e[1]]; } return null; }; -}), angular.module("openshiftConsole").filter("hashSize", function() { +}).filter("webhookURL", [ "DataService", function(a) { +return function(b, c, d, e) { +return a.url({ +type:"buildConfigHooks", +id:b, +namespace:e, +secret:d, +hookType:c +}); +}; +} ]), angular.module("openshiftConsole").filter("hashSize", function() { return function(a) { return Object.keys(a).length; }; @@ -13777,6 +13808,16 @@ case "cpu": } return d + ("" != e ? " " + e :""); }; +}).filter("helpLink", function() { +return function(a) { +switch (a) { +case "webhooks": +return "http://docs.openshift.org/latest/using_openshift/builds.html#webhook-triggers"; + +default: +return "http://docs.openshift.org/latest/welcome/index.html"; +} +}; });`) func scripts_scripts_js() ([]byte, error) { @@ -55813,25 +55854,160 @@ var _views_builds_html = []byte(`

Builds

-
+
{{emptyMessage}}
-
-

{{build.metadata.labels.buildconfig}} ({{build.metadata.name}})

+
+

{{buildConfigName}}

+
Build strategy: {{buildConfig.parameters.strategy.type}}
+
+
+Builder image: {{buildConfig.parameters.strategy.stiStrategy.image}} +
+
+
+Builder image: {{buildConfig.parameters.strategy.dockerStrategy.image}} +
+
+
+Builder image: {{buildConfig.parameters.strategy.customStrategy.image}} +
+
+
+
Source repo: {{buildConfig.parameters.source.git.uri}}
+
+
+
+
+Output image: {{buildConfig.parameters.output.to.name}} +
+
+
+Output image: {{buildConfig.parameters.output.dockerImageReference}} +
+
+
+Triggers: +
    +
  • + + +GitHub webhook URL: + + + +Generic webhook URL: + + + +Image change on image repository {{trigger.imageChange.from.name}}:{{trigger.imageChange.tag}} + +{{trigger.type}} + +
  • +
  • Manual: osc start-build {{buildConfigName}} -n {{project.metadata.name}}
  • +
+
+
+

{{build.metadata.name}}

+
Created:
+
+Status: {{build.status}} + + + + + +
+
+
Build strategy: {{build.parameters.strategy.type}}
+
+
+
+Builder image: {{build.parameters.strategy.stiStrategy.image}} +
+
+
+Builder image: {{build.parameters.strategy.dockerStrategy.image}} +
+
+
+Builder image: {{build.parameters.strategy.customStrategy.image}} +
+
+
+
+
+Source repo: {{build.parameters.source.git.uri}} +
+
+ +
+
+
+
+
+Output image: {{buildConfig.parameters.output.to.name}} +
+
+
+
+Output image: {{build.parameters.output.dockerImageReference}} +
+
+
+
+ +
+

+{{buildConfigName}} + + + + +

+
+

{{build.metadata.name}}

Created:
-
Status: {{build.status}}
+
+Status: {{build.status}} + + + + + +
Build strategy: {{build.parameters.strategy.type}}
-
-Builder image: {{build.parameters.strategy.stiStrategy.builderImage}} +
+
+Builder image: {{build.parameters.strategy.stiStrategy.image}} +
+
+
+Builder image: {{build.parameters.strategy.dockerStrategy.image}} +
+
+
+Builder image: {{build.parameters.strategy.customStrategy.image}} +
Source repo: {{build.parameters.source.git.uri}}
-
Output image: {{build.parameters.output.imageTag}}
-
Output image registry: {{build.parameters.output.registry}}
+
+
+
+Output image: {{build.parameters.output.to.name}} +
+
+
+Output image: {{build.parameters.output.dockerImageReference}} +
+
+