From 34d81ef9b27b6be99e89ceba75a5aac62c18c405 Mon Sep 17 00:00:00 2001 From: Kasra Bigdeli Date: Tue, 27 Nov 2018 20:01:32 -0800 Subject: [PATCH 1/2] rebuilt front end --- app-backend/app.js | 4 +- app-backend/dist/js/dashboard.min.js | 238 +++++++++--------- app-backend/dist/oneclick-apps/vsts-agent.js | 201 +++++++++++++++ app-backend/dist/oneclick-apps/wordpress.js | 6 +- app-backend/dist/templates/app-details.html | 10 +- app-backend/dist/templates/apps.html | 2 +- app-backend/dist/templates/login.html | 2 +- .../dist/templates/modals/delete-app.html | 2 +- .../src/datastore/DataStoreProvider.js | 12 +- app-backend/src/user/Authenticator.js | 6 +- app-frontend/package-lock.json | 6 +- 11 files changed, 349 insertions(+), 140 deletions(-) create mode 100644 app-backend/dist/oneclick-apps/vsts-agent.js diff --git a/app-backend/app.js b/app-backend/app.js index b6f68d4..7287407 100644 --- a/app-backend/app.js +++ b/app-backend/app.js @@ -174,14 +174,12 @@ app.use(function (req, res, next) { // error handler app.use(function (err, req, res, next) { // set locals, only providing error in development - res.locals.message = err.message; res.locals.error = req.app.get('env') === 'development' ? err : {}; Logger.e(err); // render the error page - res.status(err.status || 500); - res.render('error'); + res.sendStatus(err.status || 500); }); // Initializing with delay helps with debugging. Many times, docker didn't see the CAPTAIN service diff --git a/app-backend/dist/js/dashboard.min.js b/app-backend/dist/js/dashboard.min.js index 1479875..1ccf786 100644 --- a/app-backend/dist/js/dashboard.min.js +++ b/app-backend/dist/js/dashboard.min.js @@ -725,6 +725,124 @@ angular.module('RDash') } }); +/** + * File Upload Read Directive + */ + +angular + .module('RDash') + .directive("fileread", [function () { + return { + scope: { + fileread: "=" + }, + link: function (scope, element, attributes) { + element.bind("change", function (changeEvent) { + scope.$apply(function () { + scope.fileread = changeEvent.target.files[0]; + // or all selected files: + // scope.fileread = changeEvent.target.files; + }); + }); + } + } + }]); +/** + * Loading Directive + * @see http://tobiasahlin.com/spinkit/ + */ + +angular + .module('RDash') + .directive('rdLoading', rdLoading); + +function rdLoading() { + var directive = { + restrict: 'AE', + template: '
' + }; + return directive; +}; +/** + * Widget Body Directive + */ + +angular + .module('RDash') + .directive('rdWidgetBody', rdWidgetBody); + +function rdWidgetBody() { + var directive = { + requires: '^rdWidget', + scope: { + loading: '=?', + classes: '@?' + }, + transclude: true, + template: '
', + restrict: 'E' + }; + return directive; +}; + +/** + * Widget Footer Directive + */ + +angular + .module('RDash') + .directive('rdWidgetFooter', rdWidgetFooter); + +function rdWidgetFooter() { + var directive = { + requires: '^rdWidget', + transclude: true, + template: '', + restrict: 'E' + }; + return directive; +}; +/** + * Widget Header Directive + */ + +angular + .module('RDash') + .directive('rdWidgetHeader', rdWidgetTitle); + +function rdWidgetTitle() { + var directive = { + requires: '^rdWidget', + scope: { + title: '@', + icon: '@' + }, + transclude: true, + template: '
{{title}}
', + restrict: 'E' + }; + return directive; +}; +/** + * Widget Directive + */ + +angular + .module('RDash') + .directive('rdWidget', rdWidget); + +function rdWidget() { + var directive = { + transclude: true, + template: '
', + restrict: 'EA' + }; + return directive; + + function link(scope, element, attrs) { + /* */ + } +}; /** * Alerts Controller */ @@ -1886,122 +2004,4 @@ function SettingsCtrl($scope, $cookieStore, $rootScope, pageDefinitions, }()); -} -/** - * File Upload Read Directive - */ - -angular - .module('RDash') - .directive("fileread", [function () { - return { - scope: { - fileread: "=" - }, - link: function (scope, element, attributes) { - element.bind("change", function (changeEvent) { - scope.$apply(function () { - scope.fileread = changeEvent.target.files[0]; - // or all selected files: - // scope.fileread = changeEvent.target.files; - }); - }); - } - } - }]); -/** - * Loading Directive - * @see http://tobiasahlin.com/spinkit/ - */ - -angular - .module('RDash') - .directive('rdLoading', rdLoading); - -function rdLoading() { - var directive = { - restrict: 'AE', - template: '
' - }; - return directive; -}; -/** - * Widget Body Directive - */ - -angular - .module('RDash') - .directive('rdWidgetBody', rdWidgetBody); - -function rdWidgetBody() { - var directive = { - requires: '^rdWidget', - scope: { - loading: '=?', - classes: '@?' - }, - transclude: true, - template: '
', - restrict: 'E' - }; - return directive; -}; - -/** - * Widget Footer Directive - */ - -angular - .module('RDash') - .directive('rdWidgetFooter', rdWidgetFooter); - -function rdWidgetFooter() { - var directive = { - requires: '^rdWidget', - transclude: true, - template: '', - restrict: 'E' - }; - return directive; -}; -/** - * Widget Header Directive - */ - -angular - .module('RDash') - .directive('rdWidgetHeader', rdWidgetTitle); - -function rdWidgetTitle() { - var directive = { - requires: '^rdWidget', - scope: { - title: '@', - icon: '@' - }, - transclude: true, - template: '
{{title}}
', - restrict: 'E' - }; - return directive; -}; -/** - * Widget Directive - */ - -angular - .module('RDash') - .directive('rdWidget', rdWidget); - -function rdWidget() { - var directive = { - transclude: true, - template: '
', - restrict: 'EA' - }; - return directive; - - function link(scope, element, attrs) { - /* */ - } -}; \ No newline at end of file +} \ No newline at end of file diff --git a/app-backend/dist/oneclick-apps/vsts-agent.js b/app-backend/dist/oneclick-apps/vsts-agent.js new file mode 100644 index 0000000..849df9c --- /dev/null +++ b/app-backend/dist/oneclick-apps/vsts-agent.js @@ -0,0 +1,201 @@ + +(function () { + + var SUCCESS = 'success'; + var ERROR = 'danger'; + var INFO = 'info'; + + oneClickAppsRepository["vsts-agent"] = function (apiManager) { + + var getErrorMessageIfExists = apiManager.getErrorMessageIfExists; + + var VSTS_ACCOUNT = 'VSTS_ACCOUNT'; + var VSTS_TOKEN = 'VSTS_TOKEN'; + var VSTS_AGENT = 'VSTS_AGENT'; + var VSTS_POOL = 'VSTS_POOL'; + var DOCKER_TAG = 'DOCKER_TAG'; + var VSTS_AGENT_CONTAINER_NAME = 'VSTS_AGENT_CONTAINER_NAME'; + + var step1next = {}; + + step1next.data = []; + step1next.data.push({ + label: 'VSTS Agent Container Name', + id: VSTS_AGENT_CONTAINER_NAME, + type: 'text' + }); + + step1next.data.push({ + label: 'OPTIONAL: Docker Tag (default "latest")', + labelDesc: 'https://hub.docker.com/r/microsoft/vsts-agent/tags/', + id: DOCKER_TAG, + type: 'text' + }); + + step1next.data.push({ + label: 'VSTS Account', + labelDesc: 'The name of the Visual Studio account. Take only the account part from your address, e.g. http://{account}.visualstudio.com', + id: VSTS_ACCOUNT, + type: 'text' + }); + step1next.data.push({ + label: 'VSTS Token', + labelDesc: 'A personal access token (PAT) for the Visual Studio account that has been given at least the Agent Pools (read, manage) scope.', + id: VSTS_TOKEN, + type: 'text' + }); + + step1next.data.push({ + label: 'VSTS Agent', + labelDesc: 'The name of the agent.', + id: VSTS_AGENT, + type: 'text' + }); + + step1next.data.push({ + label: 'VSTS Pool', + labelDesc: 'The name of the agent pool.', + id: VSTS_POOL, + type: 'text' + }); + + step1next.process = function (data, step1Callback) { + + // create container and set persistent + // set env vars and volumes + // deploy image via dockerfile + + function endWithSuccess() { + step1Callback({ + message: { + text: 'VSTS Agent is deployed and published as ' + data[VSTS_AGENT] +'.', + type: SUCCESS + }, + next: null // this can be similar to step1next, in that case the flow continues... + }); + } + + function endWithError(errorMessage) { + step1Callback({ + message: { + text: errorMessage, + type: ERROR + }, + next: step1next + }); + } + + // process the inputs: + + var errorMessage = null; + + if (!data[VSTS_AGENT_CONTAINER_NAME]) { + errorMessage = 'Container name is required!'; + } else if (!data[VSTS_ACCOUNT]) { + errorMessage = 'Account is required!'; + } else if (!data[VSTS_TOKEN]) { + errorMessage = 'Acess token is required!'; + } else if (!data[VSTS_AGENT]) { + errorMessage = 'Agent name is required!'; + } else if (!data[VSTS_POOL]) { + errorMessage = 'Pool name is required!'; + } + + if (errorMessage) { + endWithError(errorMessage); + return; + } + + var appName = data[VSTS_AGENT_CONTAINER_NAME]; + var dockerTag = data[DOCKER_TAG] || 'latest'; + var envVars = [{ + key: VSTS_ACCOUNT, + value: data[VSTS_ACCOUNT] + }, { + key: VSTS_TOKEN, + value: data[VSTS_TOKEN] + }, + { + key: VSTS_AGENT, + value: data[VSTS_AGENT] + }, + { + key: VSTS_POOL, + value: data[VSTS_POOL] + }]; + var volumes = [{ + volumeName: appName + '-vsts-agent-vol', + containerPath: '/data/db' + }, { + volumeName: appName + '-vsts-agent-vol', + containerPath: '/data/configdb' + }]; + + function createContainer() { + + var hasPersistentData = true; + + apiManager.registerNewApp(appName, hasPersistentData, function (data) { + if (getErrorMessageIfExists(data)) { + endWithError(getErrorMessageIfExists(data)); + return; + } + + setupAppDefinition(); + }); + } + + function setupAppDefinition() { + + var appDefinition = { + instanceCount: 1, + envVars: envVars, + notExposeAsWebApp: true, + volumes: volumes + }; + + apiManager.updateConfigAndSave(appName, appDefinition, function (data) { + if (getErrorMessageIfExists(data)) { + endWithError(getErrorMessageIfExists(data)); + return; + } + + deployDockerfile(); + }); + } + + function deployDockerfile() { + + var captainDefinitionContent = { + schemaVersion: 1, + dockerfileLines: [ + "FROM microsoft/vsts-agent:" + dockerTag + ] + } + + apiManager.uploadCaptainDefinitionContent(appName, + JSON.stringify(captainDefinitionContent), function (data) { + if (getErrorMessageIfExists(data)) { + endWithError(getErrorMessageIfExists(data)); + return; + } + + endWithSuccess(); + }); + } + + createContainer(); + + } + + var step1 = {}; + step1.message = { + type: INFO, + text: 'Official image for the Visual Studio Team Services (VSTS) agent.' + } + step1.next = step1next; + return step1; + + } + +})(); diff --git a/app-backend/dist/oneclick-apps/wordpress.js b/app-backend/dist/oneclick-apps/wordpress.js index 1bf5be6..be0d33d 100644 --- a/app-backend/dist/oneclick-apps/wordpress.js +++ b/app-backend/dist/oneclick-apps/wordpress.js @@ -34,7 +34,7 @@ type: 'text' }); step1next.data.push({ - label: 'OPTIONAL: Docker Tag for MySQL (default "5.5")', + label: 'OPTIONAL: Docker Tag for MySQL (default "5.7")', labelDesc: 'https://hub.docker.com/r/library/mysql/tags/', id: DOCKER_TAG_MYSQL, type: 'text' @@ -83,7 +83,7 @@ } var dockerTagWordPress = data[DOCKER_TAG_WORDPRESS] || '4.9'; - var dockerTagMySql = data[DOCKER_TAG_MYSQL] || '5.5'; + var dockerTagMySql = data[DOCKER_TAG_MYSQL] || '5.7'; var mySqlAppName = data[WORDPRESS_NAME] + '-mysql'; var envVarsMySql = [{ key: MYSQL_ROOT_PASSWORD, @@ -231,4 +231,4 @@ } -})(); \ No newline at end of file +})(); diff --git a/app-backend/dist/templates/app-details.html b/app-backend/dist/templates/app-details.html index 92e0414..00561df 100644 --- a/app-backend/dist/templates/app-details.html +++ b/app-backend/dist/templates/app-details.html @@ -182,13 +182,13 @@

Make sure that you have a 'captain-definition' file in your project. See - docs for more details.

+ docs for more details.

Method 1 (RECOMMENDED)

Use CLI deploy command. This is the best method as it's the only method that reports potential build failures to you. - Read here + Read here

Method 2: Tarball @@ -303,7 +303,7 @@

Port Mapping   - +

@@ -337,7 +337,7 @@

Persistent Directories   - + @@ -426,7 +426,7 @@
{{!!app.hasPreDeployFunction? 'Remove':'Add'}} Pre-Deploy Script   - +   diff --git a/app-backend/dist/templates/apps.html b/app-backend/dist/templates/apps.html index bde2fa0..0347d75 100644 --- a/app-backend/dist/templates/apps.html +++ b/app-backend/dist/templates/apps.html @@ -25,7 +25,7 @@
diff --git a/app-backend/dist/templates/login.html b/app-backend/dist/templates/login.html index 280c0ce..3c49f1a 100644 --- a/app-backend/dist/templates/login.html +++ b/app-backend/dist/templates/login.html @@ -11,7 +11,7 @@
- +
diff --git a/app-backend/dist/templates/modals/delete-app.html b/app-backend/dist/templates/modals/delete-app.html index df925ea..fee2830 100644 --- a/app-backend/dist/templates/modals/delete-app.html +++ b/app-backend/dist/templates/modals/delete-app.html @@ -14,7 +14,7 @@ IMPORTANT: {{modalAppDelete.appName}} is an app with persistent data. After deleting the app from CaptainDuckDuck, you will have to manually SSH to your server, and delete Persistent Directories on your server. Refer to the - + documentations for more details.

diff --git a/app-backend/src/datastore/DataStoreProvider.js b/app-backend/src/datastore/DataStoreProvider.js index 3604e48..70612c3 100644 --- a/app-backend/src/datastore/DataStoreProvider.js +++ b/app-backend/src/datastore/DataStoreProvider.js @@ -3,6 +3,7 @@ */ const DataStore = require('./DataStoreImpl'); +const CaptainConstants = require('../utils/CaptainConstants'); const dataStoreCache = {}; module.exports = { @@ -13,11 +14,16 @@ module.exports = { return null; } - if (!dataStoreCache[namespace]) { - dataStoreCache[namespace] = new DataStore(namespace); + if (namespace === CaptainConstants.rootNameSpace) { + + if (!dataStoreCache[namespace]) { + dataStoreCache[namespace] = new DataStore(namespace); + } + + return dataStoreCache[namespace]; } - return dataStoreCache[namespace]; + return null; } }; \ No newline at end of file diff --git a/app-backend/src/user/Authenticator.js b/app-backend/src/user/Authenticator.js index 4d65a53..e47132a 100644 --- a/app-backend/src/user/Authenticator.js +++ b/app-backend/src/user/Authenticator.js @@ -225,7 +225,11 @@ module.exports = { } } - return authenticatorCache[namespace]; + if (namespace === CaptainConstants.rootNameSpace) { + return authenticatorCache[namespace]; + } + + return null; } }; \ No newline at end of file diff --git a/app-frontend/package-lock.json b/app-frontend/package-lock.json index cf5aef5..92986c2 100644 --- a/app-frontend/package-lock.json +++ b/app-frontend/package-lock.json @@ -1241,7 +1241,7 @@ }, "duplexer": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", "dev": true }, @@ -4571,7 +4571,7 @@ }, "pause-stream": { "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "resolved": "http://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", "dev": true, "requires": { @@ -5853,7 +5853,7 @@ }, "through": { "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, From 2b64af31b095ac956f8bd52d845dc06aba442946 Mon Sep 17 00:00:00 2001 From: Kasra Bigdeli Date: Tue, 27 Nov 2018 20:06:03 -0800 Subject: [PATCH 2/2] changed version to 0.7.3 --- app-backend/src/utils/CaptainConstants.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app-backend/src/utils/CaptainConstants.js b/app-backend/src/utils/CaptainConstants.js index 696081e..4284477 100644 --- a/app-backend/src/utils/CaptainConstants.js +++ b/app-backend/src/utils/CaptainConstants.js @@ -27,7 +27,7 @@ let data = { isDebug: EnvVars.CAPTAIN_IS_DEBUG, - version: '0.7.2', + version: '0.7.3', captainSaltSecretKey: 'captain-salt',