|
|
|
/// <reference path="../../includes.ts"/>
|
|
|
|
/// <reference path="../../kubernetes/ts/kubernetesHelpers.ts" />
|
|
|
|
|
|
|
|
module Developer {
|
|
|
|
|
|
|
|
export var context = '/workspaces';
|
|
|
|
export var hash = '#' + context;
|
|
|
|
export var pluginName = 'Developer';
|
|
|
|
export var pluginPath = 'plugins/developer/';
|
|
|
|
export var templatePath = pluginPath + 'html/';
|
|
|
|
export var log:Logging.Logger = Logger.get(pluginName);
|
|
|
|
|
|
|
|
export var jenkinsServiceName = "jenkins";
|
|
|
|
export var jenkinsServiceNameAndPort = jenkinsServiceName + ":http";
|
|
|
|
|
|
|
|
export var jenkinsHttpConfig = {
|
|
|
|
headers: {
|
|
|
|
Accept: "application/json, text/x-json, text/plain"
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns true if the value hasn't changed from the last cached JSON version of this object
|
|
|
|
*/
|
|
|
|
export function hasObjectChanged(value, state) {
|
|
|
|
var json = angular.toJson(value || "");
|
|
|
|
var oldJson = state.json;
|
|
|
|
state.json = json;
|
|
|
|
return !oldJson || json !== oldJson;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function projectForScope($scope) {
|
|
|
|
if ($scope) {
|
|
|
|
return $scope.buildConfig || $scope.entity || ($scope.model || {}).project;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Lets load the project versions for the given namespace
|
|
|
|
*/
|
|
|
|
export function loadProjectVersions($scope, $element, project, env, ns, answer, caches) {
|
|
|
|
var projectAnnotation = "project";
|
|
|
|
var versionAnnotation = "version";
|
|
|
|
|
|
|
|
var projectNamespace = project.$namespace;
|
|
|
|
var projectName = project.$name;
|
|
|
|
|
|
|
|
var cache = caches[ns];
|
|
|
|
if (!cache) {
|
|
|
|
cache = {};
|
|
|
|
caches[ns] = cache;
|
|
|
|
}
|
|
|
|
|
|
|
|
var status = {
|
|
|
|
rcs: [],
|
|
|
|
pods: [],
|
|
|
|
routes: [],
|
|
|
|
services: []
|
|
|
|
};
|
|
|
|
|
|
|
|
var imageStreamTags = [];
|
|
|
|
|
|
|
|
function updateModel() {
|
|
|
|
var projectInfos = {};
|
|
|
|
var model = $scope.model || {};
|
|
|
|
|
|
|
|
angular.forEach(status.rcs, (item) => {
|
|
|
|
var metadata = item.metadata || {};
|
|
|
|
var name = metadata.name;
|
|
|
|
var labels = metadata.labels || {};
|
|
|
|
var annotations = metadata.annotations || {};
|
|
|
|
var spec = item.spec || {};
|
|
|
|
var selector = spec.selector;
|
|
|
|
|
|
|
|
var project = labels[projectAnnotation];
|
|
|
|
var version = labels[versionAnnotation];
|
|
|
|
|
|
|
|
// lets try the S2I defaults...
|
|
|
|
if (!project) {
|
|
|
|
project = labels["app"];
|
|
|
|
}
|
|
|
|
if (!version) {
|
|
|
|
version = annotations["openshift.io/deployment-config.latest-version"]
|
|
|
|
}
|
|
|
|
if (project && version && project === projectName) {
|
|
|
|
var projects = projectInfos[project];
|
|
|
|
if (!projects) {
|
|
|
|
projects = {
|
|
|
|
project: project,
|
|
|
|
versions: {}
|
|
|
|
};
|
|
|
|
projectInfos[project] = projects;
|
|
|
|
}
|
|
|
|
var versionInfo = projects.versions[version];
|
|
|
|
if (!versionInfo) {
|
|
|
|
versionInfo = {
|
|
|
|
replicationControllers: {}
|
|
|
|
};
|
|
|
|
projects.versions[version] = versionInfo;
|
|
|
|
}
|
|
|
|
if (name) {
|
|
|
|
versionInfo.replicationControllers[name] = item;
|
|
|
|
item.$name = name;
|
|
|
|
if (projectNamespace && projectName) {
|
|
|
|
item.$viewLink = UrlHelpers.join("/workspaces/", projectNamespace, "projects", projectName, "namespace", ns, "replicationControllers", name);
|
|
|
|
} else {
|
|
|
|
log.warn("Missing project data! " + projectNamespace + " name " + projectName);
|
|
|
|
}
|
|
|
|
|
|
|
|
item.$services = [];
|
|
|
|
var rcLink = null;
|
|
|
|
status.services.forEach((service) => {
|
|
|
|
var repSelector = Kubernetes.getSelector(item);
|
|
|
|
var serviceSelector = Kubernetes.getSelector(service);
|
|
|
|
if (serviceSelector && repSelector &&
|
|
|
|
Kubernetes.selectorMatches(serviceSelector, repSelector) &&
|
|
|
|
Kubernetes.getNamespace(service) === Kubernetes.getNamespace(item)) {
|
|
|
|
status.routes.forEach((route) => {
|
|
|
|
var serviceName = Kubernetes.getName(service);
|
|
|
|
if (serviceName === Kubernetes.getName(route)) {
|
|
|
|
service["$route"] = route;
|
|
|
|
service["$host"] = Core.pathGet(route, ["spec", "host"]);
|
|
|
|
item.$services.push(service);
|
|
|
|
if (!rcLink) {
|
|
|
|
var url = Kubernetes.serviceLinkUrl(service, true);
|
|
|
|
if (url) {
|
|
|
|
// TODO find icon etc?
|
|
|
|
rcLink = {
|
|
|
|
name: serviceName,
|
|
|
|
href: url
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
item["$serviceLink"] = rcLink;
|
|
|
|
}
|
|
|
|
item.$buildId = annotations["fabric8.io/build-id"] || item.$buildId;
|
|
|
|
item.$buildUrl = annotations["fabric8.io/build-url"] || item.$buildUrl;
|
|
|
|
item.$gitCommit = annotations["fabric8.io/git-commit"] || item.$gitCommit;
|
|
|
|
item.$gitUrl = annotations["fabric8.io/git-url"] || item.$gitUrl;
|
|
|
|
item.$gitBranch = annotations["fabric8.io/git-branch"] || item.$gitBranch;
|
|
|
|
if (!item.$gitCommit) {
|
|
|
|
var image = getImage(item);
|
|
|
|
if (image) {
|
|
|
|
if (!$scope.$isWatchImages) {
|
|
|
|
$scope.$isWatchImages = true;
|
|
|
|
Kubernetes.watch($scope, $element, "images", null, (data) => {
|
|
|
|
imageStreamTags = data;
|
|
|
|
checkForMissingMetadata();
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
checkForMissingMetadata();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function getImage(item) {
|
|
|
|
var image = "";
|
|
|
|
// lets see if we can find the commit id from a S2I image name
|
|
|
|
// TODO needs this issue fixed to find it via an OpenShift annotation:
|
|
|
|
// https://github.com/openshift/origin/issues/6241
|
|
|
|
var containers = Core.pathGet(item, ["spec", "template", "spec", "containers"]);
|
|
|
|
if (containers && containers.length) {
|
|
|
|
var container = containers[0];
|
|
|
|
if (container) {
|
|
|
|
image = container.image;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return image;
|
|
|
|
}
|
|
|
|
|
|
|
|
function checkForMissingMetadata() {
|
|
|
|
angular.forEach(projects.versions, (vi) => {
|
|
|
|
angular.forEach(vi.replicationControllers, (item, name) => {
|
|
|
|
if (!item.$gitCommit) {
|
|
|
|
var image = getImage(item);
|
|
|
|
if (image) {
|
|
|
|
angular.forEach(imageStreamTags, (imageStreamTag) => {
|
|
|
|
var imageName = imageStreamTag.dockerImageReference;
|
|
|
|
if (imageName && imageName === image) {
|
|
|
|
var foundISTag = imageStreamTag;
|
|
|
|
var manifestJSON = imageStreamTag.dockerImageManifest;
|
|
|
|
if (manifestJSON) {
|
|
|
|
var manifest = angular.fromJson(manifestJSON) || {};
|
|
|
|
var history = manifest.history;
|
|
|
|
if (history && history.length) {
|
|
|
|
var v1 = history[0].v1Compatibility;
|
|
|
|
if (v1) {
|
|
|
|
var data = angular.fromJson(v1);
|
|
|
|
var env = Core.pathGet(data, ["config", "Env"]);
|
|
|
|
angular.forEach(env, (envExp) => {
|
|
|
|
if (envExp) {
|
|
|
|
var values = envExp.split("=");
|
|
|
|
if (values.length === 2 && values[0] == "OPENSHIFT_BUILD_NAME") {
|
|
|
|
var buildName = values[1];
|
|
|
|
if (buildName) {
|
|
|
|
item.$buildId = buildName;
|
|
|
|
item.$buildUrl = Developer.projectWorkspaceLink(ns, projectName, "buildLogs/" + buildName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
var labels = Core.pathGet(data, ["config", "Labels"]);
|
|
|
|
if (labels) {
|
|
|
|
item.$gitCommit = labels["io.openshift.build.commit.id"] || item.$gitCommit;
|
|
|
|
item.$gitCommitAuthor = labels["io.openshift.build.commit.author"] || item.$gitCommitAuthor;
|
|
|
|
item.$gitCommitDate = labels["io.openshift.build.commit.date"] || item.$gitCommitDate;
|
|
|
|
item.$gitCommitMessage = labels["io.openshift.build.commit.message"] || item.$gitCommitMessage;
|
|
|
|
item.$gitBranch = labels["io.openshift.build.commit.ref"] || item.$gitBranch;
|
|
|
|
|
|
|
|
if (!item.$gitUrl && item.$gitCommit) {
|
|
|
|
item.$gitUrl = Developer.projectWorkspaceLink(ns, projectName, "wiki/commitDetail///" + item.$gitCommit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (selector) {
|
|
|
|
var selectorText = Kubernetes.labelsToString(selector, ",");
|
|
|
|
var podLinkUrl = UrlHelpers.join(projectLink(projectName), "namespace", ns, "pods");
|
|
|
|
item.pods = [];
|
|
|
|
item.$podCounters = Kubernetes.createPodCounters(selector, status.pods, item.pods, selectorText, podLinkUrl);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// lets check for a project name if we have lots of RCs with no pods, lets remove them!
|
|
|
|
angular.forEach(projectInfos, (project, projectName) => {
|
|
|
|
var rcsNoPods = [];
|
|
|
|
var rcsWithPods = [];
|
|
|
|
angular.forEach(project.versions, (versionInfo) => {
|
|
|
|
var rcs = versionInfo.replicationControllers;
|
|
|
|
angular.forEach(rcs, (item, name) => {
|
|
|
|
var count = Kubernetes.podCounterTotal(item.$podCounters);
|
|
|
|
if (count) {
|
|
|
|
rcsWithPods.push(name);
|
|
|
|
} else {
|
|
|
|
rcsNoPods.push(() => {
|
|
|
|
delete rcs[name];
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
if (rcsWithPods.length) {
|
|
|
|
// lets remove all the empty RCs
|
|
|
|
angular.forEach(rcsNoPods, (fn) => {
|
|
|
|
fn();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
if (hasObjectChanged(projectInfos, cache)) {
|
|
|
|
log.debug("project versions has changed!");
|
|
|
|
answer[ns] = projectInfos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Kubernetes.watch($scope, $element, "replicationcontrollers", ns, (data) => {
|
|
|
|
if (data) {
|
|
|
|
status.rcs = data;
|
|
|
|
updateModel();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
Kubernetes.watch($scope, $element, "services", ns, (data) => {
|
|
|
|
if (data) {
|
|
|
|
status.services = data;
|
|
|
|
updateModel();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
Kubernetes.watch($scope, $element, "routes", ns, (data) => {
|
|
|
|
if (data) {
|
|
|
|
status.routes = data;
|
|
|
|
updateModel();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
Kubernetes.watch($scope, $element, "pods", ns, (data) => {
|
|
|
|
if (data) {
|
|
|
|
status.pods = data;
|
|
|
|
updateModel();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|