diff --git a/frontend/src/components/Terminal.vue b/frontend/src/components/Terminal.vue
index 04532a2b3..7cd49398b 100644
--- a/frontend/src/components/Terminal.vue
+++ b/frontend/src/components/Terminal.vue
@@ -8,6 +8,13 @@
{{ name }}
+
+
+
+
+
+
+
@@ -58,13 +65,57 @@ export default {
apiOrigin: API_ORIGIN || '',
appModel: null,
busyRestart: false,
+ connected: false,
+ addons: {},
+ manifestVersion: '',
id: '',
name: '',
+ socket: null,
terminal: null
};
},
methods: {
- onClear() {
+ usesAddon(addon) {
+ return !!Object.keys(this.addons).find(function (a) { return a === addon; });
+ },
+ terminalInject(addon, extra) {
+ if (!this.socket) return;
+
+ let cmd = '';
+ if (addon === 'mysql') {
+ if (this.manifestVersion === 1) {
+ cmd = 'mysql --user=${MYSQL_USERNAME} --password=${MYSQL_PASSWORD} --host=${MYSQL_HOST} ${MYSQL_DATABASE}';
+ } else {
+ cmd = 'mysql --user=${CLOUDRON_MYSQL_USERNAME} --password=${CLOUDRON_MYSQL_PASSWORD} --host=${CLOUDRON_MYSQL_HOST} ${CLOUDRON_MYSQL_DATABASE}';
+ }
+ } else if (addon === 'postgresql') {
+ if (this.manifestVersion === 1) {
+ cmd = 'PGPASSWORD=${POSTGRESQL_PASSWORD} psql -h ${POSTGRESQL_HOST} -p ${POSTGRESQL_PORT} -U ${POSTGRESQL_USERNAME} -d ${POSTGRESQL_DATABASE}';
+ } else {
+ cmd = 'PGPASSWORD=${CLOUDRON_POSTGRESQL_PASSWORD} psql -h ${CLOUDRON_POSTGRESQL_HOST} -p ${CLOUDRON_POSTGRESQL_PORT} -U ${CLOUDRON_POSTGRESQL_USERNAME} -d ${CLOUDRON_POSTGRESQL_DATABASE}';
+ }
+ } else if (addon === 'mongodb') {
+ if (this.manifestVersion === 1) {
+ cmd = 'mongo -u "${MONGODB_USERNAME}" -p "${MONGODB_PASSWORD}" ${MONGODB_HOST}:${MONGODB_PORT}/${MONGODB_DATABASE}';
+ } else {
+ cmd = 'mongosh -u "${CLOUDRON_MONGODB_USERNAME}" -p "${CLOUDRON_MONGODB_PASSWORD}" ${CLOUDRON_MONGODB_HOST}:${CLOUDRON_MONGODB_PORT}/${CLOUDRON_MONGODB_DATABASE}';
+ }
+ } else if (addon === 'redis') {
+ if (this.manifestVersion === 1) {
+ cmd = 'redis-cli -h "${REDIS_HOST}" -p "${REDIS_PORT}" -a "${REDIS_PASSWORD}"';
+ } else {
+ cmd = 'redis-cli -h "${CLOUDRON_REDIS_HOST}" -p "${CLOUDRON_REDIS_PORT}" -a "${CLOUDRON_REDIS_PASSWORD}" --no-auth-warning';
+ }
+ } else if (addon === 'scheduler' && extra) {
+ cmd = extra.command;
+ }
+
+ if (!cmd) return;
+
+ cmd += ' ';
+
+ this.socket.send(cmd);
+ this.terminal.focus();
},
async onRestartApp() {
if (this.type !== 'app') return;
@@ -104,16 +155,22 @@ export default {
// websocket cannot use relative urls
var url = `${this.apiOrigin.replace('https', 'wss')}/api/v1/apps/${this.id}/exec/${execId}/startws?tty=true&rows=${this.terminal.rows}&columns=${this.terminal.cols}&access_token=${this.accessToken}`;
- const socket = new WebSocket(url);
+ this.socket = new WebSocket(url);
- this.terminal.loadAddon(new AttachAddon(socket));
+ this.terminal.loadAddon(new AttachAddon(this.socket));
- socket.addEventListener('close', (event) => {
+ this.socket.addEventListener('open', (event) => {
+ this.connected = true;
+ });
+
+ this.socket.addEventListener('close', (event) => {
+ this.connected = false;
console.log('Socket closed. Reconnecting...');
return setTimeout(() => this.connect(true), 1000);
});
- socket.addEventListener('error', (error) => {
+ this.socket.addEventListener('error', (error) => {
+ this.connected = false;
console.log('Socket error. Reconnecting...', error);
return setTimeout(() => this.connect(true), 1000);
});
@@ -143,6 +200,8 @@ export default {
try {
const app = await this.appModel.get();
this.name = `${app.label || app.fqdn} (${app.manifest.title})`;
+ this.addons = app.manifest.addons;
+ this.manifestVersion = app.manifest.manifestVersion;
} catch (e) {
console.error(`Failed to get app info for ${this.id}:`, e);
}