Skip to content

Commit 094a415

Browse files
committed
Adding "Run on OpenShift" functionality
1 parent e024781 commit 094a415

27 files changed

+898
-327
lines changed

app/index.html

+2
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ <h1>JavaScript Required</h1>
259259
<script src="scripts/controllers/util/error.js"></script>
260260
<script src="scripts/controllers/util/logout.js"></script>
261261
<script src="scripts/controllers/create.js"></script>
262+
<script src="scripts/controllers/createFromURL.js"></script>
262263
<script src="scripts/controllers/createProject.js"></script>
263264
<script src="scripts/controllers/edit/project.js"></script>
264265
<script src="scripts/controllers/createRoute.js"></script>
@@ -277,6 +278,7 @@ <h1>JavaScript Required</h1>
277278
<script src="scripts/controllers/commandLine.js"></script>
278279
<script src="scripts/controllers/createPersistentVolumeClaim.js"></script>
279280
<script src="scripts/directives/buildClose.js"></script>
281+
<script src="scripts/directives/createProject.js"></script>
280282
<script src="scripts/directives/createSecret.js"></script>
281283
<script src="scripts/directives/date.js"></script>
282284
<script src="scripts/directives/deleteLink.js"></script>

app/scripts/app.js

+4
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,10 @@ angular
381381
templateUrl: 'views/util/logout.html',
382382
controller: 'LogoutController'
383383
})
384+
.when('/create', {
385+
templateUrl: 'views/create-from-url.html',
386+
controller: 'CreateFromURLController'
387+
})
384388
// legacy redirects
385389
.when('/createProject', {
386390
redirectTo: '/create-project'

app/scripts/constants.js

+4
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ window.OPENSHIFT_CONSTANTS = {
7878
namespace: "openshift"
7979
},
8080

81+
// only resources from the namespaces listed below can be utilized with create from url (/create)
82+
// 'openshift' should always be included
83+
CREATE_FROM_URL_WHITELIST: ['openshift'],
84+
8185
// href's will be prefixed with /project/{{projectName}} unless they are absolute URLs
8286
PROJECT_NAVIGATION: [
8387
{

app/scripts/controllers/create/createFromImage.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ angular.module("openshiftConsole")
2929

3030
$scope.projectName = $routeParams.project;
3131
$scope.sourceURLPattern = SOURCE_URL_PATTERN;
32-
var imageName = $routeParams.imageName;
32+
var imageName = $routeParams.imageStream;
3333

3434
if(!imageName){
3535
Navigate.toErrorPage("Cannot create from source: a base image was not specified");
@@ -68,9 +68,13 @@ angular.module("openshiftConsole")
6868
$scope.project = project;
6969
// Update project breadcrumb with display name.
7070
$scope.breadcrumbs[0].title = $filter('displayName')(project);
71+
if($routeParams.sourceURI) {
72+
$scope.sourceURIinParams = true;
73+
}
7174
function initAndValidate(scope){
7275

7376
scope.emptyMessage = "Loading...";
77+
scope.name = $routeParams.name;
7478
scope.imageName = imageName;
7579
scope.imageTag = $routeParams.imageTag;
7680
scope.namespace = $routeParams.namespace;
@@ -80,7 +84,10 @@ angular.module("openshiftConsole")
8084
buildOnConfigChange: true,
8185
secrets: {
8286
gitSecret: [{name: ""}]
83-
}
87+
},
88+
sourceUrl: $routeParams.sourceURI,
89+
gitRef: $routeParams.sourceRef,
90+
contextDir: $routeParams.contextDir
8491
};
8592
scope.buildConfigEnvVars = [];
8693
scope.deploymentConfig = {

app/scripts/controllers/create/nextSteps.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,17 @@ angular.module("openshiftConsole")
2020
$scope.showParamsTable = false;
2121

2222
$scope.projectName = $routeParams.project;
23-
var imageName = $routeParams.imageName;
23+
var imageName = $routeParams.imageStream;
2424
var imageTag = $routeParams.imageTag;
2525
var namespace = $routeParams.namespace;
2626
$scope.fromSampleRepo = $routeParams.fromSample;
2727

28-
var name = $routeParams.name;
28+
var template = $routeParams.template;
2929
var nameLink = "";
3030
if (creatingFromImage()) {
3131
nameLink = "project/" + $scope.projectName + "/create/fromimage?imageName=" + imageName + "&imageTag=" + imageTag + "&namespace=" + namespace + "&name=" + name;
3232
} else if (creatingFromTemplate()) {
33-
nameLink = "project/" + $scope.projectName + "/create/fromtemplate?name=" + name + "&namespace=" + namespace;
33+
nameLink = "project/" + $scope.projectName + "/create/fromtemplate?template=" + template + "&namespace=" + namespace;
3434
}
3535

3636
$scope.breadcrumbs = [
+183
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
'use strict';
2+
3+
/**
4+
* @ngdoc function
5+
* @name openshiftConsole.controller:CreateFromURLController
6+
* @description
7+
* Controller of the openshiftConsole
8+
*/
9+
angular.module('openshiftConsole')
10+
.controller('CreateFromURLController', function ($scope, $routeParams, $location, $filter, AuthService, DataService, AlertMessageService, Navigate, ProjectsService ) {
11+
AuthService.withUser();
12+
13+
AlertMessageService.getAlerts().forEach(function(alert) {
14+
$scope.alerts[alert.name] = alert.data;
15+
});
16+
AlertMessageService.clearAlerts();
17+
18+
$scope.alerts = {};
19+
$scope.selected = {};
20+
21+
var alertInvalidImageStream = function(imageStream) {
22+
$scope.alerts.invalidImageStream = {
23+
type: "error",
24+
message: "The requested image stream \"" + imageStream + "\" could not be loaded."
25+
};
26+
};
27+
28+
var alertInvalidImageTag = function(imageTag) {
29+
$scope.alerts.invalidImageTag = {
30+
type: "error",
31+
message: "The requested image stream tag \"" + imageTag + "\" could not be loaded."
32+
};
33+
};
34+
35+
var alertInvalidName = function(name) {
36+
$scope.alerts.invalidImageStream = {
37+
type: "error",
38+
message: "The app name \"" + name + "\" is not valid. An app name is an alphanumeric (a-z, and 0-9) string with a maximum length of 24 characters, where the first character is a letter (a-z), and the '-' character is allowed anywhere except the first or last character."
39+
};
40+
};
41+
42+
var alertInvalidNamespace = function(namespace) {
43+
$scope.alerts.invalidNamespace = {
44+
type: "error",
45+
message: "Resources from the namespace \"" + namespace + "\" are not permitted."
46+
};
47+
};
48+
49+
var alertInvalidTemplate = function(template) {
50+
$scope.alerts.invalidTemplate = {
51+
type: "error",
52+
message: "The requested template \"" + template + "\" could not be loaded."
53+
};
54+
};
55+
56+
var alertResourceRequired = function() {
57+
$scope.alerts.resourceRequired = {
58+
type: "error",
59+
message: "An image stream or template is required."
60+
};
61+
};
62+
63+
var showInvalidResource = function() {
64+
$scope.alerts.invalidResource = {
65+
type: "error",
66+
message: "Image streams and templates cannot be combined."
67+
};
68+
};
69+
70+
var getTemplateParamsMap = function () {
71+
try {
72+
return $routeParams.templateParamsMap && JSON.parse($routeParams.templateParamsMap) || {};
73+
}
74+
catch (e) {
75+
$scope.alerts.invalidTemplateParams = {
76+
type: "error",
77+
message: "The templateParamsMap is not valid JSON. " + e
78+
};
79+
}
80+
};
81+
82+
var namespaceWhitelist = window.OPENSHIFT_CONSTANTS.CREATE_FROM_URL_WHITELIST;
83+
var whiteListedCreateDetailsKeys = ['namespace', 'name', 'imageStream', 'imageTag', 'sourceURI', 'sourceRef', 'contextDir', 'template', 'templateParamsMap'];
84+
var createDetails = _.pick($routeParams, function(value, key) {
85+
// routeParams without a value (e.g., ?name&) return true, which results in "true" displaying in the UI
86+
return _.contains(whiteListedCreateDetailsKeys, key) && _.isString(value);
87+
});
88+
// if no namespace is specified, set it to 'openshift'
89+
createDetails.namespace = createDetails.namespace || 'openshift';
90+
91+
var validateName = function (name) {
92+
return name.length < 25 && /^[a-z]([-a-z0-9]*[a-z0-9])?$/.test(name);
93+
};
94+
95+
var getResources = function() {
96+
if (createDetails.imageStream) {
97+
DataService
98+
.get("imagestreams", createDetails.imageStream, {namespace: createDetails.namespace}, {
99+
errorNotification: false
100+
})
101+
.then(function(imageStream) {
102+
$scope.imageStream = imageStream;
103+
DataService
104+
.get("imagestreamtags", imageStream.metadata.name + ":" + createDetails.imageTag, {namespace: createDetails.namespace}, {
105+
errorNotification: false
106+
})
107+
.then(function(imageStreamTag){
108+
$scope.imageStreamTag = imageStreamTag;
109+
$scope.validationPassed = true;
110+
$scope.resource = imageStreamTag;
111+
createDetails.displayName = $filter('displayName')(imageStreamTag);
112+
}, function(){
113+
alertInvalidImageTag(createDetails.imageTag);
114+
});
115+
}, function() {
116+
alertInvalidImageStream(createDetails.imageStream);
117+
});
118+
}
119+
if (createDetails.template) {
120+
DataService
121+
.get("templates", createDetails.template, {namespace: createDetails.namespace}, {
122+
errorNotification: false
123+
})
124+
.then(function(template) {
125+
$scope.template = template;
126+
if(getTemplateParamsMap()) {
127+
$scope.validationPassed = true;
128+
$scope.resource = template;
129+
}
130+
}, function() {
131+
alertInvalidTemplate(createDetails.template);
132+
});
133+
}
134+
};
135+
136+
if (!(_.includes(namespaceWhitelist, createDetails.namespace))) {
137+
alertInvalidNamespace(createDetails.namespace);
138+
} else {
139+
if (createDetails.imageStream && createDetails.template) {
140+
showInvalidResource();
141+
} else if (!(createDetails.imageStream) && !(createDetails.template)) {
142+
alertResourceRequired();
143+
} else if (createDetails.name && !(validateName(createDetails.name))) {
144+
alertInvalidName(createDetails.name);
145+
} else {
146+
getResources();
147+
}
148+
}
149+
150+
angular.extend($scope, {
151+
createDetails: createDetails,
152+
createWithProject: function(projectName) {
153+
projectName = projectName || $scope.selected.project.metadata.name;
154+
var url = $routeParams.imageStream ?
155+
Navigate.createFromImageURL($scope.imageStream, createDetails.imageTag, projectName, createDetails) :
156+
Navigate.createFromTemplateURL($scope.template, projectName, createDetails);
157+
$location.url(url);
158+
}
159+
});
160+
161+
$scope.projects = {};
162+
$scope.canCreateProject = undefined;
163+
164+
DataService
165+
.list("projects", $scope)
166+
.then(function(items) {
167+
$scope.loaded = true;
168+
$scope.projects = $filter('orderByDisplayName')(items.by("metadata.name"));
169+
$scope.noProjects = (_.isEmpty($scope.projects));
170+
});
171+
172+
173+
// Test if the user can submit project requests. Handle error notifications
174+
// ourselves because 403 responses are expected.
175+
ProjectsService
176+
.canCreate()
177+
.then(function() {
178+
$scope.canCreateProject = true;
179+
}, function() {
180+
$scope.canCreateProject = false;
181+
});
182+
183+
});

app/scripts/controllers/createProject.js

-26
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,4 @@ angular.module('openshiftConsole')
1818
});
1919
AlertMessageService.clearAlerts();
2020

21-
$scope.createProject = function() {
22-
$scope.disableInputs = true;
23-
if ($scope.createProjectForm.$valid) {
24-
DataService.create('projectrequests', null, {
25-
apiVersion: "v1",
26-
kind: "ProjectRequest",
27-
metadata: {
28-
name: $scope.name
29-
},
30-
displayName: $scope.displayName,
31-
description: $scope.description
32-
}, $scope).then(function(data) { // Success
33-
// Take the user directly to the create page to add content.
34-
$location.path("project/" + encodeURIComponent(data.metadata.name) + "/create");
35-
}, function(result) { // Failure
36-
$scope.disableInputs = false;
37-
var data = result.data || {};
38-
if (data.reason === 'AlreadyExists') {
39-
$scope.nameTaken = true;
40-
} else {
41-
var msg = data.message || 'An error occurred creating the project.';
42-
$scope.alerts['error-creating-project'] = {type: 'error', message: msg};
43-
}
44-
});
45-
}
46-
};
4721
});

app/scripts/controllers/newfromtemplate.js

+23-2
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ angular.module('openshiftConsole')
3131
keyValueEditorUtils,
3232
Constants) {
3333

34-
35-
var name = $routeParams.name;
34+
var name = $routeParams.template;
3635

3736
// If the namespace is not defined, that indicates that the processed Template should be obtained from the 'CachedTemplateService'
3837
var namespace = $routeParams.namespace || "";
@@ -44,6 +43,7 @@ angular.module('openshiftConsole')
4443

4544
$scope.emptyMessage = "Loading...";
4645
$scope.alerts = {};
46+
$scope.alertsTop = {};
4747
$scope.projectName = $routeParams.project;
4848
$scope.projectPromise = $.Deferred();
4949
$scope.labels = [];
@@ -80,6 +80,18 @@ angular.module('openshiftConsole')
8080
var builderImage = $parse('spec.strategy.sourceStrategy.from || spec.strategy.dockerStrategy.from || spec.strategy.customStrategy.from');
8181
var outputImage = $parse('spec.output.to');
8282

83+
var getValidTemplateParamsMap = function () {
84+
try {
85+
return JSON.parse($routeParams.templateParamsMap);
86+
}
87+
catch (e) {
88+
$scope.alertsTop.invalidTemplateParams = {
89+
type: "error",
90+
message: "The templateParamsMap is not valid JSON. " + e
91+
};
92+
}
93+
};
94+
8395
ProjectsService
8496
.get($routeParams.project)
8597
.then(_.spread(function(project, context) {
@@ -356,6 +368,15 @@ angular.module('openshiftConsole')
356368
$scope.parameterDisplayNames[parameter.name] = parameter.displayName || parameter.name;
357369
});
358370

371+
if($routeParams.templateParamsMap) {
372+
var templateParams = getValidTemplateParamsMap();
373+
_.each($scope.template.parameters, function(parameter) {
374+
if (templateParams[parameter.name]) {
375+
parameter.value = templateParams[parameter.name];
376+
}
377+
});
378+
}
379+
359380
findTemplateImages($scope.template);
360381
var imageUsesParameters = function(image) {
361382
return !_.isEmpty(image.usesParameters);

app/scripts/controllers/projects.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ angular.module('openshiftConsole')
1717
AuthService,
1818
DataService,
1919
KeywordService,
20-
Logger) {
20+
Logger,
21+
ProjectsService) {
2122
var projects, sortedProjects;
2223
var watches = [];
2324
var filterKeywords = [];
@@ -129,7 +130,8 @@ angular.module('openshiftConsole')
129130

130131
// Test if the user can submit project requests. Handle error notifications
131132
// ourselves because 403 responses are expected.
132-
DataService.get("projectrequests", null, $scope, { errorNotification: false})
133+
ProjectsService
134+
.canCreate()
133135
.then(function() {
134136
$scope.canCreate = true;
135137
}, function(result) {

0 commit comments

Comments
 (0)