Browse Source

feat(iot-hub): support custom docker-compose template for gateway install

Add optional 'dockerCompose' field to GATEWAY step definition pointing
to a YAML template in the ZIP. Variables (${mqtt.host}, ${gateway.token},
form values) are resolved after gateway creation. The download button
serves the custom template as a Blob download instead of calling the
standard backend endpoint.

Falls back to the standard API-generated docker-compose.yml when no
custom template is provided.
pull/15508/head
Andrii Shvaika 6 months ago
parent
commit
43624ba380
  1. 31
      ui-ngx/src/app/modules/home/components/iot-hub/device-install-dialog/device-install-dialog.component.ts
  2. 1
      ui-ngx/src/app/shared/models/iot-hub/device-package.models.ts

31
ui-ngx/src/app/modules/home/components/iot-hub/device-install-dialog/device-install-dialog.component.ts

@ -101,6 +101,7 @@ export class TbDeviceInstallDialogComponent extends DialogComponent<TbDeviceInst
formValues: Record<string, any> = {}; formValues: Record<string, any> = {};
entityOutputs = new Map<string, EntityStepOutput>(); entityOutputs = new Map<string, EntityStepOutput>();
transportVars: Record<string, string> = {}; transportVars: Record<string, string> = {};
gatewayDockerComposeContent: string | null = null;
constructor( constructor(
protected store: Store<AppState>, protected store: Store<AppState>,
@ -254,9 +255,21 @@ export class TbDeviceInstallDialogComponent extends DialogComponent<TbDeviceInst
buttons.forEach(btn => { buttons.forEach(btn => {
btn.addEventListener('click', (e) => { btn.addEventListener('click', (e) => {
e.preventDefault(); e.preventDefault();
const gateway = this.entityOutputs.get('gateway'); if (this.gatewayDockerComposeContent) {
if (gateway?.id) { // Custom template from ZIP — download as Blob
this.deviceService.downloadGatewayDockerComposeFile(gateway.id).subscribe(); const blob = new Blob([this.gatewayDockerComposeContent], { type: 'application/x-yaml' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = 'docker-compose.yml';
link.click();
URL.revokeObjectURL(url);
} else {
// Standard template — authenticated API call
const gateway = this.entityOutputs.get('gateway');
if (gateway?.id) {
this.deviceService.downloadGatewayDockerComposeFile(gateway.id).subscribe();
}
} }
}); });
}); });
@ -502,13 +515,23 @@ export class TbDeviceInstallDialogComponent extends DialogComponent<TbDeviceInst
case InstallStepType.GATEWAY: { case InstallStepType.GATEWAY: {
const result = await firstValueFrom(this.deviceService.saveDevice(template, {ignoreErrors: true})); const result = await firstValueFrom(this.deviceService.saveDevice(template, {ignoreErrors: true}));
const creds = await this.resolveCredentials(step, result.id.id); const creds = await this.resolveCredentials(step, result.id.id);
return { const output = {
id: result.id.id, id: result.id.id,
name: result.name, name: result.name,
url: '/entities/gateways', url: '/entities/gateways',
token: creds.credentialsId, token: creds.credentialsId,
dockerComposeUrl: `/api/device-connectivity/gateway-launch/${result.id.id}/docker-compose/download` dockerComposeUrl: `/api/device-connectivity/gateway-launch/${result.id.id}/docker-compose/download`
}; };
// Store entity output early so docker-compose template can resolve ${gateway.token} etc.
this.entityOutputs.set('gateway', output);
// Resolve custom docker-compose template if provided
if (step.dockerCompose) {
const raw = this.zipFiles.get(step.dockerCompose);
if (raw) {
this.gatewayDockerComposeContent = this.resolveVariables(raw);
}
}
return output;
} }
case InstallStepType.GATEWAY_CONNECTOR: { case InstallStepType.GATEWAY_CONNECTOR: {
const gatewayOutput = this.entityOutputs.get('gateway'); const gatewayOutput = this.entityOutputs.get('gateway');

1
ui-ngx/src/app/shared/models/iot-hub/device-package.models.ts

@ -85,6 +85,7 @@ export interface DeviceInstallStep {
serverAttributes?: string; serverAttributes?: string;
sharedAttributes?: string; sharedAttributes?: string;
credentials?: string; credentials?: string;
dockerCompose?: string;
} }
export interface DevicePackageInfo { export interface DevicePackageInfo {

Loading…
Cancel
Save