diff --git a/src/commands/dev/index.ts b/src/commands/dev/index.ts
index 85eac7c1c..e1f6758a9 100644
--- a/src/commands/dev/index.ts
+++ b/src/commands/dev/index.ts
@@ -451,7 +451,7 @@ export default class Dev extends BaseCommand {
});
if (overlay_port) {
- new OverlayServer().listen(overlay_port);
+ new OverlayServer(this.app, this.config, default_project_name, DockerComposeUtils.getLocalServiceNames(compose_file)).listen(overlay_port);
}
try {
diff --git a/src/common/docker-compose/index.ts b/src/common/docker-compose/index.ts
index 65daf2bb8..00f870802 100644
--- a/src/common/docker-compose/index.ts
+++ b/src/common/docker-compose/index.ts
@@ -28,6 +28,16 @@ type GenerateOptions = {
getImage?: (ref: string) => string;
};
+type ServiceValue = {
+ name: string;
+ display_name: string;
+};
+
+export type ServiceKey = {
+ name: string;
+ value: ServiceValue;
+};
+
export class DockerComposeUtils {
// used to namespace docker-compose projects so multiple deployments can happen to local
public static DEFAULT_PROJECT = 'architect';
@@ -432,7 +442,7 @@ export class DockerComposeUtils {
service_to.labels.push(
`traefik.http.middlewares.${traefik_service}-rewritebody.plugin.rewritebody.lastModified=true`,
`traefik.http.middlewares.${traefik_service}-rewritebody.plugin.rewritebody.rewrites.regex=`,
- `traefik.http.middlewares.${traefik_service}-rewritebody.plugin.rewritebody.rewrites.replacement=`,
+ `traefik.http.middlewares.${traefik_service}-rewritebody.plugin.rewritebody.rewrites.replacement=`,
`traefik.http.routers.${traefik_service}.middlewares=${traefik_service}-rewritebody@docker`,
);
}
@@ -632,18 +642,23 @@ export class DockerComposeUtils {
return answers.environment;
}
- public static async getLocalServiceForEnvironment(compose_file: string, service_name?: string): Promise<{ display_name: string, name: string }> {
- // docker-compose -f and -p don't work in tandem
- const compose = yaml.load(fs.readFileSync(compose_file).toString()) as DockerComposeTemplate;
+ public static getLocalServiceNames(compose_file: string): ServiceKey[] {
+ // docker-compose -f and -p don't work in tandem
+ const compose = yaml.load(fs.readFileSync(compose_file).toString()) as DockerComposeTemplate;
- const services: { name: string, value: { display_name: string, name: string } }[] = [];
+ const services: ServiceKey[] = [];
for (const [service_name, service] of Object.entries(compose.services)) {
const display_name = service.labels?.find((label) => label.startsWith('architect.ref='))?.split('=')[1];
if (!display_name) continue;
services.push({ name: display_name, value: { name: service_name, display_name } });
}
- const answers: { service: { display_name: string, name: string } } = await inquirer.prompt([
+ return services;
+ }
+
+ public static async getLocalServiceForEnvironment(compose_file: string, service_name?: string): Promise {
+ const services = DockerComposeUtils.getLocalServiceNames(compose_file);
+ const answers: { service: ServiceValue } = await inquirer.prompt([
{
when: !service_name,
type: 'autocomplete',
@@ -655,7 +670,7 @@ export class DockerComposeUtils {
},
]);
- let selected_service;
+ let selected_service: ServiceValue | undefined;
if (service_name) {
selected_service = services.find((service) => service.name === service_name)?.value;
if (!selected_service) {
diff --git a/src/common/overlay/overlay-server.ts b/src/common/overlay/overlay-server.ts
index ebbf1ca08..95f20835e 100644
--- a/src/common/overlay/overlay-server.ts
+++ b/src/common/overlay/overlay-server.ts
@@ -1,28 +1,142 @@
import fs from 'fs-extra';
import http from 'http';
import path from 'path';
+import DevRestart from '../../commands/dev/restart';
+import { Config } from '@oclif/core';
+import AppService from '../../app-config/service';
+import Logs from '../../commands/logs';
+import { ServiceKey } from '../docker-compose';
export class OverlayServer {
+ private app: AppService;
+ private config: Config;
+ private environment: string;
+ private services: ServiceKey[];
+
+ constructor(app: AppService, config: Config, environment: string, services: ServiceKey[]) {
+ this.app = app;
+ this.config = config;
+ this.environment = environment;
+ this.services = services;
+ }
+
listen(port: number): void {
- const server = http.createServer(function (req, res) {
+ const server = http.createServer(async (req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
- try {
- // eslint-disable-next-line unicorn/prefer-module
- const file_path = path.join(__dirname, '../../static/overlay.js');
- const file = fs.readFileSync(file_path);
- res.writeHead(200, { 'Content-Type': 'text/javascript' });
- res.end(file);
- } catch (err) {
- res.writeHead(500, { 'Content-Type': 'text/plain' });
- res.end('Server Error');
+ if (req.url === '/overlay.js') {
+ this.handleOverlay(res);
+ } else if (req.url === '/favicon.ico') {
+ this.handleFavicon(res);
+ } else if (req.url?.startsWith('/restart/')) {
+ const [_, __, service_name] = req.url.split('/');
+ const restart_cmd = new DevRestart([service_name, '-e', this.environment], this.config);
+ restart_cmd.app = this.app;
+
+ await restart_cmd.run();
+
+ res.writeHead(200);
+ res.end(`Restarted ${service_name}.`);
+ } else if (req.url?.startsWith('/logs/')) {
+ const [_, __, service_name] = req.url.split('/');
+ const logs_cmd = new Logs([service_name, '-e', this.environment, '--raw'], this.config);
+ logs_cmd.app = this.app;
+
+ res.writeHead(200);
+ res.write(`Logs can be viewed in the CLI with the command: 'architect logs -e ${this.environment} ${service_name}'`);
+ res.write('\n----------------\n\n');
+
+ // Overwrite log function to instead send data to our response.
+ logs_cmd.log = (...message: string[]) => {
+ for (const m of message) {
+ // log writes include ansi characters because we're using chalk to color text.
+ res.write(stripAnsi(m));
+ }
+ res.write('\n');
+ };
+
+ await logs_cmd.run();
+
+ res.end();
+ } else {
+ res.writeHead(200);
+ let service_rows = '';
+ for (const service_key of this.services) {
+ service_rows += '';
+
+ service_rows += `
+ | ${service_key.name} |
+ Restart |
+ View Logs |
+ `;
+
+ service_rows += '
';
+ }
+
+ res.write(`
+
+
+ Architect Control
+
+
+
+
+ | Service |
+ |
+ |
+
+ ${service_rows}
+
+
+