From fc83d09d9c94acbc7a7392e6cb2d67d389c30c2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emirhan=20Durmu=C5=9F?= Date: Tue, 7 Oct 2025 00:38:49 +0300 Subject: [PATCH 1/3] registry service updatechangetracking fixed --- src/services/registry-service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/registry-service.js b/src/services/registry-service.js index de0a8ead..15c03c46 100644 --- a/src/services/registry-service.js +++ b/src/services/registry-service.js @@ -121,7 +121,7 @@ const updateRegistry = async function (registry, registryId, isCLI, transaction) } const _updateChangeTracking = async function (transaction) { - const fogs = await FogManager.findAll(transaction) + const fogs = await FogManager.findAll({}, transaction) for (const fog of fogs) { await ChangeTrackingService.update(fog.uuid, ChangeTrackingService.events.registries, transaction) } From fb6ca05ccdfb67b204838068d79d585844917970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emirhan=20Durmu=C5=9F?= Date: Tue, 7 Oct 2025 17:26:35 +0300 Subject: [PATCH 2/3] registry data model updated, vulnarable package patches, fog status job logic updated, fog used token cleanup service moved under jobs --- docs/swagger-test.yaml | 7638 ----------------- docs/swagger.yaml | 10 - generate-swagger.sh | 2 +- package-lock.json | 133 +- package.json | 6 +- scripts/generate-swagger.js | 778 -- src/cli/registry.js | 18 +- src/config/controller.yaml | 1 + src/config/env-mapping.js | 1 + .../mysql/db_migration_mysql_v1.0.4.sql | 3 - .../postgres/db_migration_pg_v1.0.4.sql | 3 - .../sqlite/db_migration_sqlite_v1.0.4.sql | 3 - src/data/models/registry.js | 12 - .../seeders/mysql/db_seeder_mysql_v1.0.2.sql | 6 +- .../seeders/postgres/db_seeder_pg_v1.0.2.sql | 6 +- .../sqlite/db_seeder_sqlite_v1.0.2.sql | 6 +- src/jobs/fog-status-job.js | 31 +- src/jobs/fog-token-cleanup-job.js | 42 + src/jobs/stopped-app-status-job.js | 3 +- src/schemas/iofog.js | 7 - src/schemas/registry.js | 8 +- src/server.js | 4 - src/services/agent-service.js | 13 +- src/services/cleanup-service.js | 34 - src/services/microservice-ports/default.js | 565 -- src/services/registry-service.js | 28 +- src/services/router-service.js | 2 +- 27 files changed, 132 insertions(+), 9231 deletions(-) delete mode 100644 docs/swagger-test.yaml delete mode 100644 scripts/generate-swagger.js create mode 100644 src/jobs/fog-token-cleanup-job.js delete mode 100644 src/services/cleanup-service.js delete mode 100644 src/services/microservice-ports/default.js diff --git a/docs/swagger-test.yaml b/docs/swagger-test.yaml deleted file mode 100644 index f9dc8841..00000000 --- a/docs/swagger-test.yaml +++ /dev/null @@ -1,7638 +0,0 @@ -openapi: 3.0.0 -info: - title: Datasance PoT Controller - version: 3.5.0 - description: Datasance PoT Controller REST API Documentation -servers: - - url: http://localhost:51121/api/v3 -tags: - - name: Controller - description: Manage your controller - - name: ioFog - description: Manage your agents - - name: Application - description: Manage your applications - - name: Application Template - description: Manage your application templates - - name: Catalog - description: Manage your catalog - - name: Registries - description: Manage your registries - - name: Microservices - description: Manage your microservices - - name: Routing - description: Manage your routes - - name: Router - description: Manage your Default Router - - name: Edge Resource - description: Manage your Edge Resources - - name: Diagnostics - description: Diagnostic your microservices - - name: Tunnel - description: Manage ssh tunnels - - name: Agent - description: Used by your agents to communicate with your controller - - name: User - description: Manage your users - - name: Secrets - description: Manage your secrets - - name: Certificates - description: Manage your certificates - - name: Services - description: Manage your services - - name: VolumeMounts - description: Manage your volume mounts - - name: ConfigMap - description: Manage your config maps -components: - securitySchemes: - authToken: - type: http - scheme: bearer - bearerFormat: JWT - description: JWT token for authentication (user or agent) - schemas: - image: - type: object - properties: - containerImage: - type: string - fogTypeId: - type: integer - minimum: 1 - maximum: 2 - required: - - containerImage - - fogTypeId - volumeMappings: - type: object - properties: - hostDestination: - type: string - containerDestination: - type: string - accessMode: - type: string - type: - enum: - - volume - - bind - required: - - hostDestination - - containerDestination - - accessMode - ports: - type: object - properties: - internal: - type: integer - external: - type: integer - protocol: - enum: - - tcp - - udp - required: - - internal - - external - extraHosts: - type: object - properties: - name: - type: string - address: - type: string - required: - - name - - address - env: - type: object - properties: - key: - type: string - value: - type: string - valueFromSecret: - type: string - valueFromConfigMap: - type: string - required: - - key - oneOf: - - required: - - value - - required: - - valueFromSecret - - required: - - valueFromConfigMap - straceData: - type: object - properties: - microserviceUuid: - type: string - buffer: - type: string - required: - - microserviceUuid - - buffer - microserviceStatus: - type: object - properties: - id: - type: string - containerId: - type: string - status: - type: string - startTime: - type: integer - operatingDuration: - type: integer - cpuUsage: - type: number - memoryUsage: - type: number - ipAddress: - type: string - ipAddressExternal: - type: string - execSessionIds: - type: array - items: - type: string - required: - - id - agentProvision: - type: object - properties: - type: - type: integer - minimum: 0 - maximum: 2 - key: - type: string - required: - - type - - key - agentDeprovision: - type: object - properties: - microserviceUuids: - type: array - items: - type: string - required: - - microserviceUuids - updateAgentConfig: - type: object - properties: - networkInterface: - type: string - dockerUrl: - type: string - diskLimit: - type: integer - minimum: 0 - diskDirectory: - type: string - memoryLimit: - type: integer - minimum: 0 - cpuLimit: - type: integer - minimum: 0 - logLimit: - type: integer - minimum: 0 - logDirectory: - type: string - logFileCount: - type: integer - minimum: 0 - statusFrequency: - type: integer - minimum: 0 - changeFrequency: - type: integer - minimum: 0 - deviceScanFrequency: - type: integer - minimum: 0 - watchdogEnabled: - type: boolean - latitude: - type: number - minimum: -90 - maximum: 90 - longitude: - type: number - minimum: -180 - maximum: 180 - gpsMode: - type: string - gpsDevice: - type: string - gpsScanFrequency: - type: integer - minimum: 0 - edgeGuardFrequency: - type: integer - minimum: 0 - dockerPruningFrequency: - type: integer - minimum: 0 - availableDiskThreshold: - type: integer - minimum: 0 - logLevel: - type: string - timeZone: - type: string - updateAgentStatus: - type: object - properties: - daemonStatus: - type: string - warningMessage: - type: string - daemonOperatingDuration: - type: integer - minimum: 0 - daemonLastStart: - type: integer - minimum: 0 - memoryUsage: - type: number - minimum: 0 - diskUsage: - type: number - minimum: 0 - cpuUsage: - type: number - minimum: 0 - memoryViolation: - type: boolean - diskViolation: - type: boolean - cpuViolation: - type: boolean - systemAvailableDisk: - type: integer - systemAvailableMemory: - type: integer - systemTotalCpu: - type: number - securityStatus: - type: string - securityViolationInfo: - type: string - microserviceStatus: - type: string - repositoryCount: - type: integer - minimum: 0 - repositoryStatus: - type: string - systemTime: - type: integer - minimum: 0 - lastStatusTime: - type: integer - minimum: 0 - ipAddress: - type: string - ipAddressExternal: - type: string - processedMessages: - type: integer - minimum: 0 - microserviceMessageCounts: - type: string - messageSpeed: - type: number - minimum: 0 - lastCommandTime: - type: integer - minimum: 0 - gpsMode: - type: string - gpsDevice: - type: string - gpsScanFrequency: - type: integer - minimum: 0 - edgeGuardFrequency: - type: integer - minimum: 0 - tunnelStatus: - type: string - version: - type: string - isReadyToUpgrade: - type: boolean - isReadyToRollback: - type: boolean - updateAgentStrace: - type: object - properties: - straceData: - type: array - items: - $ref: '#/components/schemas/straceData' - updateHardwareInfo: - type: object - properties: - info: - type: string - required: - - info - updateUsbInfo: - type: object - properties: - info: - type: string - required: - - info - applicationTemplateVariable: - type: object - properties: - key: - type: string - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - description: - type: string - required: - - key - applicationTemplateCreate: - type: object - properties: - name: - type: string - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - description: - type: string - variables: - type: array - items: - $ref: '#/components/schemas/applicationTemplateVariable' - required: - - name - applicationTemplateUpdate: - type: object - properties: - name: - type: string - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - description: - type: string - applicationJSON: - $ref: '#/components/schemas/applicationCreate' - variables: - type: array - items: - $ref: '#/components/schemas/applicationTemplateVariable' - applicationTemplatePatch: - type: object - properties: - name: - type: string - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - description: - type: string - applicationTemplateDeploy: - type: object - properties: - name: - type: string - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - description: - type: string - isActivated: - type: boolean - isSystem: - type: boolean - variables: - type: array - items: - type: object - properties: - key: - type: string - value: - type: string - required: - - name - applicationCreate: - type: object - properties: - name: - type: string - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - routes: - type: array - items: - $ref: '#/components/schemas/routingCreate' - microservices: - type: array - items: - $ref: '#/components/schemas/microserviceCreate' - description: - type: string - isActivated: - type: boolean - isSystem: - type: boolean - required: - - name - applicationUpdate: - type: object - properties: - name: - type: string - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - microservices: - type: array - items: - $ref: '#/components/schemas/microserviceCreate' - routes: - type: array - items: - $ref: '#/components/schemas/routingCreate' - description: - type: string - isActivated: - type: boolean - isSystem: - type: boolean - applicationPatch: - type: object - properties: - name: - type: string - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - description: - type: string - isActivated: - type: boolean - isSystem: - type: boolean - type: - type: object - properties: - infoType: - type: string - infoFormat: - type: string - catalogItemCreate: - type: object - properties: - name: - type: string - minLength: 1 - description: - type: string - category: - type: string - publisher: - type: string - diskRequired: - type: integer - ramRequired: - type: integer - picture: - type: string - isPublic: - type: boolean - registryId: - type: integer - configExample: - type: string - images: - type: array - minItems: 1 - maxItems: 2 - items: - $ref: '#/components/schemas/image' - inputType: - $ref: '#/components/schemas/type' - outputType: - $ref: '#/components/schemas/type' - required: - - name - - registryId - - images - catalogItemUpdate: - type: object - properties: - name: - type: string - minLength: 1 - description: - type: string - category: - type: string - publisher: - type: string - diskRequired: - type: integer - ramRequired: - type: integer - picture: - type: string - isPublic: - type: boolean - registryId: - type: integer - configExample: - type: string - images: - type: array - maxItems: 2 - items: - $ref: '#/components/schemas/image' - inputType: - $ref: '#/components/schemas/type' - outputType: - $ref: '#/components/schemas/type' - caCreate: - type: object - properties: - name: - type: string - minLength: 1 - maxLength: 255 - subject: - type: string - minLength: 1 - expiration: - type: integer - minimum: 0 - type: - type: string - enum: - - k8s-secret - - direct - - self-signed - secretName: - type: string - required: - - type - - name - allOf: - - {} - - {} - certificateCreate: - type: object - properties: - name: - type: string - minLength: 1 - maxLength: 255 - subject: - type: string - minLength: 1 - hosts: - type: string - minLength: 1 - expiration: - type: integer - minimum: 0 - ca: - type: object - properties: - type: - type: string - enum: - - k8s-secret - - direct - - self-signed - secretName: - type: string - required: - - type - required: - - name - - subject - - hosts - caResponse: - type: object - properties: - name: - type: string - subject: - type: string - type: - type: string - created_at: - type: string - format: date-time - updated_at: - type: string - format: date-time - required: - - name - - subject - - type - - created_at - - updated_at - certificateResponse: - type: object - properties: - name: - type: string - subject: - type: string - hosts: - type: string - created_at: - type: string - format: date-time - updated_at: - type: string - format: date-time - required: - - name - - subject - - hosts - - created_at - - updated_at - caListResponse: - type: object - properties: - cas: - type: array - items: - type: object - properties: - name: - type: string - subject: - type: string - type: - type: string - created_at: - type: string - format: date-time - updated_at: - type: string - format: date-time - required: - - name - - subject - - type - - created_at - - updated_at - required: - - cas - certificateListResponse: - type: object - properties: - certificates: - type: array - items: - type: object - properties: - name: - type: string - subject: - type: string - hosts: - type: string - created_at: - type: string - format: date-time - updated_at: - type: string - format: date-time - required: - - name - - subject - - hosts - - created_at - - updated_at - required: - - certificates - configMapCreate: - type: object - properties: - name: - type: string - minLength: 1 - maxLength: 255 - immutable: - type: boolean - data: - type: object - required: - - name - - data - configMapUpdate: - type: object - properties: - immutable: - type: boolean - data: - type: object - required: - - data - configMapResponse: - type: object - properties: - id: - type: integer - name: - type: string - immutable: - type: boolean - data: - type: object - created_at: - type: string - format: date-time - updated_at: - type: string - format: date-time - required: - - id - - name - - data - - created_at - - updated_at - configMapListResponse: - type: object - properties: - configMaps: - type: array - items: - type: object - properties: - id: - type: integer - name: - type: string - immutable: - type: boolean - created_at: - type: string - format: date-time - updated_at: - type: string - format: date-time - required: - - id - - name - - created_at - - updated_at - required: - - configMaps - configUpdate: - type: object - properties: - port: - type: integer - minimum: 0 - maximum: 65535 - sslCert: - type: string - sslKey: - type: string - intermediateCert: - type: string - logDir: - type: string - logSize: - type: integer - configElement: - type: object - properties: - key: - type: string - minLength: 1 - value: - type: string - required: - - key - - value - profile: - type: object - properties: {} - straceStateUpdate: - type: object - properties: - enable: - type: boolean - required: - - enable - straceGetData: - type: object - properties: - format: - enum: - - string - - file - required: - - format - stracePostToFtp: - type: object - properties: - ftpHost: - type: string - ftpPort: - type: integer - minimum: 0 - ftpUser: - type: string - ftpPass: - type: string - ftpDestDir: - type: string - required: - - ftpHost - - ftpPort - - ftpUser - - ftpPass - - ftpDestDir - edgeResourceDisplay: - type: object - properties: - name: - type: string - color: - type: string - pattern: ^(#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{8}))|(rgb(s*(?:(d{1,3})s*,?){3}))|(rgba(s*(?:(d{1,3})s*,?){4}))|$ - icon: - type: string - edgeResourceHTTPEndpoint: - type: object - properties: - name: - type: string - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - description: - type: string - method: - enum: - - GET - - POST - - PUT - - PATCH - - DELETE - - HEAD - - OPTIONS - url: - type: string - requestType: - type: string - responseType: - type: string - requestPayloadExample: - type: string - responsePayloadExample: - type: string - edgeResource: - type: object - properties: - display: - $ref: '#/components/schemas/edgeResourceDisplay' - name: - type: string - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - version: - type: string - minLength: 1 - pattern: ^v?(0|[1-9]d*).(0|[1-9]d*).(0|[1-9]d*)(?:-((?:0|[1-9]d*|d*[a-zA-Z-][0-9a-zA-Z-]*)(?:.(?:0|[1-9]d*|d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:[+]([0-9a-zA-Z-]+(?:.[0-9a-zA-Z-]+)*))?$ - description: - type: string - orchestrationTags: - type: array - items: - type: string - interfaceProtocol: - enum: - - http - - https - - ws - - wss - oneOf: - - properties: - interfaceProtocol: - enum: - - http - - https - - ws - - wss - interface: - type: object - properties: - endpoints: - type: array - items: - $ref: /edgeResourceHTTPEndpoint - edgeResourceCreate: - type: object - allOf: - - $ref: '#/components/schemas/edgeResource' - required: - - name - - version - edgeResourceUpdate: - type: object - allOf: - - $ref: '#/components/schemas/edgeResource' - filter: - type: object - properties: - key: - type: string - value: - type: string - condition: - enum: - - has - - equals - required: - - key - - value - - condition - iofogTag: - type: string - iofogCreate: - type: object - properties: - name: - type: string - minLength: 1 - location: - type: string - latitude: - type: number - minimum: -90 - maximum: 90 - longitude: - type: number - minimum: -180 - maximum: 180 - description: - type: string - networkInterface: - type: string - dockerUrl: - type: string - containerEngine: - type: string - enum: - - docker - - podman - deploymentType: - type: string - enum: - - native - - container - diskLimit: - type: integer - minimum: 0 - diskDirectory: - type: string - memoryLimit: - type: integer - minimum: 0 - cpuLimit: - type: integer - minimum: 0 - logLimit: - type: integer - minimum: 0 - logDirectory: - type: string - logFileCount: - type: integer - minimum: 0 - statusFrequency: - type: integer - minimum: 0 - changeFrequency: - type: integer - minimum: 0 - deviceScanFrequency: - type: integer - minimum: 0 - bluetoothEnabled: - type: boolean - watchdogEnabled: - type: boolean - abstractedHardwareEnabled: - type: boolean - fogType: - type: integer - minimum: 0 - maximum: 2 - dockerPruningFrequency: - type: integer - minimum: 0 - availableDiskThreshold: - type: integer - minimum: 0 - logLevel: - type: string - isSystem: - type: boolean - routerMode: - enum: - - none - - edge - - interior - default: edge - messagingPort: - type: integer - minimum: 1 - maximum: 65535 - interRouterPort: - type: integer - minimum: 1 - maximum: 65535 - edgeRouterPort: - type: integer - minimum: 1 - maximum: 65535 - host: - type: string - tags: - type: array - items: - $ref: '#/components/schemas/iofogTag' - upstreamRouters: - type: array - items: - type: string - minLength: 1 - networkRouter: - type: string - timeZone: - type: string - anyOf: - - properties: - routerMode: {} - required: - - interRouterPort - - edgeRouterPort - - host - - properties: - routerMode: {} - required: - - host - - properties: - routerMode: {} - required: - - name - - fogType - iofogUpdate: - type: object - properties: - uuid: - type: string - name: - type: string - minLength: 1 - location: - type: string - latitude: - type: number - minimum: -90 - maximum: 90 - longitude: - type: number - minimum: -180 - maximum: 180 - description: - type: string - networkInterface: - type: string - dockerUrl: - type: string - containerEngine: - type: string - enum: - - docker - - podman - deploymentType: - type: string - enum: - - native - - container - diskLimit: - type: integer - minimum: 0 - diskDirectory: - type: string - memoryLimit: - type: integer - minimum: 0 - cpuLimit: - type: integer - minimum: 0 - logLimit: - type: integer - minimum: 0 - logDirectory: - type: string - logFileCount: - type: integer - minimum: 0 - statusFrequency: - type: integer - minimum: 0 - changeFrequency: - type: integer - minimum: 0 - deviceScanFrequency: - type: integer - minimum: 0 - bluetoothEnabled: - type: boolean - watchdogEnabled: - type: boolean - abstractedHardwareEnabled: - type: boolean - fogType: - type: integer - minimum: 0 - maximum: 2 - dockerPruningFrequency: - type: integer - minimum: 0 - availableDiskThreshold: - type: integer - minimum: 0 - logLevel: - type: string - isSystem: - type: boolean - routerMode: - enum: - - none - - edge - - interior - messagingPort: - type: integer - minimum: 1 - maximum: 65535 - interRouterPort: - type: integer - minimum: 1 - maximum: 65535 - edgeRouterPort: - type: integer - minimum: 1 - maximum: 65535 - host: - type: string - upstreamRouters: - type: array - items: - type: string - minLength: 1 - tags: - type: array - items: - $ref: '#/components/schemas/iofogTag' - networkRouter: - type: string - minLength: 1 - timeZone: - type: string - anyOf: - - properties: - routerMode: {} - required: - - interRouterPort - - edgeRouterPort - - host - - properties: - routerMode: {} - - properties: - routerMode: {} - required: - - uuid - iofogDelete: - type: object - properties: - uuid: - type: string - required: - - uuid - iofogGet: - type: object - properties: - uuid: - type: string - name: - type: string - oneOf: - - required: - - uuid - - required: - - name - iofogGenerateProvision: - type: object - properties: - uuid: - type: string - required: - - uuid - iofogSetVersionCommand: - type: object - properties: - uuid: - type: string - versionCommand: - enum: - - upgrade - - rollback - required: - - uuid - - versionCommand - iofogReboot: - type: object - properties: - uuid: - type: string - required: - - uuid - iofogFilters: - type: array - items: - $ref: '#/components/schemas/filter' - halGet: - type: object - properties: - uuid: - type: string - required: - - uuid - iofogPrune: - type: object - properties: - uuid: - type: string - required: - - uuid - defaultRouterCreate: - type: object - properties: - messagingPort: - type: integer - minimum: 1 - maximum: 65535 - interRouterPort: - type: integer - minimum: 1 - maximum: 65535 - edgeRouterPort: - type: integer - minimum: 1 - maximum: 65535 - requireSsl: - type: string - sslProfile: - type: string - saslMechanisms: - type: string - authenticatePeer: - type: string - caCert: - type: string - tlsCert: - type: string - tlsKey: - type: string - host: - type: string - required: - - host - microserviceCreate: - type: object - properties: - name: - type: string - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - config: - type: string - annotations: - type: string - catalogItemId: - type: integer - minimum: 4 - images: - type: array - maxItems: 2 - items: - $ref: '#/components/schemas/image' - registryId: - type: integer - application: - anyOf: - - type: string - - type: number - iofogUuid: - type: string - agentName: - type: string - rootHostAccess: - type: boolean - schedule: - type: integer - minimum: 0 - maximum: 100 - logSize: - type: integer - imageSnapshot: - type: string - volumeMappings: - type: array - items: - $ref: '#/components/schemas/volumeMappings' - ports: - type: array - items: - $ref: '#/components/schemas/ports' - extraHosts: - type: array - items: - $ref: '#/components/schemas/extraHosts' - routes: - type: array - items: - type: string - env: - type: array - items: - $ref: '#/components/schemas/env' - cmd: - type: array - items: - type: string - cdiDevices: - type: array - items: - type: string - capAdd: - type: array - items: - type: string - capDrop: - type: array - items: - type: string - runAsUser: - type: string - platform: - type: string - runtime: - type: string - pubTags: - type: array - items: - type: string - subTags: - type: array - items: - type: string - required: - - name - microserviceUpdate: - type: object - properties: - name: - type: string - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - config: - type: string - annotations: - type: string - rebuild: - type: boolean - iofogUuid: - type: string - agentName: - type: string - rootHostAccess: - type: boolean - logSize: - type: integer - minimum: 0 - schedule: - type: integer - minimum: 0 - maximum: 100 - volumeMappings: - type: array - items: - $ref: '#/components/schemas/volumeMappings' - images: - type: array - maxItems: 2 - minItems: 1 - items: - $ref: '#/components/schemas/image' - ports: - type: array - items: - $ref: '#/components/schemas/ports' - extraHosts: - type: array - items: - $ref: '#/components/schemas/extraHosts' - env: - type: array - items: - $ref: '#/components/schemas/env' - cmd: - type: array - items: - type: string - cdiDevices: - type: array - items: - type: string - capAdd: - type: array - items: - type: string - capDrop: - type: array - items: - type: string - runAsUser: - type: string - platform: - type: string - runtime: - type: string - pubTags: - type: array - items: - type: string - subTags: - type: array - items: - type: string - portsCreate: - type: object - properties: - internal: - type: integer - external: - type: integer - protocol: - enum: - - tcp - - udp - required: - - internal - - external - microserviceDelete: - type: object - properties: - withCleanup: - type: boolean - additionalProperties: - type: object - additionalProperties: true - registryCreate: - type: object - properties: - url: - type: string - minLength: 1 - isPublic: - type: boolean - username: - type: string - minLength: 1 - password: - type: string - email: - type: string - pattern: ^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$ - requiresCert: - type: boolean - certificate: - type: string - required: - - url - - isPublic - - username - - password - - email - registryDelete: - type: object - properties: - id: - type: integer - required: - - id - registryUpdate: - type: object - properties: - url: - type: string - minLength: 1 - isPublic: - type: boolean - username: - type: string - minLength: 1 - password: - type: string - email: - type: string - pattern: ^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$ - requiresCert: - type: boolean - certificate: - type: string - routingCreate: - type: object - properties: - name: - type: string - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - oneOf: - - properties: - from: - type: string - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - to: - type: string - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - application: - type: string - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - required: - - name - - from - - to - - properties: - sourceMicroserviceUuid: - type: string - destMicroserviceUuid: - type: string - required: - - name - - sourceMicroserviceUuid - - destMicroserviceUuid - routingUpdate: - type: object - properties: - name: - type: string - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - oneOf: - - properties: - from: - type: string - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - to: - type: string - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - application: - type: string - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - required: - - from - - to - - application - - properties: - sourceMicroserviceUuid: - type: string - destMicroserviceUuid: - type: string - required: - - sourceMicroserviceUuid - - destMicroserviceUuid - secretCreate: - type: object - properties: - name: - type: string - minLength: 1 - maxLength: 255 - type: - type: string - enum: - - opaque - - tls - data: - type: object - required: - - name - - type - - data - secretUpdate: - type: object - properties: - data: - type: object - required: - - data - secretResponse: - type: object - properties: - id: - type: integer - name: - type: string - type: - type: string - enum: - - opaque - - tls - data: - type: object - created_at: - type: string - format: date-time - updated_at: - type: string - format: date-time - required: - - id - - name - - type - - data - - created_at - - updated_at - secretListResponse: - type: object - properties: - secrets: - type: array - items: - type: object - properties: - id: - type: integer - name: - type: string - type: - type: string - enum: - - opaque - - tls - created_at: - type: string - format: date-time - updated_at: - type: string - format: date-time - required: - - id - - name - - type - - created_at - - updated_at - required: - - secrets - serviceTag: - type: string - serviceCreate: - type: object - required: - - name - - type - - resource - - targetPort - properties: - name: - type: string - pattern: ^[a-z0-9]([a-z0-9-]*[a-z0-9])?$ - type: - type: string - enum: - - microservice - - k8s - - agent - - external - resource: - type: string - required: - - cpu - - memory - targetPort: - type: integer - defaultBridge: - type: string - servicePort: - type: integer - k8sType: - type: string - enum: - - LoadBalancer - - ClusterIP - - NodePort - tags: - type: array - items: - $ref: '#/components/schemas/serviceTag' - serviceUpdate: - type: object - required: - - name - properties: - name: - type: string - pattern: ^[a-z0-9]([a-z0-9-]*[a-z0-9])?$ - type: - type: string - enum: - - microservice - - k8s - - agent - - external - resource: - type: string - targetPort: - type: integer - defaultBridge: - type: string - servicePort: - type: integer - k8sType: - type: string - enum: - - LoadBalancer - - ClusterIP - - NodePort - tags: - type: array - items: - $ref: '#/components/schemas/serviceTag' - tunnelCreate: - type: object - properties: - iofogUuid: - type: string - username: - type: string - minLength: 1 - password: - type: string - rsakey: - type: string - lport: - type: integer - minimum: 0 - maximum: 65535 - rport: - type: integer - minimum: 0 - maximum: 65535 - required: - - iofogUuid - - username - - password - - lport - - rport - login: - type: object - properties: - email: - type: string - pattern: ^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$ - password: - type: string - totp: - type: string - required: - - email - - password - refresh: - type: object - properties: - refreshToken: - type: string - required: - - refreshToken - volumeMountCreate: - type: object - properties: - name: - type: string - pattern: ^[a-z0-9]([a-z0-9-]*[a-z0-9])?$ - secretName: - type: string - configMapName: - type: string - required: - - name - oneOf: - - required: - - secretName - - required: - - configMapName - volumeMountUpdate: - type: object - properties: - name: - type: string - pattern: ^[a-z0-9]([a-z0-9-]*[a-z0-9])?$ - secretName: - type: string - configMapName: - type: string - oneOf: - - required: - - secretName - - required: - - configMapName - volumeMountLink: - type: object - properties: - fogUuids: - type: array - items: - type: string - minItems: 1 - required: - - fogUuids - volumeMountUnlink: - type: object - properties: - fogUuids: - type: array - items: - type: string - minItems: 1 - required: - - fogUuids -security: - - authToken: [] -paths: - /agent/provision: - post: - tags: - - Agent - summary: POST /api/v3/agent/provision - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/agentProvision' - /agent/deprovision: - post: - tags: - - Agent - summary: POST /api/v3/agent/deprovision - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/agentProvision' - /agent/config: - get: - tags: - - Agent - summary: GET /api/v3/agent/config - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - patch: - tags: - - Agent - summary: PATCH /api/v3/agent/config - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - /agent/config/changes: - get: - tags: - - Agent - summary: GET /api/v3/agent/config/changes - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - patch: - tags: - - Agent - summary: PATCH /api/v3/agent/config/changes - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - /agent/status: - put: - tags: - - Agent - summary: PUT /api/v3/agent/status - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/updateAgentConfig' - /agent/edgeResources: - get: - tags: - - Agent - summary: GET /api/v3/agent/edgeResources - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /agent/volumeMounts: - get: - tags: - - Agent - summary: GET /api/v3/agent/volumeMounts - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /agent/microservices: - get: - tags: - - Agent - summary: GET /api/v3/agent/microservices - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - properties: - microservices: - type: array - items: - type: object - properties: - uuid: - type: string - name: - type: string - config: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /agent/microservices/{microserviceUuid}: - get: - tags: - - Agent - summary: GET /api/v3/agent/microservices/:microserviceUuid - security: - - authToken: [] - parameters: - - name: microserviceUuid - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - properties: - microservices: - type: array - items: - type: object - properties: - uuid: - type: string - name: - type: string - config: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /agent/registries: - get: - tags: - - Agent - summary: GET /api/v3/agent/registries - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /agent/tunnel: - get: - tags: - - Agent - summary: GET /api/v3/agent/tunnel - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /agent/strace: - get: - tags: - - Agent - summary: GET /api/v3/agent/strace - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - put: - tags: - - Agent - summary: PUT /api/v3/agent/strace - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/updateAgentConfig' - /agent/version: - get: - tags: - - Agent - summary: GET /api/v3/agent/version - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /agent/hal/hw: - put: - tags: - - Agent - summary: PUT /api/v3/agent/hal/hw - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/updateAgentConfig' - /agent/hal/usb: - put: - tags: - - Agent - summary: PUT /api/v3/agent/hal/usb - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/updateAgentConfig' - /agent/delete-node: - delete: - tags: - - Agent - summary: DELETE /api/v3/agent/delete-node - security: - - authToken: [] - parameters: [] - responses: - '204': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /agent/image-snapshot: - get: - tags: - - Agent - summary: GET /api/v3/agent/image-snapshot - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - put: - tags: - - Agent - summary: PUT /api/v3/agent/image-snapshot - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/updateAgentConfig' - /agent/cert: - get: - tags: - - Agent - summary: GET /api/v3/agent/cert - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /application: - get: - tags: - - Application - summary: GET /api/v3/application - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - properties: - applications: - type: array - items: - type: object - properties: - name: - type: string - description: - type: string - version: - type: string - microservices: - type: array - items: - type: object - properties: - name: - type: string - config: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - post: - tags: - - Application - summary: POST /api/v3/application - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/applicationCreate' - /application/system: - get: - tags: - - Application - summary: GET /api/v3/application/system - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - properties: - applications: - type: array - items: - type: object - properties: - name: - type: string - description: - type: string - version: - type: string - microservices: - type: array - items: - type: object - properties: - name: - type: string - config: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /application/yaml: - post: - tags: - - Application - summary: POST /api/v3/application/yaml - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - multipart/form-data: - schema: - type: object - properties: - application: - type: string - format: binary - /application/{name}: - get: - tags: - - Application - summary: GET /api/v3/application/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - properties: - applications: - type: array - items: - type: object - properties: - name: - type: string - description: - type: string - version: - type: string - microservices: - type: array - items: - type: object - properties: - name: - type: string - config: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - patch: - tags: - - Application - summary: PATCH /api/v3/application/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/applicationPatch' - put: - tags: - - Application - summary: PUT /api/v3/application/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/applicationUpdate' - delete: - tags: - - Application - summary: DELETE /api/v3/application/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '204': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /application/system/{name}: - get: - tags: - - Application - summary: GET /api/v3/application/system/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - properties: - applications: - type: array - items: - type: object - properties: - name: - type: string - description: - type: string - version: - type: string - microservices: - type: array - items: - type: object - properties: - name: - type: string - config: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - delete: - tags: - - Application - summary: DELETE /api/v3/application/system/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '204': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /application/yaml/{name}: - put: - tags: - - Application - summary: PUT /api/v3/application/yaml/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/applicationUpdate' - /applicationTemplates: - get: - tags: - - Application - summary: GET /api/v3/applicationTemplates - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - properties: - applications: - type: array - items: - type: object - properties: - name: - type: string - description: - type: string - version: - type: string - microservices: - type: array - items: - type: object - properties: - name: - type: string - config: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /applicationTemplate: - post: - tags: - - Application - summary: POST /api/v3/applicationTemplate - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/applicationCreate' - /applicationTemplate/yaml: - post: - tags: - - Application - summary: POST /api/v3/applicationTemplate/yaml - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - multipart/form-data: - schema: - type: object - properties: - application: - type: string - format: binary - /applicationTemplate/{name}: - get: - tags: - - Application - summary: GET /api/v3/applicationTemplate/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - properties: - applications: - type: array - items: - type: object - properties: - name: - type: string - description: - type: string - version: - type: string - microservices: - type: array - items: - type: object - properties: - name: - type: string - config: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - patch: - tags: - - Application - summary: PATCH /api/v3/applicationTemplate/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/applicationPatch' - put: - tags: - - Application - summary: PUT /api/v3/applicationTemplate/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/applicationUpdate' - delete: - tags: - - Application - summary: DELETE /api/v3/applicationTemplate/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '204': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /applicationTemplate/yaml/{name}: - put: - tags: - - Application - summary: PUT /api/v3/applicationTemplate/yaml/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/applicationUpdate' - /capabilities/edgeResources: - head: - tags: - - Controller - summary: HEAD /api/v3/capabilities/edgeResources - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /capabilities/applicationTemplates: - head: - tags: - - Controller - summary: HEAD /api/v3/capabilities/applicationTemplates - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /catalog/microservices: - get: - tags: - - Catalog - summary: GET /api/v3/catalog/microservices - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - properties: - microservices: - type: array - items: - type: object - properties: - uuid: - type: string - name: - type: string - config: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - post: - tags: - - Catalog - summary: POST /api/v3/catalog/microservices - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/microserviceCreate' - /catalog/microservices/{id}: - get: - tags: - - Catalog - summary: GET /api/v3/catalog/microservices/:id - security: - - authToken: [] - parameters: - - name: id - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - properties: - microservices: - type: array - items: - type: object - properties: - uuid: - type: string - name: - type: string - config: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - patch: - tags: - - Catalog - summary: PATCH /api/v3/catalog/microservices/:id - security: - - authToken: [] - parameters: - - name: id - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - delete: - tags: - - Catalog - summary: DELETE /api/v3/catalog/microservices/:id - security: - - authToken: [] - parameters: - - name: id - in: path - required: true - schema: - type: string - responses: - '204': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /certificates/ca: - post: - tags: - - Certificates - summary: POST /api/v3/certificates/ca - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/certificateCreate' - get: - tags: - - Certificates - summary: GET /api/v3/certificates/ca - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /certificates/ca/{name}: - get: - tags: - - Certificates - summary: GET /api/v3/certificates/ca/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - delete: - tags: - - Certificates - summary: DELETE /api/v3/certificates/ca/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '204': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /certificates: - post: - tags: - - Certificates - summary: POST /api/v3/certificates - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/certificateCreate' - get: - tags: - - Certificates - summary: GET /api/v3/certificates - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /certificates/expiring: - get: - tags: - - Certificates - summary: GET /api/v3/certificates/expiring - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /certificates/{name}: - get: - tags: - - Certificates - summary: GET /api/v3/certificates/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - delete: - tags: - - Certificates - summary: DELETE /api/v3/certificates/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '204': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /certificates/{name}/renew: - post: - tags: - - Certificates - summary: POST /api/v3/certificates/:name/renew - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/certificateCreate' - /certificates/yaml: - post: - tags: - - Certificates - summary: POST /api/v3/certificates/yaml - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - multipart/form-data: - schema: - type: object - properties: - application: - type: string - format: binary - /config: - get: - tags: - - ConfigMap - summary: GET /api/v3/config - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - put: - tags: - - ConfigMap - summary: PUT /api/v3/config - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/configUpdate' - /config/{key}: - get: - tags: - - ConfigMap - summary: GET /api/v3/config/:key - security: - - authToken: [] - parameters: - - name: key - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /configmaps: - post: - tags: - - ConfigMap - summary: POST /api/v3/configmaps - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - get: - tags: - - ConfigMap - summary: GET /api/v3/configmaps - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /configmaps/yaml: - post: - tags: - - ConfigMap - summary: POST /api/v3/configmaps/yaml - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - multipart/form-data: - schema: - type: object - properties: - application: - type: string - format: binary - /configmaps/{name}: - patch: - tags: - - ConfigMap - summary: PATCH /api/v3/configmaps/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - get: - tags: - - ConfigMap - summary: GET /api/v3/configmaps/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - delete: - tags: - - ConfigMap - summary: DELETE /api/v3/configmaps/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '204': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /configmaps/yaml/{name}: - patch: - tags: - - ConfigMap - summary: PATCH /api/v3/configmaps/yaml/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - /status: - get: - tags: - - Controller - summary: GET /api/v3/status - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /fog-types/: - get: - tags: - - Controller - summary: GET /api/v3/fog-types/ - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /microservices/{uuid}/image-snapshot: - post: - tags: - - Microservices - summary: POST /api/v3/microservices/:uuid/image-snapshot - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/microserviceCreate' - get: - tags: - - Microservices - summary: GET /api/v3/microservices/:uuid/image-snapshot - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - properties: - microservices: - type: array - items: - type: object - properties: - uuid: - type: string - name: - type: string - config: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /microservices/{uuid}/strace: - patch: - tags: - - Microservices - summary: PATCH /api/v3/microservices/:uuid/strace - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - get: - tags: - - Microservices - summary: GET /api/v3/microservices/:uuid/strace - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - properties: - microservices: - type: array - items: - type: object - properties: - uuid: - type: string - name: - type: string - config: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - put: - tags: - - Microservices - summary: PUT /api/v3/microservices/:uuid/strace - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/microserviceUpdate' - /edgeResources: - get: - tags: - - Edge Resource - summary: GET /api/v3/edgeResources - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /edgeResource/{name}/{version}: - get: - tags: - - Edge Resource - summary: GET /api/v3/edgeResource/:name/:version - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - - name: version - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - put: - tags: - - Edge Resource - summary: PUT /api/v3/edgeResource/:name/:version - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - - name: version - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/edgeResourceUpdate' - delete: - tags: - - Edge Resource - summary: DELETE /api/v3/edgeResource/:name/:version - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - - name: version - in: path - required: true - schema: - type: string - responses: - '204': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /edgeResource/{name}: - get: - tags: - - Edge Resource - summary: GET /api/v3/edgeResource/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /edgeResource: - post: - tags: - - Edge Resource - summary: POST /api/v3/edgeResource - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/edgeResourceCreate' - /edgeResource/{name}/{version}/link: - post: - tags: - - Edge Resource - summary: POST /api/v3/edgeResource/:name/:version/link - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - - name: version - in: path - required: true - schema: - type: string - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/edgeResourceCreate' - delete: - tags: - - Edge Resource - summary: DELETE /api/v3/edgeResource/:name/:version/link - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - - name: version - in: path - required: true - schema: - type: string - responses: - '204': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /flow: - get: - tags: - - Application - summary: GET /api/v3/flow - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - post: - tags: - - Application - summary: POST /api/v3/flow - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - /flow/{id}: - get: - tags: - - Application - summary: GET /api/v3/flow/:id - security: - - authToken: [] - parameters: - - name: id - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - patch: - tags: - - Application - summary: PATCH /api/v3/flow/:id - security: - - authToken: [] - parameters: - - name: id - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - delete: - tags: - - Application - summary: DELETE /api/v3/flow/:id - security: - - authToken: [] - parameters: - - name: id - in: path - required: true - schema: - type: string - responses: - '204': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /iofog-list: - get: - tags: - - ioFog - summary: GET /api/v3/iofog-list - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /iofog: - post: - tags: - - ioFog - summary: POST /api/v3/iofog - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/iofogCreate' - /iofog/{uuid}: - patch: - tags: - - ioFog - summary: PATCH /api/v3/iofog/:uuid - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - delete: - tags: - - ioFog - summary: DELETE /api/v3/iofog/:uuid - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '204': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - get: - tags: - - ioFog - summary: GET /api/v3/iofog/:uuid - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /iofog/{uuid}/provisioning-key: - get: - tags: - - ioFog - summary: GET /api/v3/iofog/:uuid/provisioning-key - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /iofog/{uuid}/version/{versionCommand}: - post: - tags: - - ioFog - summary: POST /api/v3/iofog/:uuid/version/:versionCommand - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - - name: versionCommand - in: path - required: true - schema: - type: string - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/iofogCreate' - /iofog/{uuid}/reboot: - post: - tags: - - ioFog - summary: POST /api/v3/iofog/:uuid/reboot - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/iofogCreate' - /iofog/{uuid}/hal/hw: - get: - tags: - - ioFog - summary: GET /api/v3/iofog/:uuid/hal/hw - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /iofog/{uuid}/hal/usb: - get: - tags: - - ioFog - summary: GET /api/v3/iofog/:uuid/hal/usb - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /iofog/{uuid}/prune: - post: - tags: - - ioFog - summary: POST /api/v3/iofog/:uuid/prune - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/iofogCreate' - /microservices/: - get: - tags: - - Microservices - summary: GET /api/v3/microservices/ - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - properties: - microservices: - type: array - items: - type: object - properties: - uuid: - type: string - name: - type: string - config: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /microservices/system: - get: - tags: - - Microservices - summary: GET /api/v3/microservices/system - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - properties: - microservices: - type: array - items: - type: object - properties: - uuid: - type: string - name: - type: string - config: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /microservices: - post: - tags: - - Microservices - summary: POST /api/v3/microservices - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/microserviceCreate' - /microservices/yaml: - post: - tags: - - Microservices - summary: POST /api/v3/microservices/yaml - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - multipart/form-data: - schema: - type: object - properties: - application: - type: string - format: binary - /microservices/{uuid}: - get: - tags: - - Microservices - summary: GET /api/v3/microservices/:uuid - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - properties: - microservices: - type: array - items: - type: object - properties: - uuid: - type: string - name: - type: string - config: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - patch: - tags: - - Microservices - summary: PATCH /api/v3/microservices/:uuid - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - delete: - tags: - - Microservices - summary: DELETE /api/v3/microservices/:uuid - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '204': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /microservices/system/{uuid}: - get: - tags: - - Microservices - summary: GET /api/v3/microservices/system/:uuid - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - properties: - microservices: - type: array - items: - type: object - properties: - uuid: - type: string - name: - type: string - config: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - patch: - tags: - - Microservices - summary: PATCH /api/v3/microservices/system/:uuid - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - /microservices/pub/{tag}: - get: - tags: - - Microservices - summary: GET /api/v3/microservices/pub/:tag - security: - - authToken: [] - parameters: - - name: tag - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - properties: - microservices: - type: array - items: - type: object - properties: - uuid: - type: string - name: - type: string - config: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /microservices/sub/{tag}: - get: - tags: - - Microservices - summary: GET /api/v3/microservices/sub/:tag - security: - - authToken: [] - parameters: - - name: tag - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - properties: - microservices: - type: array - items: - type: object - properties: - uuid: - type: string - name: - type: string - config: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /microservices/{uuid}/rebuild: - patch: - tags: - - Microservices - summary: PATCH /api/v3/microservices/:uuid/rebuild - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - /microservices/system/{uuid}/rebuild: - patch: - tags: - - Microservices - summary: PATCH /api/v3/microservices/system/:uuid/rebuild - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - /microservices/yaml/{uuid}: - patch: - tags: - - Microservices - summary: PATCH /api/v3/microservices/yaml/:uuid - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - /microservices/system/yaml/{uuid}: - patch: - tags: - - Microservices - summary: PATCH /api/v3/microservices/system/yaml/:uuid - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - /microservices/{uuid}/routes/{receiverUuid}: - post: - tags: - - Microservices - summary: POST /api/v3/microservices/:uuid/routes/:receiverUuid - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - - name: receiverUuid - in: path - required: true - schema: - type: string - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/microserviceCreate' - delete: - tags: - - Microservices - summary: DELETE /api/v3/microservices/:uuid/routes/:receiverUuid - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - - name: receiverUuid - in: path - required: true - schema: - type: string - responses: - '204': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /microservices/{uuid}/port-mapping: - post: - tags: - - Microservices - summary: POST /api/v3/microservices/:uuid/port-mapping - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/microserviceCreate' - get: - tags: - - Microservices - summary: GET /api/v3/microservices/:uuid/port-mapping - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - properties: - microservices: - type: array - items: - type: object - properties: - uuid: - type: string - name: - type: string - config: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /microservices/system/{uuid}/port-mapping: - post: - tags: - - Microservices - summary: POST /api/v3/microservices/system/:uuid/port-mapping - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/microserviceCreate' - /microservices/{uuid}/port-mapping/{internalPort}: - delete: - tags: - - Microservices - summary: DELETE /api/v3/microservices/:uuid/port-mapping/:internalPort - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - - name: internalPort - in: path - required: true - schema: - type: string - responses: - '204': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /microservices/system/{uuid}/port-mapping/{internalPort}: - delete: - tags: - - Microservices - summary: DELETE /api/v3/microservices/system/:uuid/port-mapping/:internalPort - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - - name: internalPort - in: path - required: true - schema: - type: string - responses: - '204': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /microservices/{uuid}/volume-mapping: - get: - tags: - - Microservices - summary: GET /api/v3/microservices/:uuid/volume-mapping - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - properties: - microservices: - type: array - items: - type: object - properties: - uuid: - type: string - name: - type: string - config: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - post: - tags: - - Microservices - summary: POST /api/v3/microservices/:uuid/volume-mapping - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/microserviceCreate' - /microservices/system/{uuid}/volume-mapping: - post: - tags: - - Microservices - summary: POST /api/v3/microservices/system/:uuid/volume-mapping - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/microserviceCreate' - /microservices/{uuid}/volume-mapping/{id}: - delete: - tags: - - Microservices - summary: DELETE /api/v3/microservices/:uuid/volume-mapping/:id - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - - name: id - in: path - required: true - schema: - type: string - responses: - '204': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /microservices/system/{uuid}/volume-mapping/{id}: - delete: - tags: - - Microservices - summary: DELETE /api/v3/microservices/system/:uuid/volume-mapping/:id - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - - name: id - in: path - required: true - schema: - type: string - responses: - '204': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /microservices/{uuid}/exec: - post: - tags: - - Microservices - summary: POST /api/v3/microservices/:uuid/exec - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/microserviceCreate' - delete: - tags: - - Microservices - summary: DELETE /api/v3/microservices/:uuid/exec - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '204': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /microservices/system/{uuid}/exec: - post: - tags: - - Microservices - summary: POST /api/v3/microservices/system/:uuid/exec - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/microserviceCreate' - delete: - tags: - - Microservices - summary: DELETE /api/v3/microservices/system/:uuid/exec - security: - - authToken: [] - parameters: - - name: uuid - in: path - required: true - schema: - type: string - responses: - '204': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /registries: - post: - tags: - - Registries - summary: POST /api/v3/registries - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - get: - tags: - - Registries - summary: GET /api/v3/registries - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /registries/{id}: - delete: - tags: - - Registries - summary: DELETE /api/v3/registries/:id - security: - - authToken: [] - parameters: - - name: id - in: path - required: true - schema: - type: string - responses: - '204': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - patch: - tags: - - Registries - summary: PATCH /api/v3/registries/:id - security: - - authToken: [] - parameters: - - name: id - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - /router: - get: - tags: - - Router - summary: GET /api/v3/router - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - put: - tags: - - Router - summary: PUT /api/v3/router - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - /routes: - get: - tags: - - Routing - summary: GET /api/v3/routes - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - post: - tags: - - Routing - summary: POST /api/v3/routes - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - /routes/{appName}/{name}: - get: - tags: - - Routing - summary: GET /api/v3/routes/:appName/:name - security: - - authToken: [] - parameters: - - name: appName - in: path - required: true - schema: - type: string - - name: name - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - patch: - tags: - - Routing - summary: PATCH /api/v3/routes/:appName/:name - security: - - authToken: [] - parameters: - - name: appName - in: path - required: true - schema: - type: string - - name: name - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - delete: - tags: - - Routing - summary: DELETE /api/v3/routes/:appName/:name - security: - - authToken: [] - parameters: - - name: appName - in: path - required: true - schema: - type: string - - name: name - in: path - required: true - schema: - type: string - responses: - '204': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /secrets: - post: - tags: - - Secrets - summary: POST /api/v3/secrets - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/secretCreate' - get: - tags: - - Secrets - summary: GET /api/v3/secrets - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /secrets/yaml: - post: - tags: - - Secrets - summary: POST /api/v3/secrets/yaml - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - multipart/form-data: - schema: - type: object - properties: - application: - type: string - format: binary - /secrets/{name}: - patch: - tags: - - Secrets - summary: PATCH /api/v3/secrets/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - get: - tags: - - Secrets - summary: GET /api/v3/secrets/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - delete: - tags: - - Secrets - summary: DELETE /api/v3/secrets/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '204': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /secrets/yaml/{name}: - patch: - tags: - - Secrets - summary: PATCH /api/v3/secrets/yaml/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - /services: - get: - tags: - - Services - summary: GET /api/v3/services - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - post: - tags: - - Services - summary: POST /api/v3/services - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/serviceCreate' - /services/{name}: - get: - tags: - - Services - summary: GET /api/v3/services/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - patch: - tags: - - Services - summary: PATCH /api/v3/services/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - delete: - tags: - - Services - summary: DELETE /api/v3/services/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '204': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /services/yaml: - post: - tags: - - Services - summary: POST /api/v3/services/yaml - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - multipart/form-data: - schema: - type: object - properties: - application: - type: string - format: binary - /services/yaml/{name}: - patch: - tags: - - Services - summary: PATCH /api/v3/services/yaml/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - /iofog/{id}/tunnel: - patch: - tags: - - ioFog - summary: PATCH /api/v3/iofog/:id/tunnel - security: - - authToken: [] - parameters: - - name: id - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - get: - tags: - - ioFog - summary: GET /api/v3/iofog/:id/tunnel - security: - - authToken: [] - parameters: - - name: id - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /user/login: - post: - tags: - - User - summary: POST /api/v3/user/login - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/login' - /user/refresh: - post: - tags: - - User - summary: POST /api/v3/user/refresh - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/login' - /user/profile: - get: - tags: - - User - summary: GET /api/v3/user/profile - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /user/logout: - post: - tags: - - User - summary: POST /api/v3/user/logout - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/login' - /volumeMounts: - get: - tags: - - VolumeMounts - summary: GET /api/v3/volumeMounts - security: - - authToken: [] - parameters: [] - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - post: - tags: - - VolumeMounts - summary: POST /api/v3/volumeMounts - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/volumeMountCreate' - /volumeMounts/{name}: - get: - tags: - - VolumeMounts - summary: GET /api/v3/volumeMounts/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - patch: - tags: - - VolumeMounts - summary: PATCH /api/v3/volumeMounts/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - delete: - tags: - - VolumeMounts - summary: DELETE /api/v3/volumeMounts/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '204': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - /volumeMounts/yaml: - post: - tags: - - VolumeMounts - summary: POST /api/v3/volumeMounts/yaml - security: - - authToken: [] - parameters: [] - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - multipart/form-data: - schema: - type: object - properties: - application: - type: string - format: binary - /volumeMounts/yaml/{name}: - patch: - tags: - - VolumeMounts - summary: PATCH /api/v3/volumeMounts/yaml/:name - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - type: object - /volumeMounts/{name}/link: - post: - tags: - - VolumeMounts - summary: POST /api/v3/volumeMounts/:name/link - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '201': - description: Created - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - content: - application/json: - schema: - type: object - '400': - description: Bad Request - '401': - description: Not Authorized - '409': - description: Duplicate Name - '500': - description: Internal Server Error - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/volumeMountCreate' - delete: - tags: - - VolumeMounts - summary: DELETE /api/v3/volumeMounts/:name/link - security: - - authToken: [] - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - '204': - description: Success - headers: - X-Timestamp: - description: FogController server timestamp - schema: - type: number - '401': - description: Not Authorized - '404': - description: Not Found - '500': - description: Internal Server Error diff --git a/docs/swagger.yaml b/docs/swagger.yaml index c7b83042..239d5296 100755 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -6204,12 +6204,6 @@ components: type: string isPublic: type: boolean - isSecure: - type: boolean - certificate: - type: string - requiresCert: - type: boolean username: type: string password: @@ -6229,10 +6223,6 @@ components: type: string email: type: string - requiresCert: - type: boolean - certificate: - type: string ActionBody: type: object properties: diff --git a/generate-swagger.sh b/generate-swagger.sh index 3b458750..cf964e82 100755 --- a/generate-swagger.sh +++ b/generate-swagger.sh @@ -1,2 +1,2 @@ #!/bin/bash -node scripts/generate-swagger.js \ No newline at end of file +docker run -v ./docs:/docs mitjaziv/swagger-codegen-cli generate -i /docs/swagger.yaml -l swagger -o /docs \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 0ab344b8..53a57d01 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@datasance/iofogcontroller", - "version": "3.5.6", + "version": "3.5.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@datasance/iofogcontroller", - "version": "3.5.6", + "version": "3.5.7", "hasInstallScript": true, "license": "EPL-2.0", "dependencies": { @@ -55,7 +55,7 @@ "os": "0.1.2", "path": "0.12.7", "pg": "8.12.0", - "pino": "9.1.0", + "pino": "9.13.1", "pino-std-serializers": "7.0.0", "portscanner": "2.2.0", "qs": "6.12.1", @@ -2422,17 +2422,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -5466,22 +5455,6 @@ "es5-ext": "~0.10.14" } }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "engines": { - "node": ">=0.8.x" - } - }, "node_modules/eventuate": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/eventuate/-/eventuate-4.0.0.tgz", @@ -5829,14 +5802,6 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, - "node_modules/fast-redact": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", - "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", - "engines": { - "node": ">=6" - } - }, "node_modules/fast-safe-stringify": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", @@ -10582,19 +10547,19 @@ } }, "node_modules/pino": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-9.1.0.tgz", - "integrity": "sha512-qUcgfrlyOtjwhNLdbhoL7NR4NkHjzykAPw0V2QLFbvu/zss29h4NkRnibyFzBrNCbzCOY3WZ9hhKSwfOkNggYA==", + "version": "9.13.1", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.13.1.tgz", + "integrity": "sha512-Szuj+ViDTjKPQYiKumGmEn3frdl+ZPSdosHyt9SnUevFosOkMY2b7ipxlEctNKPmMD/VibeBI+ZcZCJK+4DPuw==", "dependencies": { "atomic-sleep": "^1.0.0", - "fast-redact": "^3.1.1", "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^1.2.0", + "pino-abstract-transport": "^2.0.0", "pino-std-serializers": "^7.0.0", - "process-warning": "^3.0.0", + "process-warning": "^5.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.2.0", "safe-stable-stringify": "^2.3.1", + "slow-redact": "^0.3.0", "sonic-boom": "^4.0.1", "thread-stream": "^3.0.0" }, @@ -10603,60 +10568,13 @@ } }, "node_modules/pino-abstract-transport": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", - "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", "dependencies": { - "readable-stream": "^4.0.0", "split2": "^4.0.0" } }, - "node_modules/pino-abstract-transport/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/pino-abstract-transport/node_modules/readable-stream": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", - "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/pino-abstract-transport/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, "node_modules/pino-std-serializers": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", @@ -11240,9 +11158,19 @@ } }, "node_modules/process-warning": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", - "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==" + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", + "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ] }, "node_modules/progress": { "version": "2.0.3", @@ -12698,6 +12626,11 @@ "node": ">=4" } }, + "node_modules/slow-redact": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/slow-redact/-/slow-redact-0.3.1.tgz", + "integrity": "sha512-NvFvl1GuLZNW4U046Tfi8b26zXo8aBzgCAS2f7yVJR/fArN93mOqSA99cB9uITm92ajSz01bsu1K7SCVVjIMpQ==" + }, "node_modules/smart-buffer": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", @@ -14066,9 +13999,9 @@ } }, "node_modules/tar-fs": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz", - "integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", diff --git a/package.json b/package.json index c84a8064..8aaacfb2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@datasance/iofogcontroller", - "version": "3.5.6", + "version": "3.5.7", "description": "ioFog Controller project for Datasance PoT @ datasance.com \\nCopyright (c) 2023 Datasance Teknoloji A.S.", "main": "./src/main.js", "author": "Emirhan Durmus", @@ -100,7 +100,7 @@ "os": "0.1.2", "path": "0.12.7", "pg": "8.12.0", - "pino": "9.1.0", + "pino": "9.13.1", "pino-std-serializers": "7.0.0", "portscanner": "2.2.0", "qs": "6.12.1", @@ -150,7 +150,7 @@ }, "sqlite3": { "prebuild-install": { - "tar-fs": "^2.1.3" + "tar-fs": "^2.1.4" } } } diff --git a/scripts/generate-swagger.js b/scripts/generate-swagger.js deleted file mode 100644 index e04a61ee..00000000 --- a/scripts/generate-swagger.js +++ /dev/null @@ -1,778 +0,0 @@ -const fs = require('fs') -const path = require('path') -const yaml = require('js-yaml') - -// Base Swagger configuration -const swaggerBase = { - openapi: '3.0.0', - info: { - title: 'Datasance PoT Controller', - version: '3.5.0', - description: 'Datasance PoT Controller REST API Documentation' - }, - servers: [ - { - url: 'http://localhost:51121/api/v3' - } - ], - tags: [ - { name: 'Controller', description: 'Manage your controller' }, - { name: 'ioFog', description: 'Manage your agents' }, - { name: 'Application', description: 'Manage your applications' }, - { name: 'Application Template', description: 'Manage your application templates' }, - { name: 'Catalog', description: 'Manage your catalog' }, - { name: 'Registries', description: 'Manage your registries' }, - { name: 'Microservices', description: 'Manage your microservices' }, - { name: 'Routing', description: 'Manage your routes' }, - { name: 'Router', description: 'Manage your Default Router' }, - { name: 'Edge Resource', description: 'Manage your Edge Resources' }, - { name: 'Diagnostics', description: 'Diagnostic your microservices' }, - { name: 'Tunnel', description: 'Manage ssh tunnels' }, - { name: 'Agent', description: 'Used by your agents to communicate with your controller' }, - { name: 'User', description: 'Manage your users' }, - { name: 'Secrets', description: 'Manage your secrets' }, - { name: 'Certificates', description: 'Manage your certificates' }, - { name: 'Services', description: 'Manage your services' }, - { name: 'VolumeMounts', description: 'Manage your volume mounts' }, - { name: 'ConfigMap', description: 'Manage your config maps' } - ], - components: { - securitySchemes: { - authToken: { - type: 'http', - scheme: 'bearer', - bearerFormat: 'JWT', - description: 'JWT token for authentication (user or agent)' - } - }, - schemas: {} - }, - security: [ - { - authToken: [] - } - ], - paths: {} -} - -// Common response headers -const commonHeaders = { - 'X-Timestamp': { - description: 'FogController server timestamp', - schema: { - type: 'number' - } - } -} - -// Map HTTP methods to response schemas -const responseSchemas = { - get: { - '200': { - description: 'Success', - headers: commonHeaders, - content: { - 'application/json': { - schema: { - type: 'object' - } - } - } - }, - '401': { - description: 'Not Authorized' - }, - '404': { - description: 'Not Found' - }, - '500': { - description: 'Internal Server Error' - } - }, - post: { - '201': { - description: 'Created', - headers: commonHeaders, - content: { - 'application/json': { - schema: { - type: 'object' - } - } - } - }, - '400': { - description: 'Bad Request' - }, - '401': { - description: 'Not Authorized' - }, - '409': { - description: 'Duplicate Name' - }, - '500': { - description: 'Internal Server Error' - } - }, - put: { - '200': { - description: 'Success', - headers: commonHeaders, - content: { - 'application/json': { - schema: { - type: 'object' - } - } - } - }, - '400': { - description: 'Bad Request' - }, - '401': { - description: 'Not Authorized' - }, - '404': { - description: 'Not Found' - }, - '500': { - description: 'Internal Server Error' - } - }, - delete: { - '204': { - description: 'Success', - headers: commonHeaders - }, - '401': { - description: 'Not Authorized' - }, - '404': { - description: 'Not Found' - }, - '500': { - description: 'Internal Server Error' - } - } -} - -// Convert JSON Schema to OpenAPI Schema -function convertJsonSchemaToOpenAPI (schema) { - if (!schema) return {} - const openAPISchema = { ...schema } - - // Remove JSON Schema specific properties - delete openAPISchema.id - delete openAPISchema.$schema - - // Remove OpenAPI-incompatible properties - delete openAPISchema.if - delete openAPISchema.then - delete openAPISchema.const - delete openAPISchema.optional - - // Handle required arrays - if (openAPISchema.required && Array.isArray(openAPISchema.required) && openAPISchema.required.length === 0) { - delete openAPISchema.required - } - - // Convert $ref to OpenAPI format - if (openAPISchema.$ref) { - const refPath = openAPISchema.$ref.replace(/^\//, '') - // Only add #/components/schemas/ if it's not already there - if (!refPath.startsWith('#/components/schemas/')) { - openAPISchema.$ref = `#/components/schemas/${refPath}` - } else { - openAPISchema.$ref = refPath - } - } - - // Handle properties - if (openAPISchema.properties) { - Object.keys(openAPISchema.properties).forEach(key => { - if (openAPISchema.properties[key].$ref) { - const refPath = openAPISchema.properties[key].$ref.replace(/^\//, '') - // Only add #/components/schemas/ if it's not already there - if (!refPath.startsWith('#/components/schemas/')) { - openAPISchema.properties[key].$ref = `#/components/schemas/${refPath}` - } else { - openAPISchema.properties[key].$ref = refPath - } - } - // Remove additional properties from nested objects - if (openAPISchema.properties[key].type === 'object') { - delete openAPISchema.properties[key].additionalProperties - } - // Handle items in arrays - if (openAPISchema.properties[key].items) { - if (openAPISchema.properties[key].items.type === 'object') { - delete openAPISchema.properties[key].items.additionalProperties - // Convert key/value pairs to properties - if (openAPISchema.properties[key].items.key && openAPISchema.properties[key].items.value) { - openAPISchema.properties[key].items = { - type: 'object', - properties: { - key: openAPISchema.properties[key].items.key, - value: openAPISchema.properties[key].items.value - } - } - } - } - // Handle array item references - if (openAPISchema.properties[key].items.$ref) { - const refPath = openAPISchema.properties[key].items.$ref.replace(/^\//, '') - // Only add #/components/schemas/ if it's not already there - if (!refPath.startsWith('#/components/schemas/')) { - openAPISchema.properties[key].items = { - $ref: `#/components/schemas/${refPath}` - } - } else { - openAPISchema.properties[key].items = { - $ref: refPath - } - } - } - } - // Handle required arrays in properties - if (openAPISchema.properties[key].required && Array.isArray(openAPISchema.properties[key].required)) { - if (openAPISchema.properties[key].required.length === 0) { - delete openAPISchema.properties[key].required - } - } - // Handle intermediateCert optional property - if (key === 'intermediateCert') { - delete openAPISchema.properties[key].optional - } - // Handle microserviceDelete additionalProperties - if (key === 'additionalProperties') { - openAPISchema.properties[key] = { - type: 'object', - additionalProperties: true - } - } - // Handle serviceCreate resource required - if (key === 'resource' && openAPISchema.properties[key].required) { - if (!Array.isArray(openAPISchema.properties[key].required)) { - openAPISchema.properties[key].required = ['cpu', 'memory'] - } - } - }) - } - - // Handle array items - if (openAPISchema.items) { - if (openAPISchema.items.$ref) { - const refPath = openAPISchema.items.$ref.replace(/^\//, '') - // Only add #/components/schemas/ if it's not already there - if (!refPath.startsWith('#/components/schemas/')) { - openAPISchema.items.$ref = `#/components/schemas/${refPath}` - } else { - openAPISchema.items.$ref = refPath - } - } - // Remove additional properties from array items - if (openAPISchema.items.type === 'object') { - delete openAPISchema.items.additionalProperties - } - } - - // Handle allOf/anyOf - if (openAPISchema.allOf) { - openAPISchema.allOf = openAPISchema.allOf.map(item => { - const converted = convertJsonSchemaToOpenAPI(item) - // Remove const from routerMode in anyOf/allOf - if (converted.properties && converted.properties.routerMode) { - delete converted.properties.routerMode.const - } - return converted - }) - } - if (openAPISchema.anyOf) { - openAPISchema.anyOf = openAPISchema.anyOf.map(item => { - const converted = convertJsonSchemaToOpenAPI(item) - // Remove const from routerMode in anyOf/allOf - if (converted.properties && converted.properties.routerMode) { - delete converted.properties.routerMode.const - } - return converted - }) - } - - // Remove additionalProperties at root level - delete openAPISchema.additionalProperties - - return openAPISchema -} - -// Convert path parameters from :param to {param} format and remove /api/v3 prefix -function convertPathParameters (path) { - // Remove /api/v3 prefix if present - const pathWithoutPrefix = path.replace(/^\/api\/v3/, '') - // Convert :param to {param} - return pathWithoutPrefix.replace(/:([^/]+)/g, '{$1}') -} - -// Get response schema based on route path and method -function getResponseSchema (path, method) { - const baseResponse = JSON.parse(JSON.stringify(responseSchemas[method] || responseSchemas.get)) - // Customize response schema based on path - if (path.includes('/application')) { - if (method === 'get') { - baseResponse['200'].content['application/json'].schema = { - type: 'object', - properties: { - applications: { - type: 'array', - items: { - type: 'object', - properties: { - name: { type: 'string' }, - description: { type: 'string' }, - version: { type: 'string' }, - microservices: { - type: 'array', - items: { - type: 'object', - properties: { - name: { type: 'string' }, - config: { type: 'object' } - } - } - } - } - } - } - } - } - } - } else if (path.includes('/microservices')) { - if (method === 'get') { - baseResponse['200'].content['application/json'].schema = { - type: 'object', - properties: { - microservices: { - type: 'array', - items: { - type: 'object', - properties: { - uuid: { type: 'string' }, - name: { type: 'string' }, - config: { type: 'object' } - } - } - } - } - } - } - } - return baseResponse -} - -// Get request body schema based on route path and method -function getRequestBodySchema (path, method) { - // Handle YAML file upload endpoints - if (path.endsWith('/yaml')) { - return { - required: true, - content: { - 'multipart/form-data': { - schema: { - type: 'object', - properties: { - application: { - type: 'string', - format: 'binary' - } - } - } - } - } - } - } - - // Map routes to their corresponding schemas based on service validations - const schemaMapping = { - // Application routes - '/application': { - post: 'applicationCreate', - put: 'applicationUpdate', - patch: 'applicationPatch' - }, - // Microservice routes - '/microservices': { - post: 'microserviceCreate', - put: 'microserviceUpdate' - }, - // Iofog routes - '/iofog': { - post: 'iofogCreate', - put: 'iofogUpdate' - }, - // Agent routes - '/agent': { - post: 'agentProvision', - put: 'updateAgentConfig' - }, - // Routing routes - '/routing': { - post: 'routingCreate', - put: 'routingUpdate' - }, - // Secret routes - '/secret': { - post: 'secretCreate', - put: 'secretUpdate' - }, - // Service routes - '/service': { - post: 'serviceCreate', - put: 'serviceUpdate' - }, - // Certificate routes - '/certificate': { - post: 'certificateCreate', - put: 'caCreate' - }, - // Config map routes - '/configMap': { - post: 'configMapCreate', - put: 'configMapUpdate' - }, - // Volume mount routes - '/volumeMount': { - post: 'volumeMountCreate', - put: 'volumeMountUpdate' - }, - // Edge resource routes - '/edgeResource': { - post: 'edgeResourceCreate', - put: 'edgeResourceUpdate' - }, - // Application template routes - '/applicationTemplate': { - post: 'applicationTemplateCreate', - put: 'applicationTemplateUpdate', - patch: 'applicationTemplatePatch' - }, - // User routes - '/user': { - post: 'login', - put: 'refresh' - }, - // Catalog routes - '/catalog': { - post: 'catalogItemCreate', - put: 'catalogItemUpdate' - }, - // Registry routes - '/registry': { - post: 'registryCreate', - put: 'registryUpdate' - }, - // Tunnel routes - '/tunnel': { - post: 'tunnelCreate' - }, - // Config routes - '/config': { - put: 'configUpdate' - } - } - - // Find the matching schema for this path and method - for (const [routePath, methods] of Object.entries(schemaMapping)) { - if (path.includes(routePath) && methods[method]) { - const schemaName = methods[method] - return { - required: true, - content: { - 'application/json': { - schema: { - $ref: `#/components/schemas/${schemaName}` - } - } - } - } - } - } - - // Default JSON request body - return { - required: true, - content: { - 'application/json': { - schema: { - type: 'object' - } - } - } - } -} - -// Find the most similar tag from the tag list -function findMostSimilarTag (path) { - const pathSegments = path.split('/').filter(Boolean) - if (pathSegments.length === 0) return 'Controller' - - // Get the first meaningful segment (skip empty strings) - const firstSegment = pathSegments[0] - - // Define tag mapping for common paths - const tagMapping = { - 'application': 'Application', - 'applications': 'Application', - 'flow': 'Application', - 'flows': 'Application', - 'template': 'Application Template', - 'templates': 'Application Template', - 'catalog': 'Catalog', - 'registry': 'Registries', - 'registries': 'Registries', - 'microservice': 'Microservices', - 'microservices': 'Microservices', - 'route': 'Routing', - 'routes': 'Routing', - 'routing': 'Routing', - 'router': 'Router', - 'edgeResource': 'Edge Resource', - 'edgeResources': 'Edge Resource', - 'edge-resource': 'Edge Resource', - 'edge-resources': 'Edge Resource', - 'edge_resource': 'Edge Resource', - 'edge_resources': 'Edge Resource', - 'diagnostic': 'Diagnostics', - 'diagnostics': 'Diagnostics', - 'tunnel': 'Tunnel', - 'tunnels': 'Tunnel', - 'agent': 'Agent', - 'agents': 'Agent', - 'user': 'User', - 'users': 'User', - 'secret': 'Secrets', - 'secrets': 'Secrets', - 'certificate': 'Certificates', - 'certificates': 'Certificates', - 'service': 'Services', - 'services': 'Services', - 'volume': 'VolumeMounts', - 'volumes': 'VolumeMounts', - 'config': 'ConfigMap', - 'configs': 'ConfigMap', - 'iofog': 'ioFog' - } - - // Try to find an exact match first (case-insensitive) - const lowerFirstSegment = firstSegment.toLowerCase() - if (tagMapping[lowerFirstSegment]) { - return tagMapping[lowerFirstSegment] - } - - // Try to find a match with different case formats - const possibleFormats = [ - firstSegment, - firstSegment.toLowerCase(), - firstSegment.toUpperCase(), - firstSegment.replace(/([A-Z])/g, '-$1').toLowerCase(), - firstSegment.replace(/([A-Z])/g, '_$1').toLowerCase(), - firstSegment.charAt(0).toUpperCase() + firstSegment.slice(1) - ] - - for (const format of possibleFormats) { - if (tagMapping[format]) { - return tagMapping[format] - } - } - - // If no exact match, try to find the most similar tag - const tagNames = swaggerBase.tags.map(tag => tag.name.toLowerCase()) - let bestMatch = 'Controller' - let bestScore = 0 - - for (const tagName of tagNames) { - // Check if the path segment contains the tag name or vice versa - if (lowerFirstSegment.includes(tagName) || tagName.includes(lowerFirstSegment)) { - const score = Math.min(lowerFirstSegment.length, tagName.length) - if (score > bestScore) { - bestScore = score - bestMatch = swaggerBase.tags.find(tag => tag.name.toLowerCase() === tagName).name - } - } - } - - return bestMatch -} - -// Process route file -function processRouteFile (filePath) { - const routeFile = require(filePath) - const paths = {} - routeFile.forEach(route => { - // Skip WebSocket endpoints - if (route.method.toLowerCase() === 'ws') { - return - } - - const originalPath = route.path - const path = convertPathParameters(originalPath) - const method = route.method.toLowerCase() - if (!paths[path]) { - paths[path] = {} - } - // Extract parameters from path - const pathParams = [] - const pathRegex = /{([^}]+)}/g - let match - while ((match = pathRegex.exec(path)) !== null) { - pathParams.push({ - name: match[1], - in: 'path', - required: true, - schema: { - type: 'string' - } - }) - } - // Create path object - paths[path][method] = { - tags: [findMostSimilarTag(path)], - summary: `${method.toUpperCase()} ${originalPath}`, - security: [{ authToken: [] }], - parameters: pathParams, - responses: getResponseSchema(path, method) - } - // Add request body for POST/PUT/PATCH - if (['post', 'put', 'patch'].includes(method)) { - paths[path][method].requestBody = getRequestBodySchema(path, method) - } - }) - return paths -} - -// Process schema file -function processSchemaFile (filePath) { - const schemaFile = require(filePath) - const schemas = {} - - // Process all inner schemas first - if (schemaFile.innerSchemas) { - schemaFile.innerSchemas.forEach(schema => { - if (schema.id) { - const schemaName = schema.id.replace(/^\//, '') - schemas[schemaName] = convertJsonSchemaToOpenAPI(schema) - } - }) - } - - // Then process main schemas - if (schemaFile.mainSchemas) { - schemaFile.mainSchemas.forEach(schema => { - if (schema.id) { - const schemaName = schema.id.replace(/^\//, '') - schemas[schemaName] = convertJsonSchemaToOpenAPI(schema) - } - }) - } - - // Handle direct schema exports - Object.keys(schemaFile).forEach(key => { - if (typeof schemaFile[key] === 'object' && schemaFile[key].type) { - const schemaName = key - schemas[schemaName] = convertJsonSchemaToOpenAPI(schemaFile[key]) - } - }) - - return schemas -} - -// Main function -function generateSwagger () { - const routesDir = path.join(__dirname, '../src/routes') - const schemasDir = path.join(__dirname, '../src/schemas') - - // First, add base schemas that are commonly referenced - const baseSchemas = { - image: { - type: 'object', - properties: { - name: { type: 'string' }, - registry: { type: 'string' } - }, - required: ['name'] - }, - volumeMappings: { - type: 'object', - properties: { - hostDestination: { type: 'string' }, - containerDestination: { type: 'string' }, - accessMode: { type: 'string' }, - type: { type: 'string', enum: ['volume', 'bind'] } - }, - required: ['hostDestination', 'containerDestination', 'accessMode'] - }, - ports: { - type: 'object', - properties: { - internal: { type: 'integer' }, - external: { type: 'integer' }, - protocol: { type: 'string', enum: ['tcp', 'udp'] } - }, - required: ['internal', 'external'] - }, - extraHosts: { - type: 'object', - properties: { - name: { type: 'string' }, - address: { type: 'string' } - }, - required: ['name', 'address'] - }, - env: { - type: 'object', - properties: { - key: { type: 'string' }, - value: { type: 'string' }, - valueFromSecret: { type: 'string' }, - valueFromConfigMap: { type: 'string' } - }, - required: ['key'], - oneOf: [ - { required: ['value'] }, - { required: ['valueFromSecret'] }, - { required: ['valueFromConfigMap'] } - ] - } - } - - // Initialize schemas with base schemas - const allSchemas = { ...baseSchemas } - - // Process all schema files - fs.readdirSync(schemasDir) - .filter(file => file.endsWith('.js')) - .forEach(file => { - const schemaDefinitions = processSchemaFile(path.join(schemasDir, file)) - Object.assign(allSchemas, schemaDefinitions) - }) - - // Add all schemas to the OpenAPI document - swaggerBase.components.schemas = allSchemas - - // Process all route files - fs.readdirSync(routesDir) - .filter(file => file.endsWith('.js')) - .forEach(file => { - const routePaths = processRouteFile(path.join(routesDir, file)) - Object.assign(swaggerBase.paths, routePaths) - }) - - // Write to YAML file - const yamlStr = yaml.dump(swaggerBase, { - noRefs: true, // Disable YAML anchors and references - lineWidth: -1, // Disable line wrapping - noCompatMode: true // Use modern YAML features - }) - fs.writeFileSync(path.join(__dirname, '../docs/swagger-test.yaml'), yamlStr) - console.log('Swagger YAML generated successfully!') -} - -generateSwagger() diff --git a/src/cli/registry.js b/src/cli/registry.js index 046bdbc1..1efee349 100644 --- a/src/cli/registry.js +++ b/src/cli/registry.js @@ -64,20 +64,6 @@ class Registry extends BaseCLIHandler { description: 'Password', group: [constants.CMD_ADD, constants.CMD_UPDATE] }, - { - name: 'requires-certificate', - alias: 'c', - type: Boolean, - description: 'Requires certificate', - group: [constants.CMD_ADD, constants.CMD_UPDATE] - }, - { - name: 'certificate', - alias: 'C', - type: String, - description: 'Certificate', - group: [constants.CMD_ADD, constants.CMD_UPDATE] - }, { name: 'email', alias: 'e', @@ -183,9 +169,7 @@ function _createRegistryObject (cliData) { username: cliData.username, password: cliData.password, isPublic: AppHelper.validateBooleanCliOptions(cliData.public, cliData.private), - email: cliData.email, - requiresCert: cliData.requiresCertificate, - certificate: cliData.certificate + email: cliData.email } } diff --git a/src/config/controller.yaml b/src/config/controller.yaml index 8f1b8756..cd93ad6d 100644 --- a/src/config/controller.yaml +++ b/src/config/controller.yaml @@ -50,6 +50,7 @@ settings: # defaultJobInterval: 120 # Default job interval in seconds fogStatusUpdateInterval: 30 # Fog status update interval in seconds fogStatusUpdateTolerance: 3 # Fog status update tolerance + fogExpiredTokenCleanupInterval: 300 # Fog expired token cleanup interval in seconds # Database Configuration database: diff --git a/src/config/env-mapping.js b/src/config/env-mapping.js index 18f1baea..d4365fb5 100644 --- a/src/config/env-mapping.js +++ b/src/config/env-mapping.js @@ -38,6 +38,7 @@ module.exports = { // Settings Configuration 'FOG_STATUS_UPDATE_INTERVAL': 'settings.fogStatusUpdateInterval', 'FOG_STATUS_UPDATE_TOLERANCE': 'settings.fogStatusUpdateTolerance', + 'FOG_EXPIRED_TOKEN_CLEANUP_INTERVAL': 'settings.fogExpiredTokenCleanupInterval', // Database Configuration 'DB_PROVIDER': 'database.provider', diff --git a/src/data/migrations/mysql/db_migration_mysql_v1.0.4.sql b/src/data/migrations/mysql/db_migration_mysql_v1.0.4.sql index 1be5d278..f0f0c931 100644 --- a/src/data/migrations/mysql/db_migration_mysql_v1.0.4.sql +++ b/src/data/migrations/mysql/db_migration_mysql_v1.0.4.sql @@ -14,9 +14,6 @@ CREATE TABLE IF NOT EXISTS Registries ( id INT AUTO_INCREMENT PRIMARY KEY, url VARCHAR(255), is_public BOOLEAN, - secure BOOLEAN, - certificate TEXT, - requires_cert BOOLEAN, user_name TEXT, password TEXT, user_email TEXT diff --git a/src/data/migrations/postgres/db_migration_pg_v1.0.4.sql b/src/data/migrations/postgres/db_migration_pg_v1.0.4.sql index 3181cc00..3ffbb188 100644 --- a/src/data/migrations/postgres/db_migration_pg_v1.0.4.sql +++ b/src/data/migrations/postgres/db_migration_pg_v1.0.4.sql @@ -12,9 +12,6 @@ CREATE TABLE IF NOT EXISTS "Registries" ( id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, url VARCHAR(255), is_public BOOLEAN, - secure BOOLEAN, - certificate TEXT, - requires_cert BOOLEAN, user_name TEXT, password TEXT, user_email TEXT diff --git a/src/data/migrations/sqlite/db_migration_sqlite_v1.0.4.sql b/src/data/migrations/sqlite/db_migration_sqlite_v1.0.4.sql index 13d21c08..83b6d35a 100644 --- a/src/data/migrations/sqlite/db_migration_sqlite_v1.0.4.sql +++ b/src/data/migrations/sqlite/db_migration_sqlite_v1.0.4.sql @@ -12,9 +12,6 @@ CREATE TABLE IF NOT EXISTS Registries ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, url VARCHAR(255), is_public BOOLEAN, - secure BOOLEAN, - certificate TEXT, - requires_cert BOOLEAN, user_name TEXT, password TEXT, user_email TEXT diff --git a/src/data/models/registry.js b/src/data/models/registry.js index 15295fba..fe169e51 100644 --- a/src/data/models/registry.js +++ b/src/data/models/registry.js @@ -16,18 +16,6 @@ module.exports = (sequelize, DataTypes) => { type: DataTypes.BOOLEAN, field: 'is_public' }, - isSecure: { - type: DataTypes.BOOLEAN, - field: 'secure' - }, - certificate: { - type: DataTypes.TEXT, - field: 'certificate' - }, - requiresCert: { - type: DataTypes.BOOLEAN, - field: 'requires_cert' - }, username: { type: DataTypes.TEXT, field: 'user_name' diff --git a/src/data/seeders/mysql/db_seeder_mysql_v1.0.2.sql b/src/data/seeders/mysql/db_seeder_mysql_v1.0.2.sql index 5675a835..d73d393e 100644 --- a/src/data/seeders/mysql/db_seeder_mysql_v1.0.2.sql +++ b/src/data/seeders/mysql/db_seeder_mysql_v1.0.2.sql @@ -1,9 +1,9 @@ START TRANSACTION; -INSERT INTO `Registries` (url, is_public, secure, certificate, requires_cert, user_name, password, user_email) +INSERT INTO `Registries` (url, is_public, user_name, password, user_email) VALUES - ('registry.hub.docker.com', true, true, '', false, '', '', ''), - ('from_cache', true, true, '', false, '', '', ''); + ('registry.hub.docker.com', true, '', '', ''), + ('from_cache', true, '', '', ''); INSERT INTO `CatalogItems` (name, description, category, publisher, disk_required, ram_required, picture, config_example, is_public, registry_id) VALUES diff --git a/src/data/seeders/postgres/db_seeder_pg_v1.0.2.sql b/src/data/seeders/postgres/db_seeder_pg_v1.0.2.sql index 37a361f4..ca8d0821 100644 --- a/src/data/seeders/postgres/db_seeder_pg_v1.0.2.sql +++ b/src/data/seeders/postgres/db_seeder_pg_v1.0.2.sql @@ -1,9 +1,9 @@ START TRANSACTION; -INSERT INTO "Registries" (url, is_public, secure, certificate, requires_cert, user_name, password, user_email) +INSERT INTO "Registries" (url, is_public, user_name, password, user_email) VALUES - ('registry.hub.docker.com', true, true, '', false, '', '', ''), - ('from_cache', true, true, '', false, '', '', ''); + ('registry.hub.docker.com', true, '', '', ''), + ('from_cache', true, '', '', ''); INSERT INTO "CatalogItems" (name, description, category, publisher, disk_required, ram_required, picture, config_example, is_public, registry_id) VALUES diff --git a/src/data/seeders/sqlite/db_seeder_sqlite_v1.0.2.sql b/src/data/seeders/sqlite/db_seeder_sqlite_v1.0.2.sql index d3e6e162..80d4ee2c 100644 --- a/src/data/seeders/sqlite/db_seeder_sqlite_v1.0.2.sql +++ b/src/data/seeders/sqlite/db_seeder_sqlite_v1.0.2.sql @@ -1,7 +1,7 @@ -INSERT INTO `Registries` (url, is_public, secure, certificate, requires_cert, user_name, password, user_email) +INSERT INTO `Registries` (url, is_public, user_name, password, user_email) VALUES - ('registry.hub.docker.com', true, true, '', false, '', '', ''), - ('from_cache', true, true, '', false, '', '', ''); + ('registry.hub.docker.com', true, '', '', ''), + ('from_cache', true, '', '', ''); INSERT INTO `CatalogItems` (name, description, category, publisher, disk_required, ram_required, picture, config_example, is_public, registry_id) VALUES diff --git a/src/jobs/fog-status-job.js b/src/jobs/fog-status-job.js index 6f96ff7a..2d1f167c 100644 --- a/src/jobs/fog-status-job.js +++ b/src/jobs/fog-status-job.js @@ -21,6 +21,7 @@ const MicroserviceService = require('../services/microservices-service') const { microserviceState, microserviceExecState } = require('../enums/microservice-state') const FogStates = require('../enums/fog-state') const Config = require('../config') +const logger = require('../logger') const scheduleTime = Config.get('settings.fogStatusUpdateInterval') * 1000 @@ -29,7 +30,7 @@ async function run () { const _updateFogsConnectionStatus = TransactionDecorator.generateTransaction(updateFogsConnectionStatus) await _updateFogsConnectionStatus() } catch (error) { - console.error(error) + logger.error('Error during fog status update:', error) } finally { setTimeout(run, scheduleTime) } @@ -62,12 +63,36 @@ async function _updateFogStatus (transaction) { async function _updateMicroserviceStatus (unknownFogUuids, transaction) { const microservices = await MicroserviceManager.findAllWithStatuses({ iofogUuid: unknownFogUuids }, transaction) + + // Filter out inactive microservices that are already STOPPED - they should not be updated to UNKNOWN const microserviceStatusIds = microservices - .filter((microservice) => microservice.microserviceStatus) + .filter((microservice) => { + // Skip if no microservice status + if (!microservice.microserviceStatus) { + return false + } + // Skip if microservice is inactive and already STOPPED + if (!microservice.isActivated && microservice.microserviceStatus.status === microserviceState.STOPPED) { + return false + } + return true + }) .map((microservice) => microservice.microserviceStatus.id) + const microserviceExecStatusIds = microservices - .filter((microservice) => microservice.microserviceExecStatus) + .filter((microservice) => { + // Skip if no exec status + if (!microservice.microserviceExecStatus) { + return false + } + // Skip if microservice is inactive and already STOPPED + if (!microservice.isActivated && microservice.microserviceStatus && microservice.microserviceStatus.status === microserviceState.STOPPED) { + return false + } + return true + }) .map((microservice) => microservice.microserviceExecStatus.id) + await MicroserviceStatusManager.update({ id: microserviceStatusIds }, { status: microserviceState.UNKNOWN }, transaction) await MicroserviceExecStatusManager.update({ id: microserviceExecStatusIds }, { execSesssionId: '', status: microserviceExecState.INACTIVE }, transaction) return microservices diff --git a/src/jobs/fog-token-cleanup-job.js b/src/jobs/fog-token-cleanup-job.js new file mode 100644 index 00000000..1cce9459 --- /dev/null +++ b/src/jobs/fog-token-cleanup-job.js @@ -0,0 +1,42 @@ +/* + * ******************************************************************************* + * * Copyright (c) 2023 Datasance Teknoloji A.S. + * * + * * This program and the accompanying materials are made available under the + * * terms of the Eclipse Public License v. 2.0 which is available at + * * http://www.eclipse.org/legal/epl-2.0 + * * + * * SPDX-License-Identifier: EPL-2.0 + * ******************************************************************************* + * + */ + +const FogUsedTokenManager = require('../data/managers/fog-used-token-manager') +const Config = require('../config') +const logger = require('../logger') + +const scheduleTime = Config.get('settings.fogExpiredTokenCleanupInterval') * 1000 + +async function run () { + try { + await cleanupExpiredTokens() + } catch (error) { + logger.error('Error during JTI cleanup:', error) + } finally { + setTimeout(run, scheduleTime) + } +} + +async function cleanupExpiredTokens () { + try { + logger.debug('Starting cleanup of expired JTIs') + const count = await FogUsedTokenManager.cleanupExpiredJtis() + logger.debug(`Cleaned up ${count} expired JTIs`) + } catch (error) { + logger.error('Error during JTI cleanup:', error) + } +} + +module.exports = { + run +} diff --git a/src/jobs/stopped-app-status-job.js b/src/jobs/stopped-app-status-job.js index 05a5403d..ea07f2bd 100644 --- a/src/jobs/stopped-app-status-job.js +++ b/src/jobs/stopped-app-status-job.js @@ -20,6 +20,7 @@ const { microserviceState, microserviceExecState } = require('../enums/microserv const Config = require('../config') const ApplicationManager = require('../data/managers/application-manager') +const logger = require('../logger') const scheduleTime = Config.get('settings.fogStatusUpdateInterval') * 1000 @@ -33,7 +34,7 @@ async function run () { // Handle individually deactivated microservices await _updateStoppedMicroserviceStatus() } catch (error) { - console.error(error) + logger.error('Error during stopped application status update:', error) } finally { setTimeout(run, scheduleTime) } diff --git a/src/schemas/iofog.js b/src/schemas/iofog.js index eaf608bc..c2246808 100644 --- a/src/schemas/iofog.js +++ b/src/schemas/iofog.js @@ -245,13 +245,6 @@ const defaultRouterCreate = { 'messagingPort': { 'type': 'integer', 'minimum': 1, 'maximum': 65535 }, 'interRouterPort': { 'type': 'integer', 'minimum': 1, 'maximum': 65535 }, 'edgeRouterPort': { 'type': 'integer', 'minimum': 1, 'maximum': 65535 }, - 'requireSsl': { 'type': 'string' }, - 'sslProfile': { 'type': 'string' }, - 'saslMechanisms': { 'type': 'string' }, - 'authenticatePeer': { 'type': 'string' }, - 'caCert': { 'type': 'string' }, - 'tlsCert': { 'type': 'string' }, - 'tlsKey': { 'type': 'string' }, 'host': { 'type': 'string' } }, 'required': ['host'], diff --git a/src/schemas/registry.js b/src/schemas/registry.js index 695c936f..4e31e986 100644 --- a/src/schemas/registry.js +++ b/src/schemas/registry.js @@ -23,9 +23,7 @@ const registryCreate = { 'type': 'string', 'pattern': '^(([^<>()\\[\\]\\\\.,;:\\s@"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@"]+)*)|(".+"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}' + '\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$' - }, - 'requiresCert': { 'type': 'boolean' }, - 'certificate': { 'type': 'string' } + } }, 'required': ['url', 'isPublic', 'username', 'password', 'email'], 'additionalProperties': true @@ -53,9 +51,7 @@ const registryUpdate = { 'type': 'string', 'pattern': '^(([^<>()\\[\\]\\\\.,;:\\s@"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@"]+)*)|(".+"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}' + '\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$' - }, - 'requiresCert': { 'type': 'boolean' }, - 'certificate': { 'type': 'string' } + } }, 'additionalProperties': true } diff --git a/src/server.js b/src/server.js index 25a7e387..5cae2fff 100755 --- a/src/server.js +++ b/src/server.js @@ -17,7 +17,6 @@ initialize().then(() => { const config = require('./config') const logger = require('./logger') const db = require('./data/models') - const CleanupService = require('./services/cleanup-service') const WebSocketServer = require('./websocket/server') const bodyParser = require('body-parser') @@ -269,9 +268,6 @@ initialize().then(() => { fs.writeFileSync(ecnViewerControllerConfigFilePath, ecnViewerConfigScript) } - // Initialize cleanup service - CleanupService.start() - initState() .then(() => { if (hasFileBasedSSL) { diff --git a/src/services/agent-service.js b/src/services/agent-service.js index 5e2208dd..4d771081 100644 --- a/src/services/agent-service.js +++ b/src/services/agent-service.js @@ -15,9 +15,9 @@ const config = require('../config') const path = require('path') const fs = require('fs') const formidable = require('formidable') -const Sequelize = require('sequelize') +// const Sequelize = require('sequelize') const moment = require('moment') -const Op = Sequelize.Op +// const Op = Sequelize.Op const logger = require('../logger') const TransactionDecorator = require('../decorators/transaction-decorator') @@ -493,14 +493,7 @@ const getAgentMicroservice = async function (microserviceUuid, fog, transaction) } const getAgentRegistries = async function (fog, transaction) { - const registries = await RegistryManager.findAll({ - [Op.or]: - [ - { - isPublic: true - } - ] - }, transaction) + const registries = await RegistryManager.findAll({}, transaction) return { registries: registries } diff --git a/src/services/cleanup-service.js b/src/services/cleanup-service.js deleted file mode 100644 index 9c67201d..00000000 --- a/src/services/cleanup-service.js +++ /dev/null @@ -1,34 +0,0 @@ -/* - * ******************************************************************************* - * * Copyright (c) 2023 Datasance Teknoloji A.S. - * * - * * This program and the accompanying materials are made available under the - * * terms of the Eclipse Public License v. 2.0 which is available at - * * http://www.eclipse.org/legal/epl-2.0 - * * - * * SPDX-License-Identifier: EPL-2.0 - * ******************************************************************************* - * - */ - -const schedule = require('node-schedule') -const FogUsedTokenManager = require('../data/managers/fog-used-token-manager') -const logger = require('../logger') - -class CleanupService { - start () { - // Run every 5 minutes to ensure we catch all expired tokens - // (since tokens are valid for 10 minutes) - schedule.scheduleJob('*/5 * * * *', async () => { - try { - logger.debug('Starting cleanup of expired JTIs') - const count = await FogUsedTokenManager.cleanupExpiredJtis() - logger.debug(`Cleaned up ${count} expired JTIs`) - } catch (error) { - logger.error('Error during JTI cleanup:', error) - } - }) - } -} - -module.exports = new CleanupService() diff --git a/src/services/microservice-ports/default.js b/src/services/microservice-ports/default.js deleted file mode 100644 index 956186be..00000000 --- a/src/services/microservice-ports/default.js +++ /dev/null @@ -1,565 +0,0 @@ -/* only "[a-zA-Z0-9][a-zA-Z0-9_.-]" are allowed - * ******************************************************************************* - * * Copyright (c) 2023 Datasance Teknoloji A.S. - * * - * * This program and the accompanying materials are made available under the - * * terms of the Eclipse Public License v. 2.0 which is available at - * * http://www.eclipse.org/legal/epl-2.0 - * * - * * SPDX-License-Identifier: EPL-2.0 - * ******************************************************************************* - * - */ - -const MicroservicePortManager = require('../../data/managers/microservice-port-manager') -const MicroserviceManager = require('../../data/managers/microservice-manager') -const MicroserviceStatusManager = require('../../data/managers/microservice-status-manager') -const ApplicationManager = require('../../data/managers/application-manager') -const ConfigManager = require('../../data/managers/config-manager') -const ChangeTrackingService = require('../change-tracking-service') -const AppHelper = require('../../helpers/app-helper') -const Errors = require('../../helpers/errors') -const ErrorMessages = require('../../helpers/error-messages') -const CatalogService = require('../../services/catalog-service') -const Op = require('sequelize').Op -const FogManager = require('../../data/managers/iofog-manager') -const RouterManager = require('../../data/managers/router-manager') -const MicroservicePublicPortManager = require('../../data/managers/microservice-public-port-manager') -const MicroserviceExtraHostManager = require('../../data/managers/microservice-extra-host-manager') -const controllerConfig = require('../../config') - -const { MICROSERVICE_DEFAULT_LOG_SIZE, DEFAULT_ROUTER_NAME, DEFAULT_PROXY_HOST, RESERVED_PORTS } = require('../../helpers/constants') - -const lget = require('lodash/get') - -async function _checkForDuplicatePorts (agent, localPort, transaction) { - if (RESERVED_PORTS.find(port => port === localPort)) { - throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.PORT_RESERVED, localPort)) - } - - const microservices = await agent.getMicroservice() - for (const microservice of microservices) { - const ports = await microservice.getPorts() - if (ports.find(port => port.portExternal === localPort)) { - throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.PORT_NOT_AVAILABLE, localPort)) - } - } - - const publicPorts = await MicroservicePublicPortManager.findAll({ hostId: agent.uuid }, transaction) - if (publicPorts.find(port => port.publicPort === localPort)) { - throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.PORT_NOT_AVAILABLE, localPort)) - } -} - -function _createDefaultPublicPortRange () { - const defaultPortRangeStr = process.env.PUBLIC_PORTS_RANGE || controllerConfig.get('publicPorts.range') - const [startStr, endStr] = defaultPortRangeStr.split('-') - let start = parseInt(startStr) - let end = parseInt(endStr) - if (!start || Number.isNaN(start)) { start = 6001 } - if (!end || Number.isNaN(end) || end < start) { - end = start + 1998 - } - const size = end - start - const availablePorts = new Array(size) - for (let i = 0; i < size; ++i) { - availablePorts[i] = start + i - } - - return availablePorts -} - -// Validate port and populate mapping.publicHost, mapping.publicPort, mapping.localAgent -async function validatePortMapping (agent, mapping, availablePublicPortsByHost, transaction) { - await _checkForDuplicatePorts(agent, mapping.external, transaction) - - if (mapping.public) { - const isTcp = mapping.public.protocol ? mapping.public.protocol.toLowerCase() === 'tcp' : false - // Validate link protocol - for (const scheme of mapping.public.schemes) { - // !isTcp === HTTP link protocol will be used - if (!scheme.startsWith('http') && !isTcp) { - throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.WRONG_PUBLIC_LINK_PROTOCOL, mapping.internal, scheme, 'http')) - } - } - let host - if (mapping.public.router && mapping.public.router.host && mapping.public.router.host !== DEFAULT_ROUTER_NAME) { - host = await FogManager.findOne({ uuid: mapping.public.router.host }, transaction) - if (!host) { - throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.INVALID_ROUTER_HOST, mapping.public.host)) - } - } else { - host = await FogManager.findOne({ isSystem: true }, transaction) - if (!host) { - const defaultRouter = await RouterManager.findOne({ isDefault: true }, transaction) - if (!defaultRouter) { - throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.INVALID_ROUTER_HOST, DEFAULT_ROUTER_NAME)) - } - } - } - - // We have found a host - if (host) { - // Port is defined by user - if (mapping.public.router && mapping.public.router.port) { - await _checkForDuplicatePorts(host, mapping.public.router.port, transaction) - mapping.publicPort = mapping.public.router.port - } else { - // Assign next available public port - const currentPublicPorts = (await MicroservicePublicPortManager.findAll({ hostId: host.uuid }, transaction)).map(p => p.publicPort) - // Default range 6001 -> 7999 - availablePublicPortsByHost[host.uuid] = availablePublicPortsByHost[host.uuid] || _createDefaultPublicPortRange() - availablePublicPortsByHost[host.uuid] = availablePublicPortsByHost[host.uuid].filter(port => !currentPublicPorts.includes(port)) - if (availablePublicPortsByHost[host.uuid].length === 0) { - throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.NO_AVAILABLE_PUBLIC_PORT, host.isSystem ? DEFAULT_ROUTER_NAME : host.name)) - } - mapping.publicPort = availablePublicPortsByHost[host.uuid].shift() - } - } else { - const hostId = 'default-router' - // We don't have a host. A.k.a, there is no System agent, but there is a default router. A.k.a: We're running on K8s - // Port is defined by user - if (mapping.public.router && mapping.public.router.port) { - // Alls ports are shared by the same proxy msvc - const publicPorts = await MicroservicePublicPortManager.findAll({ hostId: null }, transaction) - if (publicPorts.find(port => port.publicPort === mapping.public.router.port)) { - throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.PORT_NOT_AVAILABLE, mapping.public.router.port)) - } - mapping.publicPort = mapping.public.router.port - } else { - // Port - // Alls ports are shared by the same proxy msvc - const currentPublicPorts = (await MicroservicePublicPortManager.findAll({ hostId: null }, transaction)).map(p => p.publicPort) - availablePublicPortsByHost[hostId] = availablePublicPortsByHost[hostId] || _createDefaultPublicPortRange() - availablePublicPortsByHost[hostId] = availablePublicPortsByHost[hostId].filter(port => !currentPublicPorts.includes(port)) - if (availablePublicPortsByHost[hostId].length === 0) { - throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.NO_AVAILABLE_PUBLIC_PORT, host.isSystem ? DEFAULT_ROUTER_NAME : host.name)) - } - mapping.publicPort = availablePublicPortsByHost[hostId].shift() - } - } - - mapping.publicHost = host - mapping.localAgent = agent - } -} - -async function validatePortMappings (microserviceData, transaction) { - if (!microserviceData.ports || microserviceData.ports.length === 0) { - return - } - - const localAgent = await FogManager.findOne({ uuid: microserviceData.iofogUuid }, transaction) - if (!localAgent) { - throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.INVALID_IOFOG_UUID, microserviceData.iofogUuid)) - } - - // Will be filled by validatePortMapping - // In memory store to keep track of newly allocated ports - const availablePublicPortsByHost = {} - for (const mapping of microserviceData.ports) { - await validatePortMapping(localAgent, mapping, availablePublicPortsByHost, transaction) - } -} - -async function validatePublicPortAppHostTemplate (extraHost, templateArgs, msvc, transaction) { - if (templateArgs.length !== 5) { - throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.INVALID_HOST_TEMPLATE, templateArgs.join('.'))) - } - - const ports = await MicroservicePortManager.findAllPublicPorts({ microserviceUuid: msvc.uuid }, transaction) - - for (const port of ports) { - if (port.publicPort.publicPort === +(templateArgs[4])) { - if (port.publicPort.hostId) { - const fog = await FogManager.findOne({ uuid: port.publicPort.hostId }, transaction) - extraHost.publicPort = port.publicPort.publicPort - extraHost.targetFogUuid = fog.uuid - extraHost.value = fog.host || fog.ipAddress - } else { - extraHost.publicPort = port.publicPort.publicPort - extraHost.targetFogUuid = null - extraHost.value = lget( - await ConfigManager.findOne({ key: DEFAULT_PROXY_HOST }, transaction), - 'value', - 'undefined-proxy-host' - ) - } - return extraHost - } - } - - throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.NOT_FOUND_HOST_TEMPLATE, templateArgs[4])) -} - -async function movePublicPortsToNewFog (updatedMicroservice, transaction) { - const portMappings = await updatedMicroservice.getPorts() - for (const portMapping of portMappings) { - if (!portMapping.isPublic) { - continue - } - - const publicPort = await portMapping.getPublicPort() - const localMapping = `amqp:${publicPort.queueName}=>${publicPort.protocol}:${portMapping.portExternal}` - const localProxy = await MicroserviceManager.findOne({ uuid: publicPort.localProxyId }, transaction) - await _updateOrDeleteProxyMicroservice(localProxy.uuid, localMapping, transaction) - - const destAgent = await FogManager.findOne({ uuid: updatedMicroservice.iofogUuid }, transaction) - const destAgentsRouter = destAgent.routerId ? await RouterManager.findOne({ id: destAgent.routerId }, transaction) : await RouterManager.findOne({ iofogUuid: destAgent.uuid }, transaction) - const networkRouter = { - host: 'localhost', - port: destAgentsRouter.messagingPort - } - const newProxy = await _createOrUpdateProxyMicroservice(localMapping, networkRouter, updatedMicroservice.iofogUuid, localProxy.catalogItemId, transaction) - publicPort.localProxyId = newProxy.uuid - await MicroservicePublicPortManager.updateOrCreate({ id: publicPort.id }, publicPort.toJSON(), transaction) - } -} - -async function createPortMapping (microservice, portMappingData, transaction) { - if (!microservice.iofogUuid) { - throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.REQUIRED_FOG_NODE)) - } - - const msPorts = await MicroservicePortManager.findOne({ - microserviceUuid: microservice.uuid, - [Op.or]: [] - }, transaction) - if (msPorts) { - throw new Errors.ValidationError(ErrorMessages.PORT_MAPPING_ALREADY_EXISTS) - } - - portMappingData.protocol = portMappingData.protocol || '' - - if (portMappingData.public) { - return _createPublicPortMapping(microservice, portMappingData, transaction) - } else { - return _createSimplePortMapping(microservice, portMappingData, transaction) - } -} - -async function _createOrUpdateProxyMicroservice (mapping, networkRouter, hostUuid, proxyCatalogId, transaction) { - const existingProxy = await MicroserviceManager.findOne({ catalogItemId: proxyCatalogId, iofogUuid: hostUuid }, transaction) - if (existingProxy) { - const config = JSON.parse(existingProxy.config || '{}') - config.mappings = (config.mappings || []).concat(mapping) - existingProxy.config = JSON.stringify(config) - await MicroserviceManager.updateIfChanged({ uuid: existingProxy.uuid }, { config: JSON.stringify(config) }, transaction) - await ChangeTrackingService.update(hostUuid, ChangeTrackingService.events.microserviceConfig, transaction) - return existingProxy - } - - const proxyMicroserviceData = { - uuid: AppHelper.generateRandomString(32), - name: `proxy-${hostUuid.toLowerCase()}`, - config: JSON.stringify({ - mappings: [mapping], - networkRouter - }), - catalogItemId: proxyCatalogId, - iofogUuid: hostUuid, - rootHostAccess: true, - registryId: 1, - logSize: MICROSERVICE_DEFAULT_LOG_SIZE, - configLastUpdated: Date.now() - } - const application = await ApplicationManager.findOne({ name: `system-${hostUuid.toLowerCase()}` }, transaction) - proxyMicroserviceData.applicationId = application.id - const res = await MicroserviceManager.create(proxyMicroserviceData, transaction) - await MicroserviceStatusManager.create({ microserviceUuid: proxyMicroserviceData.uuid }, transaction) - await ChangeTrackingService.update(hostUuid, ChangeTrackingService.events.microserviceCommon, transaction) - return res -} - -async function _createPublicPortMapping (microservice, portMappingData, transaction) { - const isTcp = portMappingData.public.protocol ? portMappingData.public.protocol.toLowerCase() === 'tcp' : false - const isUdp = portMappingData.protocol.toLowerCase() === 'udp' - const localAgent = portMappingData.localAgent // This is populated by validating the ports - const localAgentsRouter = localAgent.routerId ? await RouterManager.findOne({ id: localAgent.routerId }, transaction) : await RouterManager.findOne({ iofogUuid: localAgent.uuid }, transaction) - const localNetworkRouter = { - // host: localAgentsRouter.host, - host: 'localhost', - port: localAgentsRouter.messagingPort - } - - // create proxy microservices - const queueName = AppHelper.generateRandomString(32) - const proxyCatalog = await CatalogService.getProxyCatalogItem(transaction) - const localMapping = `amqp:${queueName}=>${isTcp ? 'tcp' : 'http'}:${portMappingData.external}` - const remoteMapping = `${isTcp ? 'tcp' : 'http'}:${portMappingData.publicPort}=>amqp:${queueName}` - - const localProxy = !portMappingData.public.disabled - ? await _createOrUpdateProxyMicroservice( - localMapping, - localNetworkRouter, - microservice.iofogUuid, - proxyCatalog.id, - transaction) - : null - - let remoteProxy - if (portMappingData.publicHost) { - const hostRouter = portMappingData.publicHost.routerId ? await RouterManager.findOne({ id: portMappingData.publicHost.routerId }, transaction) : await RouterManager.findOne({ iofogUuid: portMappingData.publicHost.uuid }, transaction) - const remoteNetworkRouter = { - // host: hostRouter.host, - host: 'localhost', - port: hostRouter.messagingPort - } - - remoteProxy = !portMappingData.public.disabled - ? await _createOrUpdateProxyMicroservice( - remoteMapping, - remoteNetworkRouter, - portMappingData.publicHost.uuid, - proxyCatalog.id, - transaction) - : null - } - - const mappingData = { - isPublic: true, - isProxy: false, - portInternal: portMappingData.internal, - portExternal: portMappingData.external, - isUdp, - microserviceUuid: microservice.uuid - } - const port = await MicroservicePortManager.create(mappingData, transaction) - const schemes = portMappingData.public && portMappingData.public.schemes - - const publicPort = { - portId: port.id, - hostId: portMappingData.publicHost ? portMappingData.publicHost.uuid : null, - localProxyId: localProxy.uuid, - remoteProxyId: portMappingData.publicHost ? remoteProxy.uuid : null, - publicPort: portMappingData.publicPort, - queueName, - schemes: JSON.stringify(schemes), - isTcp - } - await MicroservicePublicPortManager.create(publicPort, transaction) - - // Look for related extraHosts to update - const relatedExtraHosts = await MicroserviceExtraHostManager.findAll({ microserviceUuid: microservice.uuid, publicPort: publicPort.publicPort }, transaction) - for (const extraHost of relatedExtraHosts) { - extraHost.targetFogUuid = publicPort.hostId - extraHost.value = portMappingData.publicHost.host - await extraHost.save() - await MicroserviceExtraHostManager.updateOriginMicroserviceChangeTracking(extraHost, transaction) - } -} - -async function _deletePortMapping (microservice, portMapping, transaction) { - if (portMapping.isPublic) { - await _deletePublicPortMapping(microservice, portMapping, transaction) - } else { - await _deleteSimplePortMapping(microservice, portMapping, transaction) - } -} - -async function _updateOrDeleteProxyMicroservice (proxyId, proxyMapping, transaction) { - const proxy = await MicroserviceManager.findOne({ uuid: proxyId }, transaction) - if (!proxy) { - return - } - - const config = JSON.parse(proxy.config || '{}') - config.mappings = (config.mappings || []).filter(mapping => mapping !== proxyMapping) - if (config.mappings.length === 0) { - await MicroserviceManager.delete({ uuid: proxy.uuid }, transaction) - await ChangeTrackingService.update(proxy.iofogUuid, ChangeTrackingService.events.microserviceConfig, transaction) - } else { - await MicroserviceManager.updateIfChanged({ uuid: proxy.uuid }, { config: JSON.stringify(config) }, transaction) - await ChangeTrackingService.update(proxy.iofogUuid, ChangeTrackingService.events.microserviceCommon, transaction) - } -} - -async function _deletePublicPortMapping (microservice, portMapping, transaction) { - const publicPort = await portMapping.getPublicPort() - if (publicPort) { - const protocol = publicPort.isTcp ? 'tcp' : 'http' - const localMapping = `amqp:${publicPort.queueName}=>${protocol}:${portMapping.portExternal}` - const remoteMapping = `${protocol}:${publicPort.publicPort}=>amqp:${publicPort.queueName}` - - await _updateOrDeleteProxyMicroservice(publicPort.localProxyId, localMapping, transaction) - await _updateOrDeleteProxyMicroservice(publicPort.remoteProxyId, remoteMapping, transaction) - } - - await MicroservicePortManager.delete({ id: portMapping.id }, transaction) -} - -async function _createSimplePortMapping (microservice, portMappingData, transaction) { - // create port mapping - const mappingData = { - isPublic: false, - isProxy: false, - portInternal: portMappingData.internal, - portExternal: portMappingData.external, - isUdp: portMappingData.protocol.toLowerCase() === 'udp', - microserviceUuid: microservice.uuid - } - - await MicroservicePortManager.create(mappingData, transaction) - await switchOnUpdateFlagsForMicroservicesForPortMapping(microservice, false, transaction) -} - -async function _deleteSimplePortMapping (microservice, msPorts, transaction) { - await MicroservicePortManager.delete({ id: msPorts.id }, transaction) - - const updateRebuildMs = { - rebuild: true - } - await MicroserviceManager.update({ uuid: microservice.uuid }, updateRebuildMs, transaction) - await ChangeTrackingService.update(microservice.iofogUuid, ChangeTrackingService.events.microserviceCommon, transaction) -} - -async function _buildPortsList (portsPairs, transaction) { - const res = [] - for (const ports of portsPairs) { - const portMappingResponseData = { - internal: ports.portInternal, - external: ports.portExternal, - protocol: ports.isUdp ? 'udp' : 'tcp' - } - await buildPublicPortMapping(ports, portMappingResponseData, transaction) - res.push(portMappingResponseData) - } - return res -} - -function _buildLink (protocol, host, port) { - return `${protocol || 'http'}://${host}:${port}` -} - -async function buildPublicPortMapping (pm, mapping, transaction) { - if (!pm.isPublic) { - return - } - - const publicPortMapping = await pm.getPublicPort() - if (!publicPortMapping) { - return - } - - const port = publicPortMapping.publicPort - const hostRouter = publicPortMapping.hostId ? await RouterManager.findOne({ iofogUuid: publicPortMapping.hostId }, transaction) : { host: lget(await ConfigManager.findOne({ key: DEFAULT_PROXY_HOST }, transaction), 'value', 'undefined-proxy-host') } - const hostFog = publicPortMapping.hostId ? await FogManager.findOne({ uuid: publicPortMapping.hostId }, transaction) : { uuid: DEFAULT_ROUTER_NAME } - const schemes = JSON.parse(publicPortMapping.schemes) - mapping.public = { - links: schemes.map(s => _buildLink(s, hostRouter.host, port)), - protocol: publicPortMapping.protocol, - schemes, - enabled: !!publicPortMapping.localProxyId - } - mapping.public.router = { - port, - host: hostFog.isSystem ? DEFAULT_ROUTER_NAME : hostFog.uuid - } -} - -async function switchOnUpdateFlagsForMicroservicesForPortMapping (microservice, isPublic, transaction) { - const updateRebuildMs = { - rebuild: true - } - await MicroserviceManager.update({ uuid: microservice.uuid }, updateRebuildMs, transaction) - - if (isPublic) { - await ChangeTrackingService.update(microservice.iofogUuid, ChangeTrackingService.events.microserviceFull, transaction) - } else { - await ChangeTrackingService.update(microservice.iofogUuid, ChangeTrackingService.events.microserviceConfig, transaction) - } -} - -async function listPortMappings (microserviceUuid, isCLI, transaction) { - const where = isCLI - ? { uuid: microserviceUuid } - : { uuid: microserviceUuid } - const microservice = await MicroserviceManager.findOne(where, transaction) - if (!microservice) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)) - } - - const portsPairs = await MicroservicePortManager.findAll({ microserviceUuid }, transaction) - return _buildPortsList(portsPairs, transaction) -} - -async function deletePortMapping (microserviceUuid, internalPort, isCLI, transaction) { - const where = isCLI - ? { uuid: microserviceUuid } - : { uuid: microserviceUuid } - - const microservice = await MicroserviceManager.findMicroserviceOnGet(where, transaction) - if (!microservice) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)) - } - - if (!internalPort) { - throw new Errors.ValidationError(ErrorMessages.PORT_MAPPING_INTERNAL_PORT_NOT_PROVIDED) - } - - const msPorts = await MicroservicePortManager.findOne({ - microserviceUuid: microservice.uuid, - portInternal: internalPort - }, transaction) - if (!msPorts) { - throw new Errors.NotFoundError('port mapping not exists') - } - - await _deletePortMapping(microservice, msPorts, transaction) -} - -async function deleteSystemPortMapping (microserviceUuid, internalPort, isCLI, transaction) { - const where = isCLI - ? { uuid: microserviceUuid } - : { uuid: microserviceUuid } - - const microservice = await MicroserviceManager.findOne(where, transaction) - if (!microservice) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)) - } - - if (!internalPort) { - throw new Errors.ValidationError(ErrorMessages.PORT_MAPPING_INTERNAL_PORT_NOT_PROVIDED) - } - - const msPorts = await MicroservicePortManager.findOne({ - microserviceUuid: microservice.uuid, - portInternal: internalPort - }, transaction) - if (!msPorts) { - throw new Errors.NotFoundError('port mapping not exists') - } - - await _deletePortMapping(microservice, msPorts, transaction) -} - -async function deletePortMappings (microservice, transaction) { - const portMappings = await MicroservicePortManager.findAll({ microserviceUuid: microservice.uuid }, transaction) - for (const ports of portMappings) { - await _deletePortMapping(microservice, ports, transaction) - } -} - -async function getPortMappings (microserviceUuid, transaction) { - return MicroservicePortManager.findAll({ microserviceUuid }, transaction) -} - -function listAllPublicPorts (transaction) { - return MicroservicePortManager.findAllPublicPorts(transaction) -} - -module.exports = { - validatePublicPortAppHostTemplate, - validatePortMappings, - validatePortMapping, - movePublicPortsToNewFog, - switchOnUpdateFlagsForMicroservicesForPortMapping, - createPortMapping, - buildPublicPortMapping, - listPortMappings, - deletePortMapping, - deleteSystemPortMapping, - deletePortMappings, - getPortMappings, - listAllPublicPorts -} diff --git a/src/services/registry-service.js b/src/services/registry-service.js index 15c03c46..eeb2550e 100644 --- a/src/services/registry-service.js +++ b/src/services/registry-service.js @@ -18,24 +18,19 @@ const ErrorMessages = require('../helpers/error-messages') const ChangeTrackingService = require('./change-tracking-service') const TransactionDecorator = require('../decorators/transaction-decorator') const FogManager = require('../data/managers/iofog-manager') -const Sequelize = require('sequelize') -const Op = Sequelize.Op +// const Sequelize = require('sequelize') +// const Op = Sequelize.Op const AppHelper = require('../helpers/app-helper') const createRegistry = async function (registry, transaction) { await Validator.validate(registry, Validator.schemas.registryCreate) - if (registry.requiresCert && registry.certificate === undefined) { - throw new Errors.ValidationError(ErrorMessages.CERT_PROPERTY_REQUIRED) - } let registryCreate = { url: registry.url, username: registry.username, password: registry.password, isPublic: registry.isPublic, - userEmail: registry.email, - requiresCert: registry.requiresCert, - certificate: registry.certificate + userEmail: registry.email } registryCreate = AppHelper.deleteUndefinedFields(registryCreate) @@ -52,14 +47,7 @@ const createRegistry = async function (registry, transaction) { const findRegistries = async function (isCLI, transaction) { const queryRegistry = isCLI ? {} - : { - [Op.or]: - [ - { - isPublic: true - } - ] - } + : {} const registries = await RegistryManager.findAllWithAttributes(queryRegistry, { exclude: ['password'] }, transaction) return { @@ -83,10 +71,6 @@ const deleteRegistry = async function (registryData, isCLI, transaction) { const updateRegistry = async function (registry, registryId, isCLI, transaction) { await Validator.validate(registry, Validator.schemas.registryUpdate) - if (registry.requiresCert && registry.certificate === undefined) { - throw new Errors.ValidationError(ErrorMessages.CERT_PROPERTY_REQUIRED) - } - const existingRegistry = await RegistryManager.findOne({ id: registryId }, transaction) @@ -100,9 +84,7 @@ const updateRegistry = async function (registry, registryId, isCLI, transaction) username: registry.username, password: registry.password, isPublic: registry.isPublic, - userEmail: registry.email, - requiresCert: registry.requiresCert, - certificate: registry.certificate + userEmail: registry.email } registryUpdate = AppHelper.deleteUndefinedFields(registryUpdate) diff --git a/src/services/router-service.js b/src/services/router-service.js index 8286c138..8472e002 100644 --- a/src/services/router-service.js +++ b/src/services/router-service.js @@ -295,7 +295,7 @@ function _createRouterPorts (routerMicroserviceUuid, port, transaction) { async function _createRouterMicroservice (isEdge, uuid, microserviceConfig, transaction) { const routerCatalog = await CatalogService.getRouterCatalogItem(transaction) - + // const hostNetworkMode = isEdge ? false : true const routerApplicationData = { name: `system-${uuid.toLowerCase()}`, isActivated: true, From 7fb573d82b60715c56b7b6c57c54942d21a4f46b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emirhan=20Durmu=C5=9F?= Date: Wed, 5 Nov 2025 00:38:54 +0300 Subject: [PATCH 3/3] msvc roothostacces to hostnetworkmode and isprivileged , regitry and catalog's change tracking logic updated, microservice env auto update with secret and configmap update, multi system agent router upstreamrouter handler, service defautl bridge fixed, minor fixes on cluster resources --- docs/swagger.yaml | 24 +++-- package-lock.json | 22 ++--- package.json | 7 +- src/cli/microservice.js | 24 +++-- ....0.4.sql => db_migration_mysql_v1.0.5.sql} | 4 + ..._v1.0.4.sql => db_migration_pg_v1.0.5.sql} | 6 +- ...0.4.sql => db_migration_sqlite_v1.0.5.sql} | 5 +- src/data/models/microservice.js | 9 +- src/data/providers/database-provider.js | 12 +-- src/helpers/error-messages.js | 2 + src/schemas/microservice.js | 6 +- src/schemas/secret.js | 1 + src/services/agent-service.js | 3 +- src/services/catalog-service.js | 38 +++++-- src/services/certificate-service.js | 9 +- src/services/config-map-service.js | 65 ++++++++++++ src/services/iofog-service.js | 36 ++++--- src/services/microservices-service.js | 32 ++++-- src/services/registry-service.js | 28 +++++- src/services/router-service.js | 30 +++++- src/services/secret-service.js | 98 ++++++++++++++++++- src/services/services-service.js | 63 ++++++++++-- src/services/yaml-parser-service.js | 3 +- 23 files changed, 431 insertions(+), 96 deletions(-) rename src/data/migrations/mysql/{db_migration_mysql_v1.0.4.sql => db_migration_mysql_v1.0.5.sql} (99%) rename src/data/migrations/postgres/{db_migration_pg_v1.0.4.sql => db_migration_pg_v1.0.5.sql} (99%) rename src/data/migrations/sqlite/{db_migration_sqlite_v1.0.4.sql => db_migration_sqlite_v1.0.5.sql} (99%) diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 239d5296..f38adde9 100755 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -5165,7 +5165,9 @@ components: type: string iofogUuid: type: string - rootHostAccess: + hostNetworkMode: + type: boolean + isPrivileged: type: boolean logSize: type: number @@ -5316,7 +5318,9 @@ components: type: string agentName: type: string - rootHostAccess: + hostNetworkMode: + type: boolean + isPrivileged: type: boolean logSize: type: number @@ -6012,7 +6016,9 @@ components: type: string rebuild: type: boolean - rootHostAccess: + hostNetworkMode: + type: boolean + isPrivileged: type: boolean logSize: type: number @@ -6364,7 +6370,9 @@ components: type: string annotations: type: string - rootHostAccess: + hostNetworkMode: + type: boolean + isPrivileged: type: boolean logLimit: type: number @@ -6457,7 +6465,9 @@ components: type: string agentName: type: string - rootHostAccess: + hostNetworkMode: + type: boolean + isPrivileged: type: boolean logSize: type: number @@ -6516,7 +6526,9 @@ components: type: string agentName: type: string - rootHostAccess: + hostNetworkMode: + type: boolean + isPrivileged: type: boolean logLimit: type: number diff --git a/package-lock.json b/package-lock.json index 53a57d01..1c0c914e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "hasInstallScript": true, "license": "EPL-2.0", "dependencies": { - "@datasance/ecn-viewer": "1.2.1", + "@datasance/ecn-viewer": "1.2.2", "@kubernetes/client-node": "^0.22.3", "@msgpack/msgpack": "^3.1.2", "@opentelemetry/api": "^1.9.0", @@ -60,7 +60,7 @@ "portscanner": "2.2.0", "qs": "6.12.1", "retry-as-promised": "7.0.4", - "sequelize": "6.37.3", + "sequelize": "6.37.7", "sqlite3": "^5.1.7", "string-format": "2.0.0", "umzug": "^3.7.0", @@ -426,9 +426,9 @@ } }, "node_modules/@datasance/ecn-viewer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@datasance/ecn-viewer/-/ecn-viewer-1.2.1.tgz", - "integrity": "sha512-l7st68cRAJIHfKQq3NOY6kV5dCU6kTHS/CnZCnxnC2i4GJcjVgWNgCo9IdS+gLkgVPL9Xh68VnndW/fYyd057Q==" + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@datasance/ecn-viewer/-/ecn-viewer-1.2.2.tgz", + "integrity": "sha512-IpDHtj90jg6AvEsZ3oj+y1K3FkJHem7HoIjQE+Tce4LE9Sk/hqgUsI5gW+VgjmWUIyME9W3Nw86S4AYx0uINEw==" }, "node_modules/@eslint-community/eslint-utils": { "version": "4.7.0", @@ -12136,9 +12136,9 @@ "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" }, "node_modules/sequelize": { - "version": "6.37.3", - "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.37.3.tgz", - "integrity": "sha512-V2FTqYpdZjPy3VQrZvjTPnOoLm0KudCRXfGWp48QwhyPPp2yW8z0p0sCYZd/em847Tl2dVxJJ1DR+hF+O77T7A==", + "version": "6.37.7", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.37.7.tgz", + "integrity": "sha512-mCnh83zuz7kQxxJirtFD7q6Huy6liPanI67BSlbzSYgVNl5eXVdE2CN1FuAeZwG1SNpGsNRCV+bJAVVnykZAFA==", "funding": [ { "type": "opencollective", @@ -14650,9 +14650,9 @@ } }, "node_modules/validator": { - "version": "13.15.15", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.15.tgz", - "integrity": "sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A==", + "version": "13.15.20", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.20.tgz", + "integrity": "sha512-KxPOq3V2LmfQPP4eqf3Mq/zrT0Dqp2Vmx2Bn285LwVahLc+CsxOM0crBHczm8ijlcjZ0Q5Xd6LW3z3odTPnlrw==", "engines": { "node": ">= 0.10" } diff --git a/package.json b/package.json index 8aaacfb2..9f981962 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "iofog-controller": "src/main.js" }, "dependencies": { - "@datasance/ecn-viewer": "1.2.1", + "@datasance/ecn-viewer": "1.2.2", "@kubernetes/client-node": "^0.22.3", "@msgpack/msgpack": "^3.1.2", "@opentelemetry/api": "^1.9.0", @@ -105,7 +105,7 @@ "portscanner": "2.2.0", "qs": "6.12.1", "retry-as-promised": "7.0.4", - "sequelize": "6.37.3", + "sequelize": "6.37.7", "sqlite3": "^5.1.7", "string-format": "2.0.0", "umzug": "^3.7.0", @@ -152,6 +152,9 @@ "prebuild-install": { "tar-fs": "^2.1.4" } + }, + "sequelize": { + "validator": "^13.15.20" } } } diff --git a/src/cli/microservice.js b/src/cli/microservice.js index e105537e..589b0cde 100644 --- a/src/cli/microservice.js +++ b/src/cli/microservice.js @@ -35,7 +35,8 @@ const JSON_SCHEMA_ADD = AppHelper.stringifyCliJsonSchema( registryId: 1, application: 'string', iofogUuid: 'string', - rootHostAccess: true, + hostNetworkMode: true, + isPrivileged: true, logSize: 0, volumeMappings: [ { @@ -86,7 +87,8 @@ const JSON_SCHEMA_UPDATE = AppHelper.stringifyCliJsonSchema( annotations: 'string', rebuild: true, iofogUuid: 'string', - rootHostAccess: true, + hostNetworkMode: true, + isPrivileged: true, logSize: 0, catalogItemId: 0, images: [ @@ -234,17 +236,17 @@ class Microservice extends BaseCLIHandler { group: [constants.CMD_UPDATE, constants.CMD_ADD] }, { - name: 'root-enable', - alias: 'r', + name: 'host-network-mode', + alias: 'hN', type: Boolean, - description: 'Enable root access', + description: 'Enable host network mode', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, { - name: 'root-disable', - alias: 'R', + name: 'is-privileged', + alias: 'iP', type: Boolean, - description: 'Disable root access', + description: 'Enable privileged mode', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, { @@ -663,7 +665,8 @@ const _updateMicroserviceObject = function (obj) { config: obj.config, annotations: obj.annotations, iofogUuid: obj.iofogUuid, - rootHostAccess: AppHelper.validateBooleanCliOptions(obj.rootEnable, obj.rootDisable), + hostNetworkMode: obj.hostNetworkMode, + isPrivileged: obj.isPrivileged, logSize: (obj.logSize || constants.MICROSERVICE_DEFAULT_LOG_SIZE) * 1, rebuild: obj.rebuild, cmd: obj.cmd, @@ -731,7 +734,8 @@ const _createMicroserviceObject = function (obj) { application: obj.applicationName, registryId: parseInt(obj.registryId) || undefined, iofogUuid: obj.iofogUuid, - rootHostAccess: AppHelper.validateBooleanCliOptions(obj.rootEnable, obj.rootDisable), + hostNetworkMode: obj.hostNetworkMode, + isPrivileged: obj.isPrivileged, logSize: (obj.logSize || constants.MICROSERVICE_DEFAULT_LOG_SIZE) * 1, routes: obj.routes, cmd: obj.cmd, diff --git a/src/data/migrations/mysql/db_migration_mysql_v1.0.4.sql b/src/data/migrations/mysql/db_migration_mysql_v1.0.5.sql similarity index 99% rename from src/data/migrations/mysql/db_migration_mysql_v1.0.4.sql rename to src/data/migrations/mysql/db_migration_mysql_v1.0.5.sql index f0f0c931..b0e86802 100644 --- a/src/data/migrations/mysql/db_migration_mysql_v1.0.4.sql +++ b/src/data/migrations/mysql/db_migration_mysql_v1.0.5.sql @@ -809,4 +809,8 @@ ALTER TABLE MicroserviceStatuses ADD COLUMN health_status TEXT; ALTER TABLE Microservices ADD COLUMN is_activated BOOLEAN DEFAULT true; +ALTER TABLE Microservices ADD COLUMN host_network_mode BOOLEAN DEFAULT false; +ALTER TABLE Microservices ADD COLUMN is_privileged BOOLEAN DEFAULT false; +ALTER TABLE Microservices DROP COLUMN root_host_access; + COMMIT; \ No newline at end of file diff --git a/src/data/migrations/postgres/db_migration_pg_v1.0.4.sql b/src/data/migrations/postgres/db_migration_pg_v1.0.5.sql similarity index 99% rename from src/data/migrations/postgres/db_migration_pg_v1.0.4.sql rename to src/data/migrations/postgres/db_migration_pg_v1.0.5.sql index 3ffbb188..09d6404b 100644 --- a/src/data/migrations/postgres/db_migration_pg_v1.0.4.sql +++ b/src/data/migrations/postgres/db_migration_pg_v1.0.5.sql @@ -807,4 +807,8 @@ CREATE INDEX idx_microservice_health_check_microservice_uuid ON "MicroserviceHea ALTER TABLE "MicroserviceStatuses" ADD COLUMN health_status TEXT; -ALTER TABLE "Microservices" ADD COLUMN is_activated BOOLEAN DEFAULT true; \ No newline at end of file +ALTER TABLE "Microservices" ADD COLUMN is_activated BOOLEAN DEFAULT true; + +ALTER TABLE "Microservices" ADD COLUMN host_network_mode BOOLEAN DEFAULT false; +ALTER TABLE "Microservices" ADD COLUMN is_privileged BOOLEAN DEFAULT false; +ALTER TABLE "Microservices" DROP COLUMN root_host_access; diff --git a/src/data/migrations/sqlite/db_migration_sqlite_v1.0.4.sql b/src/data/migrations/sqlite/db_migration_sqlite_v1.0.5.sql similarity index 99% rename from src/data/migrations/sqlite/db_migration_sqlite_v1.0.4.sql rename to src/data/migrations/sqlite/db_migration_sqlite_v1.0.5.sql index 83b6d35a..ab609d82 100644 --- a/src/data/migrations/sqlite/db_migration_sqlite_v1.0.4.sql +++ b/src/data/migrations/sqlite/db_migration_sqlite_v1.0.5.sql @@ -794,4 +794,7 @@ CREATE INDEX idx_microservice_health_check_microservice_uuid ON MicroserviceHeal ALTER TABLE MicroserviceStatuses ADD COLUMN health_status TEXT; -ALTER TABLE Microservices ADD COLUMN is_activated BOOLEAN DEFAULT true; \ No newline at end of file +ALTER TABLE Microservices ADD COLUMN is_activated BOOLEAN DEFAULT true; + +ALTER TABLE Microservices ADD COLUMN host_network_mode BOOLEAN DEFAULT false; +ALTER TABLE Microservices ADD COLUMN is_privileged BOOLEAN DEFAULT false; diff --git a/src/data/models/microservice.js b/src/data/models/microservice.js index e1128093..8278d10e 100644 --- a/src/data/models/microservice.js +++ b/src/data/models/microservice.js @@ -37,9 +37,14 @@ module.exports = (sequelize, DataTypes) => { field: 'rebuild', defaultValue: false }, - rootHostAccess: { + hostNetworkMode: { type: DataTypes.BOOLEAN, - field: 'root_host_access', + field: 'host_network_mode', + defaultValue: false + }, + isPrivileged: { + type: DataTypes.BOOLEAN, + field: 'is_privileged', defaultValue: false }, runAsUser: { diff --git a/src/data/providers/database-provider.js b/src/data/providers/database-provider.js index fd6b899c..941edff7 100644 --- a/src/data/providers/database-provider.js +++ b/src/data/providers/database-provider.js @@ -251,8 +251,8 @@ class DatabaseProvider { // SQLite migration async runMigrationSQLite (dbName) { - const migrationSqlPath = path.resolve(__dirname, '../migrations/sqlite/db_migration_sqlite_v1.0.4.sql') - const migrationVersion = '1.0.4' + const migrationSqlPath = path.resolve(__dirname, '../migrations/sqlite/db_migration_sqlite_v1.0.5.sql') + const migrationVersion = '1.0.5' if (!fs.existsSync(migrationSqlPath)) { logger.error(`Migration file not found: ${migrationSqlPath}`) @@ -324,8 +324,8 @@ class DatabaseProvider { // MySQL migration async runMigrationMySQL (db) { - const migrationSqlPath = path.resolve(__dirname, '../migrations/mysql/db_migration_mysql_v1.0.4.sql') - const migrationVersion = '1.0.4' + const migrationSqlPath = path.resolve(__dirname, '../migrations/mysql/db_migration_mysql_v1.0.5.sql') + const migrationVersion = '1.0.5' if (!fs.existsSync(migrationSqlPath)) { logger.error(`Migration file not found: ${migrationSqlPath}`) @@ -385,8 +385,8 @@ class DatabaseProvider { // PostgreSQL migration async runMigrationPostgres (db) { - const migrationSqlPath = path.resolve(__dirname, '../migrations/postgres/db_migration_pg_v1.0.4.sql') - const migrationVersion = '1.0.4' + const migrationSqlPath = path.resolve(__dirname, '../migrations/postgres/db_migration_pg_v1.0.5.sql') + const migrationVersion = '1.0.5' if (!fs.existsSync(migrationSqlPath)) { logger.error(`Migration file not found: ${migrationSqlPath}`) diff --git a/src/helpers/error-messages.js b/src/helpers/error-messages.js index 9966ca14..88131689 100644 --- a/src/helpers/error-messages.js +++ b/src/helpers/error-messages.js @@ -79,6 +79,8 @@ module.exports = { REGISTRY_NOT_FOUND: 'Registry not found', USER_ALREADY_ACTIVATED: 'User is already activated.', USER_NOT_ACTIVATED_YET: 'User is not activated yet.', + REGISTRY_IS_SYSTEM: 'Registry is system and can\'t be updated or deleted', + REGISTRY_IS_IN_USE: 'Registry is in use by microservices and can\'t be deleted', CLI: { INVALID_PORT_MAPPING: 'Port mapping parsing error. Please provide valid port mapping.', INVALID_VOLUME_MAPPING: 'Volume mapping parsing error. Please provide valid volume mapping.', diff --git a/src/schemas/microservice.js b/src/schemas/microservice.js index 4ec80352..670c491d 100644 --- a/src/schemas/microservice.js +++ b/src/schemas/microservice.js @@ -30,7 +30,8 @@ const microserviceCreate = { }, 'iofogUuid': { 'type': 'string' }, 'agentName': { 'type': 'string' }, - 'rootHostAccess': { 'type': 'boolean' }, + 'hostNetworkMode': { 'type': 'boolean' }, + 'isPrivileged': { 'type': 'boolean' }, 'schedule': { 'type': 'integer', 'minimum': 0, @@ -100,7 +101,8 @@ const microserviceUpdate = { 'rebuild': { 'type': 'boolean' }, 'iofogUuid': { 'type': 'string' }, 'agentName': { 'type': 'string' }, - 'rootHostAccess': { 'type': 'boolean' }, + 'hostNetworkMode': { 'type': 'boolean' }, + 'isPrivileged': { 'type': 'boolean' }, 'logSize': { 'type': 'integer', 'minimum': 0 }, 'schedule': { 'type': 'integer', diff --git a/src/schemas/secret.js b/src/schemas/secret.js index 6b52e5eb..3a370c67 100644 --- a/src/schemas/secret.js +++ b/src/schemas/secret.js @@ -15,6 +15,7 @@ const secretUpdate = { type: 'object', properties: { name: { type: 'string', minLength: 1, maxLength: 255 }, + type: { type: 'string', enum: ['Opaque', 'tls'] }, data: { type: 'object' } }, required: ['data'], diff --git a/src/services/agent-service.js b/src/services/agent-service.js index 4d771081..0fbd0705 100644 --- a/src/services/agent-service.js +++ b/src/services/agent-service.js @@ -411,7 +411,8 @@ const getAgentMicroservices = async function (fog, transaction) { config: microservice.config, annotations: microservice.annotations, rebuild: microservice.rebuild, - rootHostAccess: microservice.rootHostAccess, + hostNetworkMode: microservice.hostNetworkMode, + isPrivileged: microservice.isPrivileged, cpuSetCpus: microservice.cpuSetCpus, memoryLimit: microservice.memoryLimit, healthCheck: healthCheck, diff --git a/src/services/catalog-service.js b/src/services/catalog-service.js index 8350c19c..dcd36ac9 100644 --- a/src/services/catalog-service.js +++ b/src/services/catalog-service.js @@ -24,11 +24,12 @@ const Op = require('sequelize').Op const Validator = require('../schemas/index') const RegistryManager = require('../data/managers/registry-manager') const MicroserviceManager = require('../data/managers/microservice-manager') -const MicroseriveStates = require('../enums/microservice-state') +// const MicroseriveStates = require('../enums/microservice-state') +const ChangeTrackingService = require('./change-tracking-service') const createCatalogItemEndPoint = async function (data, transaction) { await Validator.validate(data, Validator.schemas.catalogItemCreate) - await _checkForDuplicateName(data.name, transaction) + await _checkForDuplicateName(data.name, null, transaction) await _checkForRestrictedPublisher(data.publisher) const catalogItem = await _createCatalogItem(data, transaction) await _createCatalogImages(data, catalogItem, transaction) @@ -129,6 +130,11 @@ const deleteCatalogItemEndPoint = async function (id, isCLI, transaction) { throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.SYSTEM_CATALOG_ITEM_DELETE, id)) } + const microservices = await MicroserviceManager.findAllWithStatuses({ catalogItemId: id }, transaction) + if (microservices.length > 0) { + throw new Errors.ValidationError(ErrorMessages.CATALOG_ITEM_IMAGES_IS_FROZEN) + } + const affectedRows = await CatalogItemManager.delete(where, transaction) if (affectedRows === 0) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_CATALOG_ITEM_ID, id)) @@ -183,7 +189,7 @@ async function getHalCatalogItem (transaction) { const _checkForDuplicateName = async function (name, item, transaction) { if (name) { - const where = item.id + const where = (item && item.id) ? { name: name, id: { [Op.ne]: item.id } } : { name: name } @@ -314,6 +320,12 @@ const _updateCatalogItem = async function (data, where, transaction) { if (!registry) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_REGISTRY_ID, data.registryId)) } + const microservices = await MicroserviceManager.findAllWithStatuses({ catalogItemId: data.id }, transaction) + if (microservices.length > 0) { + for (const ms of microservices) { + await MicroserviceManager.updateAndFind({ uuid: ms.uuid }, { registryId: data.registryId }, transaction) + } + } } const item = await _checkIfItemExists(where, transaction) @@ -328,12 +340,13 @@ const _updateCatalogItem = async function (data, where, transaction) { const _updateCatalogItemImages = async function (data, transaction) { if (data.images) { - const microservices = await MicroserviceManager.findAllWithStatuses({ catalogItemId: data.id }, transaction) - for (const ms of microservices) { - if (ms.microserviceStatus.status === MicroseriveStates.RUNNING) { - throw new Errors.ValidationError(ErrorMessages.CATALOG_ITEM_IMAGES_IS_FROZEN) - } - } + // TODO: Rather than not allowing images for running microservices, update changetracking for agent microsevice list so that once catalog item images are updated, the microservices are updated and restarted. + // const microservices = await MicroserviceManager.findAllWithStatuses({ catalogItemId: data.id }, transaction) + // for (const ms of microservices) { + // if (ms.microserviceStatus.status === MicroseriveStates.RUNNING) { + // throw new Errors.ValidationError(ErrorMessages.CATALOG_ITEM_IMAGES_IS_FROZEN) + // } + // } for (const image of data.images) { await CatalogItemImageManager.updateOrCreate({ @@ -345,6 +358,13 @@ const _updateCatalogItemImages = async function (data, transaction) { containerImage: image.containerImage }, transaction) } + const microservices = await MicroserviceManager.findAllWithStatuses({ catalogItemId: data.id }, transaction) + if (microservices.length > 0) { + for (const ms of microservices) { + await MicroserviceManager.updateAndFind({ uuid: ms.uuid }, { rebuild: true }, transaction) + await ChangeTrackingService.update(ms.iofogUuid, ChangeTrackingService.events.microserviceCommon, transaction) + } + } } } diff --git a/src/services/certificate-service.js b/src/services/certificate-service.js index 316062bc..e0e6b35e 100644 --- a/src/services/certificate-service.js +++ b/src/services/certificate-service.js @@ -215,7 +215,7 @@ async function deleteCAEndpoint (name, transaction) { // Delete certificate record and the secret await CertificateManager.deleteCertificate(name, transaction) - await SecretService.deleteSecretEndpoint(name) + await SecretService.deleteSecretEndpoint(name, transaction) return {} } @@ -420,15 +420,12 @@ async function deleteCertificateEndpoint (name, transaction) { // Check if this is a CA with signed certificates if (certRecord.isCA) { - const signedCerts = await CertificateManager.findCertificatesByCA(certRecord.id, transaction) - if (signedCerts.length > 0) { - throw new Errors.ValidationError(`Cannot delete CA that has signed certificates. Please delete the following certificates first: ${signedCerts.map(cert => cert.name).join(', ')}`) - } + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.CERTIFICATE_NOT_FOUND, name)) } // Delete certificate record and the secret await CertificateManager.deleteCertificate(name, transaction) - await SecretService.deleteSecretEndpoint(name) + await SecretService.deleteSecretEndpoint(name, transaction) return {} } diff --git a/src/services/config-map-service.js b/src/services/config-map-service.js index 1ccf0f0d..a1aa48c4 100644 --- a/src/services/config-map-service.js +++ b/src/services/config-map-service.js @@ -13,6 +13,9 @@ const TransactionDecorator = require('../decorators/transaction-decorator') const ConfigMapManager = require('../data/managers/config-map-manager') +const MicroserviceManager = require('../data/managers/microservice-manager') +const MicroserviceEnvManager = require('../data/managers/microservice-env-manager') +const ChangeTrackingService = require('./change-tracking-service') const AppHelper = require('../helpers/app-helper') const Errors = require('../helpers/errors') const ErrorMessages = require('../helpers/error-messages') @@ -58,6 +61,7 @@ async function updateConfigMapEndpoint (configMapName, configMapData, transactio const configMap = await ConfigMapManager.updateConfigMap(configMapName, configMapData.immutable, configMapData.data, transaction) await _updateChangeTrackingForFogs(configMapName, transaction) + await _updateMicroservicesUsingConfigMap(configMapName, transaction) return { id: configMap.id, name: configMap.name, @@ -102,9 +106,19 @@ async function deleteConfigMapEndpoint (configMapName, transaction) { } await ConfigMapManager.deleteConfigMap(configMapName, transaction) + await _deleteVolumeMountsUsingConfigMap(configMapName, transaction) return {} } +async function _deleteVolumeMountsUsingConfigMap (configMapName, transaction) { + const volumeMounts = await VolumeMountingManager.findAll({ configMapName: configMapName }, transaction) + if (volumeMounts.length > 0) { + for (const volumeMount of volumeMounts) { + await VolumeMountService.deleteVolumeMountEndpoint(volumeMount.name, transaction) + } + } +} + async function _updateChangeTrackingForFogs (configMapName, transaction) { const configMapVolumeMounts = await VolumeMountingManager.findAll({ configMapName: configMapName }, transaction) if (configMapVolumeMounts.length > 0) { @@ -118,6 +132,57 @@ async function _updateChangeTrackingForFogs (configMapName, transaction) { } } +async function _updateMicroservicesUsingConfigMap (configMapName, transaction) { + // Find all microservice environment variables that use this config map + const envVars = await MicroserviceEnvManager.findAll({ + valueFromConfigMap: { [require('sequelize').Op.like]: `${configMapName}/%` } + }, transaction) + + if (envVars.length === 0) { + return + } + + // Get the updated config map data + const configMap = await ConfigMapManager.getConfigMap(configMapName, transaction) + if (!configMap) { + return + } + + // Group environment variables by microservice UUID + const microserviceEnvMap = new Map() + for (const envVar of envVars) { + if (!microserviceEnvMap.has(envVar.microserviceUuid)) { + microserviceEnvMap.set(envVar.microserviceUuid, []) + } + microserviceEnvMap.get(envVar.microserviceUuid).push(envVar) + } + + // Update each microservice's environment variables and change tracking + for (const [microserviceUuid, envVars] of microserviceEnvMap) { + // Get the microservice to access its iofogUuid + const microservice = await MicroserviceManager.findOne({ uuid: microserviceUuid }, transaction) + if (!microservice) { + continue + } + + // Update each environment variable with the new config map data + for (const envVar of envVars) { + const [configMapNameFromRef, dataKey] = envVar.valueFromConfigMap.split('/') + if (configMapNameFromRef === configMapName && configMap.data[dataKey]) { + // Update the environment variable value with the new config map data + await MicroserviceEnvManager.update( + { id: envVar.id }, + { value: configMap.data[dataKey] }, + transaction + ) + } + } + + // Update change tracking for the microservice's fog node + await ChangeTrackingService.update(microservice.iofogUuid, ChangeTrackingService.events.microserviceCommon, transaction) + } +} + module.exports = { createConfigMapEndpoint: TransactionDecorator.generateTransaction(createConfigMapEndpoint), updateConfigMapEndpoint: TransactionDecorator.generateTransaction(updateConfigMapEndpoint), diff --git a/src/services/iofog-service.js b/src/services/iofog-service.js index 50229608..4e465b42 100644 --- a/src/services/iofog-service.js +++ b/src/services/iofog-service.js @@ -62,17 +62,19 @@ async function getLocalCertificateHosts (isKubernetes, namespace) { return '127.0.0.1,localhost,host.docker.internal,host.containers.internal' } -async function getSiteCertificateHosts (fogData, transaction) { +async function getSiteCertificateHosts (fogData, fogUuid, transaction) { const hosts = new Set() - // Add existing hosts if isSystem - if (fogData.isSystem) { + const defaultRouter = await RouterManager.findOne({ isDefault: true }, transaction) + const isFogDefaultRouter = fogUuid === defaultRouter.iofogUuid + // Add existing hosts if isSystem and fog is default-router + if (fogData.isSystem && isFogDefaultRouter) { if (fogData.host) hosts.add(fogData.host) if (fogData.ipAddress) hosts.add(fogData.ipAddress) if (fogData.ipAddressExternal) hosts.add(fogData.ipAddressExternal) } - // Add default router host if not system - if (!fogData.isSystem) { - const defaultRouter = await RouterManager.findOne({ isDefault: true }, transaction) + // Add default router host if not system or fog isSystem but not default-router + if (!fogData.isSystem || (fogData.isSystem && !isFogDefaultRouter)) { + // const defaultRouter = await RouterManager.findOne({ isDefault: true }, transaction) if (defaultRouter.host) hosts.add(defaultRouter.host) } // Add upstream router hosts @@ -197,7 +199,7 @@ async function _handleRouterCertificates (fogData, uuid, isRouterModeChanged, tr // For other router modes, ensure all other certificates // Always ensure site-server cert exists logger.debug('Ensuring site-server certificate exists') - const siteHosts = await getSiteCertificateHosts(fogData, transaction) + const siteHosts = await getSiteCertificateHosts(fogData, uuid, transaction) await ensureCert( `${uuid}-site-server`, `${uuid}-site-server`, @@ -298,10 +300,10 @@ async function createFogEndPoint (fogData, isCLI, transaction) { throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.INVALID_ROUTER_MODE, fogData.routerMode)) } - // TODO: handle multiple system fogs a.k.a multi-remote-controller and multi interior routers - if (fogData.isSystem && !!(await FogManager.findOne({ isSystem: true }, transaction))) { - throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.DUPLICATE_SYSTEM_FOG)) - } + // // TODO: handle multiple system fogs a.k.a multi-remote-controller and multi interior routers + // if (fogData.isSystem && !!(await FogManager.findOne({ isSystem: true }, transaction))) { + // throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.DUPLICATE_SYSTEM_FOG)) + // } const existingFog = await FogManager.findOne({ name: createFogData.name }, transaction) if (existingFog) { @@ -1079,7 +1081,8 @@ async function _createHalMicroserviceForFog (fogData, oldFog, transaction) { config: '{}', catalogItemId: halItem.id, iofogUuid: fogData.uuid, - rootHostAccess: true, + hostNetworkMode: true, + isPrivileged: true, logSize: Constants.MICROSERVICE_DEFAULT_LOG_SIZE, schedule: 1, configLastUpdated: Date.now() @@ -1124,7 +1127,8 @@ async function _createBluetoothMicroserviceForFog (fogData, oldFog, transaction) config: '{}', catalogItemId: bluetoothItem.id, iofogUuid: fogData.uuid, - rootHostAccess: true, + hostNetworkMode: true, + isPrivileged: true, logSize: Constants.MICROSERVICE_DEFAULT_LOG_SIZE, schedule: 1, configLastUpdated: Date.now() @@ -1187,7 +1191,8 @@ async function enableNodeExecEndPoint (execData, isCLI, transaction) { iofogUuid: execData.uuid, ipcMode: 'host', pidMode: 'host', - rootHostAccess: true, + hostNetworkMode: true, + isPrivileged: true, logSize: Constants.MICROSERVICE_DEFAULT_LOG_SIZE, schedule: 0, execEnabled: true, @@ -1228,7 +1233,8 @@ async function enableNodeExecEndPoint (execData, isCLI, transaction) { const updateData = { ipcMode: debugMicroserviceData.ipcMode, pidMode: debugMicroserviceData.pidMode, - rootHostAccess: debugMicroserviceData.rootHostAccess, + hostNetworkMode: debugMicroserviceData.hostNetworkMode, + isPrivileged: debugMicroserviceData.isPrivileged, logSize: debugMicroserviceData.logSize, schedule: debugMicroserviceData.schedule, configLastUpdated: debugMicroserviceData.configLastUpdated, diff --git a/src/services/microservices-service.js b/src/services/microservices-service.js index be84fcda..1214d170 100644 --- a/src/services/microservices-service.js +++ b/src/services/microservices-service.js @@ -314,6 +314,10 @@ async function createMicroserviceEndPoint (microserviceData, isCLI, transaction) _validateImagesAgainstCatalog(catalogItem, microserviceData.images || []) microserviceData.images = catalogItem.images _validateImageFogType(microserviceData, fog, catalogItem.images) + // use catalog item's registryId if it is set + if (catalogItem.registryId) { + microserviceData.registryId = catalogItem.registryId + } } else { _validateImageFogType(microserviceData, fog, microserviceData.images) } @@ -519,7 +523,8 @@ async function updateSystemMicroserviceEndPoint (microserviceUuid, microserviceD catalogItemId: microserviceData.catalogItemId, rebuild: microserviceData.rebuild, iofogUuid: newFog.uuid, - rootHostAccess: microserviceData.rootHostAccess, + hostNetworkMode: microserviceData.hostNetworkMode, + isPrivileged: microserviceData.isPrivileged, cpuSetCpus: microserviceData.cpuSetCpus, memoryLimit: microserviceData.memoryLimit, schedule: microserviceData.schedule, @@ -600,6 +605,11 @@ async function updateSystemMicroserviceEndPoint (microserviceUuid, microserviceD await _deleteImages(microserviceUuid, transaction) microserviceDataUpdate.registryId = catalogItem.registryId || 1 } + } else { + // use catalog item's registryId if it is set + if (catalogItem.registryId) { + microserviceDataUpdate.registryId = catalogItem.registryId + } } } else if (!microservice.catalogItemId && microserviceDataUpdate.images && microserviceDataUpdate.images.length === 0) { // No catalog, and no image @@ -640,7 +650,8 @@ async function updateSystemMicroserviceEndPoint (microserviceUuid, microserviceD // Set rebuild flag if needed microserviceDataUpdate.rebuild = microserviceDataUpdate.rebuild || !!( - (microserviceDataUpdate.rootHostAccess !== undefined && microservice.rootHostAccess !== microserviceDataUpdate.rootHostAccess) || + (microserviceDataUpdate.hostNetworkMode !== undefined && microservice.hostNetworkMode !== microserviceDataUpdate.hostNetworkMode) || + (microserviceDataUpdate.isPrivileged !== undefined && microservice.isPrivileged !== microserviceDataUpdate.isPrivileged) || microserviceDataUpdate.pidMode || microserviceDataUpdate.ipcMode || microserviceDataUpdate.cpuSetCpus || @@ -762,7 +773,8 @@ async function updateMicroserviceEndPoint (microserviceUuid, microserviceData, i catalogItemId: microserviceData.catalogItemId, rebuild: microserviceData.rebuild, iofogUuid: newFog.uuid, - rootHostAccess: microserviceData.rootHostAccess, + hostNetworkMode: microserviceData.hostNetworkMode, + isPrivileged: microserviceData.isPrivileged, cpuSetCpus: microserviceData.cpuSetCpus, memoryLimit: microserviceData.memoryLimit, schedule: microserviceData.schedule, @@ -847,6 +859,11 @@ async function updateMicroserviceEndPoint (microserviceUuid, microserviceData, i await _deleteImages(microserviceUuid, transaction) microserviceDataUpdate.registryId = catalogItem.registryId || 1 } + } else { + // use catalog item's registryId if it is set + if (catalogItem.registryId) { + microserviceDataUpdate.registryId = catalogItem.registryId + } } } else if (!microservice.catalogItemId && microserviceDataUpdate.images && microserviceDataUpdate.images.length === 0) { // No catalog, and no image @@ -887,7 +904,8 @@ async function updateMicroserviceEndPoint (microserviceUuid, microserviceData, i // Set rebuild flag if needed microserviceDataUpdate.rebuild = microserviceDataUpdate.rebuild || !!( - (microserviceDataUpdate.rootHostAccess !== undefined && microservice.rootHostAccess !== microserviceDataUpdate.rootHostAccess) || + (microserviceDataUpdate.hostNetworkMode !== undefined && microservice.hostNetworkMode !== microserviceDataUpdate.hostNetworkMode) || + (microserviceDataUpdate.isPrivileged !== undefined && microservice.isPrivileged !== microserviceDataUpdate.isPrivileged) || microserviceDataUpdate.pidMode || microserviceDataUpdate.ipcMode || microserviceDataUpdate.cpuSetCpus || @@ -1240,13 +1258,12 @@ async function deleteMicroserviceEndPoint (microserviceUuid, microserviceData, i throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.SYSTEM_MICROSERVICE_DELETE, microserviceUuid)) } - await deleteMicroserviceWithRoutesAndPortMappings(microservice, transaction) - const existingService = await ServiceManager.findOne({ type: `microservice`, resource: microservice.uuid }, transaction) if (existingService) { logger.info(`Deleting service ${existingService.name}`) await ServiceServices.deleteServiceEndpoint(existingService.name, transaction) } + await deleteMicroserviceWithRoutesAndPortMappings(microservice, transaction) await _updateChangeTracking(false, microservice.iofogUuid, transaction) } @@ -1726,7 +1743,8 @@ async function _createMicroservice (microserviceData, isCLI, transaction) { annotations: annotations, catalogItemId: microserviceData.catalogItemId, iofogUuid: microserviceData.iofogUuid, - rootHostAccess: microserviceData.rootHostAccess, + hostNetworkMode: microserviceData.hostNetworkMode, + isPrivileged: microserviceData.isPrivileged, cpuSetCpus: microserviceData.cpuSetCpus, memoryLimit: microserviceData.memoryLimit, pidMode: microserviceData.pidMode, diff --git a/src/services/registry-service.js b/src/services/registry-service.js index eeb2550e..62955855 100644 --- a/src/services/registry-service.js +++ b/src/services/registry-service.js @@ -18,6 +18,7 @@ const ErrorMessages = require('../helpers/error-messages') const ChangeTrackingService = require('./change-tracking-service') const TransactionDecorator = require('../decorators/transaction-decorator') const FogManager = require('../data/managers/iofog-manager') +const MicroserviceManager = require('../data/managers/microservice-manager') // const Sequelize = require('sequelize') // const Op = Sequelize.Op const AppHelper = require('../helpers/app-helper') @@ -60,17 +61,31 @@ const deleteRegistry = async function (registryData, isCLI, transaction) { const queryData = isCLI ? { id: registryData.id } : { id: registryData.id } + // Convert registryId to number to handle string IDs from URL parameters + const id = parseInt(registryData.id, 10) + if (id === 1 || id === 2) { + throw new Errors.ValidationError(ErrorMessages.REGISTRY_IS_SYSTEM) + } const registry = await RegistryManager.findOne(queryData, transaction) if (!registry) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_REGISTRY_ID, registryData.id)) } - await RegistryManager.delete(queryData, transaction) - await _updateChangeTracking(transaction) + const microservices = await MicroserviceManager.findAllWithStatuses({ registryId: registryData.id }, transaction) + if (microservices.length > 0) { + throw new Errors.ValidationError(ErrorMessages.REGISTRY_IS_IN_USE) + } else { + await RegistryManager.delete(queryData, transaction) + await _updateChangeTracking(transaction) + } } const updateRegistry = async function (registry, registryId, isCLI, transaction) { await Validator.validate(registry, Validator.schemas.registryUpdate) - + // Convert registryId to number to handle string IDs from URL parameters + const id = parseInt(registryId, 10) + if (id === 1 || id === 2) { + throw new Errors.ValidationError(ErrorMessages.REGISTRY_IS_SYSTEM) + } const existingRegistry = await RegistryManager.findOne({ id: registryId }, transaction) @@ -98,6 +113,13 @@ const updateRegistry = async function (registry, registryId, isCLI, transaction) } await RegistryManager.update(where, registryUpdate, transaction) + const microservices = await MicroserviceManager.findAllWithStatuses({ registryId: registryId }, transaction) + if (microservices.length > 0) { + for (const ms of microservices) { + await MicroserviceManager.updateAndFind({ uuid: ms.uuid }, { rebuild: true }, transaction) + await ChangeTrackingService.update(ms.iofogUuid, ChangeTrackingService.events.microserviceCommon, transaction) + } + } await _updateChangeTracking(transaction) } diff --git a/src/services/router-service.js b/src/services/router-service.js index 8472e002..c384e6d7 100644 --- a/src/services/router-service.js +++ b/src/services/router-service.js @@ -31,6 +31,7 @@ const ldifferenceWith = require('lodash/differenceWith') const constants = require('../helpers/constants') const MicroserviceEnvManager = require('../data/managers/microservice-env-manager') const SecretManager = require('../data/managers/secret-manager') +const FogManager = require('../data/managers/iofog-manager') const SITE_CONFIG_VERSION = 'pot' const SITE_CONFIG_NAMESPACE = 'datasance' @@ -42,7 +43,29 @@ async function validateAndReturnUpstreamRouters (upstreamRouterIds, isSystemFog, if (isSystemFog) { return [] } throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_ROUTER, Constants.DEFAULT_ROUTER_NAME)) } - return [defaultRouter] + + // Get all system fogs + const allSystemFogs = await FogManager.findAll({ isSystem: true }, transaction) + + // Get routers for each system fog + const systemFogRouters = [] + for (const systemFog of allSystemFogs) { + const systemFogRouter = await RouterManager.findOne({ iofogUuid: systemFog.uuid }, transaction) + if (systemFogRouter) { + systemFogRouters.push(systemFogRouter) + } + } + + // Combine default router with system fog routers, removing duplicates + const combinedRouters = [defaultRouter] + for (const systemFogRouter of systemFogRouters) { + // Check if this system fog router is not the same as the default router + if (systemFogRouter.id !== defaultRouter.id) { + combinedRouters.push(systemFogRouter) + } + } + + return combinedRouters } const upstreamRouters = [] @@ -295,7 +318,7 @@ function _createRouterPorts (routerMicroserviceUuid, port, transaction) { async function _createRouterMicroservice (isEdge, uuid, microserviceConfig, transaction) { const routerCatalog = await CatalogService.getRouterCatalogItem(transaction) - // const hostNetworkMode = isEdge ? false : true + const hostNetworkMode = !isEdge const routerApplicationData = { name: `system-${uuid.toLowerCase()}`, isActivated: true, @@ -307,7 +330,8 @@ async function _createRouterMicroservice (isEdge, uuid, microserviceConfig, tran config: JSON.stringify(microserviceConfig), catalogItemId: routerCatalog.id, iofogUuid: uuid, - rootHostAccess: false, + hostNetworkMode: hostNetworkMode, + isPrivileged: false, logSize: constants.MICROSERVICE_DEFAULT_LOG_SIZE, schedule: 0, configLastUpdated: Date.now(), diff --git a/src/services/secret-service.js b/src/services/secret-service.js index a51e11a6..c788d255 100644 --- a/src/services/secret-service.js +++ b/src/services/secret-service.js @@ -13,12 +13,16 @@ const TransactionDecorator = require('../decorators/transaction-decorator') const SecretManager = require('../data/managers/secret-manager') +const MicroserviceManager = require('../data/managers/microservice-manager') +const MicroserviceEnvManager = require('../data/managers/microservice-env-manager') +const ChangeTrackingService = require('./change-tracking-service') const AppHelper = require('../helpers/app-helper') const Errors = require('../helpers/errors') const ErrorMessages = require('../helpers/error-messages') const Validator = require('../schemas/index') const VolumeMountService = require('./volume-mount-service') const VolumeMountingManager = require('../data/managers/volume-mounting-manager') +const CertificateManager = require('../data/managers/certificate-manager') function validateBase64 (value) { try { @@ -82,6 +86,7 @@ async function updateSecretEndpoint (secretName, secretData, transaction) { const secret = await SecretManager.updateSecret(secretName, secretData.data, transaction) await _updateChangeTrackingForFogs(secretName, transaction) + await _updateMicroservicesUsingSecret(secretName, transaction) return { id: secret.id, name: secret.name, @@ -126,10 +131,38 @@ async function deleteSecretEndpoint (secretName, transaction) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.SECRET_NOT_FOUND, secretName)) } - await SecretManager.deleteSecret(secretName, transaction) + if (existingSecret.type === 'tls') { + const certificate = await CertificateManager.findCertificateByName(secretName, transaction) + if (certificate) { + if (certificate.isCA) { + // Check if this CA has signed certificates + const signedCerts = await CertificateManager.findCertificatesByCA(certificate.id, transaction) + if (signedCerts.length > 0) { + throw new Errors.ValidationError(`Cannot delete CA that has signed certificates. Please delete the following certificates first: ${signedCerts.map(cert => cert.name).join(', ')}`) + } + await CertificateManager.deleteCertificate(certificate.name, transaction) + await _deleteVolumeMountsUsingSecret(secretName, transaction) + } else { + await CertificateManager.deleteCertificate(certificate.name, transaction) + await _deleteVolumeMountsUsingSecret(secretName, transaction) + } + } + } else { + await SecretManager.deleteSecret(secretName, transaction) + await _deleteVolumeMountsUsingSecret(secretName, transaction) + } return {} } +async function _deleteVolumeMountsUsingSecret (secretName, transaction) { + const volumeMounts = await VolumeMountingManager.findAll({ secretName: secretName }, transaction) + if (volumeMounts.length > 0) { + for (const volumeMount of volumeMounts) { + await VolumeMountService.deleteVolumeMountEndpoint(volumeMount.name, transaction) + } + } +} + async function _updateChangeTrackingForFogs (secretName, transaction) { const secretVolumeMounts = await VolumeMountingManager.findAll({ secretName: secretName }, transaction) if (secretVolumeMounts.length > 0) { @@ -143,6 +176,69 @@ async function _updateChangeTrackingForFogs (secretName, transaction) { } } +async function _updateMicroservicesUsingSecret (secretName, transaction) { + // Find all microservice environment variables that use this secret + const envVars = await MicroserviceEnvManager.findAll({ + valueFromSecret: { [require('sequelize').Op.like]: `${secretName}/%` } + }, transaction) + + if (envVars.length === 0) { + return + } + + // Get the updated secret data + const secret = await SecretManager.getSecret(secretName, transaction) + if (!secret) { + return + } + + // Group environment variables by microservice UUID + const microserviceEnvMap = new Map() + for (const envVar of envVars) { + if (!microserviceEnvMap.has(envVar.microserviceUuid)) { + microserviceEnvMap.set(envVar.microserviceUuid, []) + } + microserviceEnvMap.get(envVar.microserviceUuid).push(envVar) + } + + // Update each microservice's environment variables and change tracking + for (const [microserviceUuid, envVars] of microserviceEnvMap) { + // Get the microservice to access its iofogUuid + const microservice = await MicroserviceManager.findOne({ uuid: microserviceUuid }, transaction) + if (!microservice) { + continue + } + + // Update each environment variable with the new secret data + for (const envVar of envVars) { + const [secretNameFromRef, dataKey] = envVar.valueFromSecret.split('/') + if (secretNameFromRef === secretName && secret.data[dataKey]) { + let newValue = secret.data[dataKey] + + // If it's a TLS secret, decode the base64 value + if (secret.type === 'tls') { + try { + newValue = Buffer.from(secret.data[dataKey], 'base64').toString('utf-8') + } catch (error) { + // Skip this environment variable if base64 decoding fails + continue + } + } + + // Update the environment variable value with the new secret data + await MicroserviceEnvManager.update( + { id: envVar.id }, + { value: newValue }, + transaction + ) + } + } + + // Update change tracking for the microservice's fog node + await ChangeTrackingService.update(microservice.iofogUuid, ChangeTrackingService.events.microserviceCommon, transaction) + } +} + module.exports = { createSecretEndpoint: TransactionDecorator.generateTransaction(createSecretEndpoint), updateSecretEndpoint: TransactionDecorator.generateTransaction(updateSecretEndpoint), diff --git a/src/services/services-service.js b/src/services/services-service.js index be2982ab..2b2c0b59 100644 --- a/src/services/services-service.js +++ b/src/services/services-service.js @@ -257,7 +257,7 @@ async function _determineConnectorHost (serviceConfig, transaction) { switch (serviceConfig.type.toLowerCase()) { case 'microservice': const microservice = await MicroserviceManager.findOne({ uuid: serviceConfig.resource }, transaction) - if (microservice.rootHostAccess) { + if (microservice.hostNetworkMode) { return 'iofog' } else { return `iofog_${serviceConfig.resource}` @@ -462,14 +462,20 @@ async function _addTcpListener (serviceConfig, transaction) { // If not in K8s environment, always include default router if (!isK8s) { - const defaultRouter = await RouterManager.findOne({ isDefault: true }, transaction) - if (!defaultRouter) { - logger.error('Default router not found') - throw new Errors.NotFoundError('Default router not found') - } - // Add default router if not already in the list - if (!fogNodeUuids.includes(defaultRouter.iofogUuid)) { - fogNodeUuids.push(defaultRouter.iofogUuid) + if (serviceConfig.defaultBridge === 'default-router') { + const defaultRouter = await RouterManager.findOne({ isDefault: true }, transaction) + if (!defaultRouter) { + logger.error('Default router not found') + throw new Errors.NotFoundError('Default router not found') + } + // Add default router if not already in the list + if (!fogNodeUuids.includes(defaultRouter.iofogUuid)) { + fogNodeUuids.push(defaultRouter.iofogUuid) + } + } else { + if (!fogNodeUuids.includes(serviceConfig.defaultBridge)) { + fogNodeUuids.push(serviceConfig.defaultBridge) + } } } // else if (!fogNodeUuids || fogNodeUuids.length === 0) { @@ -950,6 +956,23 @@ async function createServiceEndpoint (serviceData, transaction) { // Set provisioning fields serviceData.provisioningStatus = 'pending' serviceData.provisioningError = null + if (!isK8s) { + if (serviceData.defaultBridge === 'default-router') { + const defaultRouter = await RouterManager.findOne({ isDefault: true }, transaction) + if (!defaultRouter) { + throw new Errors.NotFoundError('Default router not found') + } + serviceData.serviceEndpoint = defaultRouter.host + serviceData.servicePort = serviceData.bridgePort + } else { + const router = await RouterManager.findOne({ iofogUuid: serviceData.defaultBridge }, transaction) + if (!router) { + throw new Errors.NotFoundError('Router not found') + } + serviceData.serviceEndpoint = router.host + serviceData.servicePort = serviceData.bridgePort + } + } // 7. Create service in database first logger.debug('Creating service in database') @@ -1008,6 +1031,10 @@ async function updateServiceEndpoint (serviceName, serviceData, transaction) { throw new Errors.ValidationError('Changing service type is not allowed. Please delete the service and create a new one with the desired type.') } + if (serviceData.defaultBridge && serviceData.defaultBridge !== existingService.defaultBridge) { + throw new Errors.ValidationError('Changing default bridge is not allowed. Please delete the service and create a new one with the desired default bridge.') + } + // 4. Check K8s environment if type is k8s const isK8s = await checkKubernetesEnvironment() if (existingService.type === 'k8s' && !isK8s) { @@ -1040,6 +1067,24 @@ async function updateServiceEndpoint (serviceName, serviceData, transaction) { serviceData.provisioningStatus = 'pending' serviceData.provisioningError = null + if (!isK8s) { + if (serviceData.defaultBridge === 'default-router') { + const defaultRouter = await RouterManager.findOne({ isDefault: true }, transaction) + if (!defaultRouter) { + throw new Errors.NotFoundError('Default router not found') + } + serviceData.serviceEndpoint = defaultRouter.host + serviceData.servicePort = serviceData.bridgePort + } else { + const router = await RouterManager.findOne({ iofogUuid: serviceData.defaultBridge }, transaction) + if (!router) { + throw new Errors.NotFoundError('Router not found') + } + serviceData.serviceEndpoint = router.host + serviceData.servicePort = serviceData.bridgePort + } + } + // 8. Update service in database const updatedService = await ServiceManager.update( { name: serviceName }, diff --git a/src/services/yaml-parser-service.js b/src/services/yaml-parser-service.js index adc8d94c..084f2f3e 100644 --- a/src/services/yaml-parser-service.js +++ b/src/services/yaml-parser-service.js @@ -333,7 +333,8 @@ const parseMicroserviceYAML = async (microservice) => { agentName: lget(microservice, 'agent.name'), registryId, ...container, - rootHostAccess: lget(microservice, 'container.rootHostAccess', false), + hostNetworkMode: lget(microservice, 'container.hostNetworkMode', false), + isPrivileged: lget(microservice, 'container.isPrivileged', false), pidMode: lget(microservice, 'container.pidMode', ''), ipcMode: lget(microservice, 'container.ipcMode', ''), cpuSetCpus: lget(microservice, 'container.cpuSetCpus', ''),