@flightctl/ui-components 1.1.0-rc1 → 1.1.0-rc3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/components/Repository/CreateRepository/CreateRepositoryForm.css +5 -1
- package/dist/types/imagebuilder/index.d.ts +2 -0
- package/dist/types/imagebuilder/index.d.ts.map +1 -1
- package/dist/types/imagebuilder/index.js +3 -1
- package/dist/types/imagebuilder/index.js.map +1 -1
- package/dist/types/imagebuilder/models/ApiVersion.d.ts +8 -0
- package/dist/types/imagebuilder/models/ApiVersion.d.ts.map +1 -0
- package/dist/types/imagebuilder/models/ApiVersion.js +16 -0
- package/dist/types/imagebuilder/models/ApiVersion.js.map +1 -0
- package/dist/types/imagebuilder/models/ImageBuild.d.ts +2 -4
- package/dist/types/imagebuilder/models/ImageBuild.d.ts.map +1 -1
- package/dist/types/imagebuilder/models/ImageBuildList.d.ts +2 -4
- package/dist/types/imagebuilder/models/ImageBuildList.d.ts.map +1 -1
- package/dist/types/imagebuilder/models/ImageExport.d.ts +2 -4
- package/dist/types/imagebuilder/models/ImageExport.d.ts.map +1 -1
- package/dist/types/imagebuilder/models/ImageExportList.d.ts +2 -4
- package/dist/types/imagebuilder/models/ImageExportList.d.ts.map +1 -1
- package/dist/types/imagebuilder/models/Status.d.ts +28 -0
- package/dist/types/imagebuilder/models/Status.d.ts.map +1 -0
- package/dist/types/imagebuilder/models/Status.js +3 -0
- package/dist/types/imagebuilder/models/Status.js.map +1 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +3 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/models/ApiVersion.d.ts +9 -0
- package/dist/types/models/ApiVersion.d.ts.map +1 -0
- package/dist/types/models/ApiVersion.js +17 -0
- package/dist/types/models/ApiVersion.js.map +1 -0
- package/dist/types/models/ApplicationProviderBase.d.ts +12 -0
- package/dist/types/models/ApplicationProviderBase.d.ts.map +1 -0
- package/dist/types/models/ApplicationProviderBase.js +3 -0
- package/dist/types/models/ApplicationProviderBase.js.map +1 -0
- package/dist/types/models/ApplicationProviderSpec.d.ts +5 -15
- package/dist/types/models/ApplicationProviderSpec.d.ts.map +1 -1
- package/dist/types/models/ApplicationUser.d.ts +7 -0
- package/dist/types/models/ApplicationUser.d.ts.map +1 -0
- package/dist/types/models/ApplicationUser.js +3 -0
- package/dist/types/models/ApplicationUser.js.map +1 -0
- package/dist/types/models/AuthConfig.d.ts +2 -4
- package/dist/types/models/AuthConfig.d.ts.map +1 -1
- package/dist/types/models/AuthProvider.d.ts +2 -4
- package/dist/types/models/AuthProvider.d.ts.map +1 -1
- package/dist/types/models/AuthProviderList.d.ts +2 -4
- package/dist/types/models/AuthProviderList.d.ts.map +1 -1
- package/dist/types/models/CertificateSigningRequest.d.ts +2 -4
- package/dist/types/models/CertificateSigningRequest.d.ts.map +1 -1
- package/dist/types/models/CertificateSigningRequestList.d.ts +2 -4
- package/dist/types/models/CertificateSigningRequestList.d.ts.map +1 -1
- package/dist/types/models/ComposeApplication.d.ts +7 -0
- package/dist/types/models/ComposeApplication.d.ts.map +1 -0
- package/dist/types/models/ComposeApplication.js +3 -0
- package/dist/types/models/ComposeApplication.js.map +1 -0
- package/dist/types/models/ContainerApplication.d.ts +18 -0
- package/dist/types/models/ContainerApplication.d.ts.map +1 -0
- package/dist/types/models/ContainerApplication.js +3 -0
- package/dist/types/models/ContainerApplication.js.map +1 -0
- package/dist/types/models/ContainerApplicationProperties.d.ts +13 -0
- package/dist/types/models/ContainerApplicationProperties.d.ts.map +1 -0
- package/dist/types/models/ContainerApplicationProperties.js +3 -0
- package/dist/types/models/ContainerApplicationProperties.js.map +1 -0
- package/dist/types/models/Device.d.ts +2 -4
- package/dist/types/models/Device.d.ts.map +1 -1
- package/dist/types/models/DeviceList.d.ts +2 -4
- package/dist/types/models/DeviceList.d.ts.map +1 -1
- package/dist/types/models/EnrollmentRequest.d.ts +2 -4
- package/dist/types/models/EnrollmentRequest.d.ts.map +1 -1
- package/dist/types/models/EnrollmentRequestList.d.ts +2 -4
- package/dist/types/models/EnrollmentRequestList.d.ts.map +1 -1
- package/dist/types/models/Event.d.ts +2 -4
- package/dist/types/models/Event.d.ts.map +1 -1
- package/dist/types/models/Event.js.map +1 -1
- package/dist/types/models/EventList.d.ts +2 -4
- package/dist/types/models/EventList.d.ts.map +1 -1
- package/dist/types/models/Fleet.d.ts +2 -4
- package/dist/types/models/Fleet.d.ts.map +1 -1
- package/dist/types/models/FleetList.d.ts +2 -4
- package/dist/types/models/FleetList.d.ts.map +1 -1
- package/dist/types/models/HelmApplication.d.ts +20 -0
- package/dist/types/models/HelmApplication.d.ts.map +1 -0
- package/dist/types/models/HelmApplication.js +3 -0
- package/dist/types/models/HelmApplication.js.map +1 -0
- package/dist/types/models/ImageApplicationProviderSpec.d.ts +2 -22
- package/dist/types/models/ImageApplicationProviderSpec.d.ts.map +1 -1
- package/dist/types/models/InlineApplicationProviderSpec.d.ts +2 -3
- package/dist/types/models/InlineApplicationProviderSpec.d.ts.map +1 -1
- package/dist/types/models/Organization.d.ts +2 -4
- package/dist/types/models/Organization.d.ts.map +1 -1
- package/dist/types/models/OrganizationList.d.ts +2 -4
- package/dist/types/models/OrganizationList.d.ts.map +1 -1
- package/dist/types/models/QuadletApplication.d.ts +8 -0
- package/dist/types/models/QuadletApplication.d.ts.map +1 -0
- package/dist/types/models/QuadletApplication.js +3 -0
- package/dist/types/models/QuadletApplication.js.map +1 -0
- package/dist/types/models/Repository.d.ts +2 -4
- package/dist/types/models/Repository.d.ts.map +1 -1
- package/dist/types/models/RepositoryList.d.ts +2 -4
- package/dist/types/models/RepositoryList.d.ts.map +1 -1
- package/dist/types/models/ResourceSync.d.ts +2 -4
- package/dist/types/models/ResourceSync.d.ts.map +1 -1
- package/dist/types/models/ResourceSyncList.d.ts +2 -4
- package/dist/types/models/ResourceSyncList.d.ts.map +1 -1
- package/dist/types/models/Status.d.ts +2 -4
- package/dist/types/models/Status.d.ts.map +1 -1
- package/dist/types/models/TemplateVersion.d.ts +2 -4
- package/dist/types/models/TemplateVersion.d.ts.map +1 -1
- package/dist/types/models/TemplateVersionList.d.ts +2 -4
- package/dist/types/models/TemplateVersionList.d.ts.map +1 -1
- package/dist/ui-components/src/components/AuthProvider/CreateAuthProvider/utils.d.ts.map +1 -1
- package/dist/ui-components/src/components/AuthProvider/CreateAuthProvider/utils.js +51 -51
- package/dist/ui-components/src/components/AuthProvider/CreateAuthProvider/utils.js.map +1 -1
- package/dist/ui-components/src/components/DetailsPage/Tables/ApplicationsTable.js +1 -1
- package/dist/ui-components/src/components/DetailsPage/Tables/ApplicationsTable.js.map +1 -1
- package/dist/ui-components/src/components/Device/DeviceDetails/DeviceDetailsPage.d.ts.map +1 -1
- package/dist/ui-components/src/components/Device/DeviceDetails/DeviceDetailsPage.js +5 -4
- package/dist/ui-components/src/components/Device/DeviceDetails/DeviceDetailsPage.js.map +1 -1
- package/dist/ui-components/src/components/Device/DeviceDetails/TerminalTab.d.ts.map +1 -1
- package/dist/ui-components/src/components/Device/DeviceDetails/TerminalTab.js +5 -1
- package/dist/ui-components/src/components/Device/DeviceDetails/TerminalTab.js.map +1 -1
- package/dist/ui-components/src/components/Device/EditDeviceWizard/deviceSpecUtils.d.ts +3 -3
- package/dist/ui-components/src/components/Device/EditDeviceWizard/deviceSpecUtils.d.ts.map +1 -1
- package/dist/ui-components/src/components/Device/EditDeviceWizard/deviceSpecUtils.js +310 -363
- package/dist/ui-components/src/components/Device/EditDeviceWizard/deviceSpecUtils.js.map +1 -1
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationContainerForm.d.ts +1 -3
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationContainerForm.d.ts.map +1 -1
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationContainerForm.js +18 -19
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationContainerForm.js.map +1 -1
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationHelmForm.d.ts +1 -3
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationHelmForm.d.ts.map +1 -1
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationHelmForm.js +5 -4
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationHelmForm.js.map +1 -1
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationImageForm.d.ts +1 -3
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationImageForm.d.ts.map +1 -1
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationImageForm.js +2 -2
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationImageForm.js.map +1 -1
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationInlineForm.d.ts +3 -3
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationInlineForm.d.ts.map +1 -1
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationInlineForm.js +20 -23
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationInlineForm.js.map +1 -1
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationIntegritySettings.js +3 -3
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationIntegritySettings.js.map +1 -1
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationTemplates.d.ts.map +1 -1
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationTemplates.js +25 -45
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationTemplates.js.map +1 -1
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationVariablesForm.d.ts +8 -0
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationVariablesForm.d.ts.map +1 -0
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationVariablesForm.js +37 -0
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationVariablesForm.js.map +1 -0
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationVolumeForm.d.ts +1 -3
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationVolumeForm.d.ts.map +1 -1
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationVolumeForm.js +5 -8
- package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationVolumeForm.js.map +1 -1
- package/dist/ui-components/src/components/Device/EditDeviceWizard/utils.d.ts +18 -18
- package/dist/ui-components/src/components/ErrorAlert/ErrorAlert.d.ts +4 -2
- package/dist/ui-components/src/components/ErrorAlert/ErrorAlert.d.ts.map +1 -1
- package/dist/ui-components/src/components/ErrorAlert/ErrorAlert.js +2 -2
- package/dist/ui-components/src/components/ErrorAlert/ErrorAlert.js.map +1 -1
- package/dist/ui-components/src/components/Fleet/CreateFleet/utils.d.ts +1 -1
- package/dist/ui-components/src/components/Fleet/CreateFleet/utils.d.ts.map +1 -1
- package/dist/ui-components/src/components/Fleet/CreateFleet/utils.js +3 -3
- package/dist/ui-components/src/components/Fleet/CreateFleet/utils.js.map +1 -1
- package/dist/ui-components/src/components/Fleet/ImportFleetWizard/steps/RepositoryStep.d.ts.map +1 -1
- package/dist/ui-components/src/components/Fleet/ImportFleetWizard/steps/RepositoryStep.js +3 -1
- package/dist/ui-components/src/components/Fleet/ImportFleetWizard/steps/RepositoryStep.js.map +1 -1
- package/dist/ui-components/src/components/ImageBuilds/CancelImageBuildModal/CancelImageBuildModal.d.ts +7 -0
- package/dist/ui-components/src/components/ImageBuilds/CancelImageBuildModal/CancelImageBuildModal.d.ts.map +1 -0
- package/dist/ui-components/src/components/ImageBuilds/CancelImageBuildModal/CancelImageBuildModal.js +40 -0
- package/dist/ui-components/src/components/ImageBuilds/CancelImageBuildModal/CancelImageBuildModal.js.map +1 -0
- package/dist/ui-components/src/components/ImageBuilds/ConfirmImageExportModal/ConfirmImageExportModal.d.ts +8 -0
- package/dist/ui-components/src/components/ImageBuilds/ConfirmImageExportModal/ConfirmImageExportModal.d.ts.map +1 -0
- package/dist/ui-components/src/components/ImageBuilds/ConfirmImageExportModal/ConfirmImageExportModal.js +37 -0
- package/dist/ui-components/src/components/ImageBuilds/ConfirmImageExportModal/ConfirmImageExportModal.js.map +1 -0
- package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/CreateImageBuildWizard.d.ts.map +1 -1
- package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/CreateImageBuildWizard.js +4 -3
- package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/CreateImageBuildWizard.js.map +1 -1
- package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/steps/OutputImageStep.js +1 -1
- package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/steps/OutputImageStep.js.map +1 -1
- package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/steps/RegistrationStep.d.ts.map +1 -1
- package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/steps/RegistrationStep.js +13 -10
- package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/steps/RegistrationStep.js.map +1 -1
- package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/steps/ReviewStep.d.ts.map +1 -1
- package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/steps/ReviewStep.js +4 -2
- package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/steps/ReviewStep.js.map +1 -1
- package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/steps/SourceImageStep.d.ts.map +1 -1
- package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/steps/SourceImageStep.js +7 -1
- package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/steps/SourceImageStep.js.map +1 -1
- package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/types.d.ts +3 -5
- package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/types.d.ts.map +1 -1
- package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/utils.d.ts +3 -2
- package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/utils.d.ts.map +1 -1
- package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/utils.js +139 -34
- package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/utils.js.map +1 -1
- package/dist/ui-components/src/components/ImageBuilds/ImageBuildDetails/ImageBuildDetailsPage.d.ts.map +1 -1
- package/dist/ui-components/src/components/ImageBuilds/ImageBuildDetails/ImageBuildDetailsPage.js +23 -12
- package/dist/ui-components/src/components/ImageBuilds/ImageBuildDetails/ImageBuildDetailsPage.js.map +1 -1
- package/dist/ui-components/src/components/ImageBuilds/ImageBuildDetails/ImageBuildExportsGallery.d.ts.map +1 -1
- package/dist/ui-components/src/components/ImageBuilds/ImageBuildDetails/ImageBuildExportsGallery.js +115 -39
- package/dist/ui-components/src/components/ImageBuilds/ImageBuildDetails/ImageBuildExportsGallery.js.map +1 -1
- package/dist/ui-components/src/components/ImageBuilds/ImageBuildDetails/ImageBuildLogsTab.d.ts +1 -0
- package/dist/ui-components/src/components/ImageBuilds/ImageBuildDetails/ImageBuildLogsTab.d.ts.map +1 -1
- package/dist/ui-components/src/components/ImageBuilds/ImageBuildDetails/ImageBuildLogsTab.js +17 -18
- package/dist/ui-components/src/components/ImageBuilds/ImageBuildDetails/ImageBuildLogsTab.js.map +1 -1
- package/dist/ui-components/src/components/ImageBuilds/ImageBuildRow.d.ts +5 -2
- package/dist/ui-components/src/components/ImageBuilds/ImageBuildRow.d.ts.map +1 -1
- package/dist/ui-components/src/components/ImageBuilds/ImageBuildRow.js +22 -12
- package/dist/ui-components/src/components/ImageBuilds/ImageBuildRow.js.map +1 -1
- package/dist/ui-components/src/components/ImageBuilds/ImageBuildsPage.d.ts.map +1 -1
- package/dist/ui-components/src/components/ImageBuilds/ImageBuildsPage.js +17 -8
- package/dist/ui-components/src/components/ImageBuilds/ImageBuildsPage.js.map +1 -1
- package/dist/ui-components/src/components/ImageBuilds/ImageExportCards.d.ts +10 -9
- package/dist/ui-components/src/components/ImageBuilds/ImageExportCards.d.ts.map +1 -1
- package/dist/ui-components/src/components/ImageBuilds/ImageExportCards.js +122 -26
- package/dist/ui-components/src/components/ImageBuilds/ImageExportCards.js.map +1 -1
- package/dist/ui-components/src/components/Repository/CreateRepository/CreateRepositoryForm.d.ts +2 -1
- package/dist/ui-components/src/components/Repository/CreateRepository/CreateRepositoryForm.d.ts.map +1 -1
- package/dist/ui-components/src/components/Repository/CreateRepository/CreateRepositoryForm.js +10 -4
- package/dist/ui-components/src/components/Repository/CreateRepository/CreateRepositoryForm.js.map +1 -1
- package/dist/ui-components/src/components/Repository/CreateRepository/utils.d.ts.map +1 -1
- package/dist/ui-components/src/components/Repository/CreateRepository/utils.js +3 -4
- package/dist/ui-components/src/components/Repository/CreateRepository/utils.js.map +1 -1
- package/dist/ui-components/src/components/form/RepositorySelect.d.ts.map +1 -1
- package/dist/ui-components/src/components/form/RepositorySelect.js +1 -1
- package/dist/ui-components/src/components/form/RepositorySelect.js.map +1 -1
- package/dist/ui-components/src/components/form/UploadField.d.ts.map +1 -1
- package/dist/ui-components/src/components/form/UploadField.js +25 -16
- package/dist/ui-components/src/components/form/UploadField.js.map +1 -1
- package/dist/ui-components/src/components/form/validations.d.ts +25 -18
- package/dist/ui-components/src/components/form/validations.d.ts.map +1 -1
- package/dist/ui-components/src/components/form/validations.js +79 -33
- package/dist/ui-components/src/components/form/validations.js.map +1 -1
- package/dist/ui-components/src/components/modals/CreateRepositoryModal/CreateRepositoryModal.d.ts +2 -1
- package/dist/ui-components/src/components/modals/CreateRepositoryModal/CreateRepositoryModal.d.ts.map +1 -1
- package/dist/ui-components/src/components/modals/CreateRepositoryModal/CreateRepositoryModal.js +2 -2
- package/dist/ui-components/src/components/modals/CreateRepositoryModal/CreateRepositoryModal.js.map +1 -1
- package/dist/ui-components/src/constants.d.ts +5 -6
- package/dist/ui-components/src/constants.d.ts.map +1 -1
- package/dist/ui-components/src/constants.js +19 -11
- package/dist/ui-components/src/constants.js.map +1 -1
- package/dist/ui-components/src/hooks/useWebSocket.d.ts.map +1 -1
- package/dist/ui-components/src/hooks/useWebSocket.js +25 -4
- package/dist/ui-components/src/hooks/useWebSocket.js.map +1 -1
- package/dist/ui-components/src/types/deviceSpec.d.ts +44 -76
- package/dist/ui-components/src/types/deviceSpec.d.ts.map +1 -1
- package/dist/ui-components/src/types/deviceSpec.js +13 -26
- package/dist/ui-components/src/types/deviceSpec.js.map +1 -1
- package/dist/ui-components/src/types/extraTypes.d.ts +1 -7
- package/dist/ui-components/src/types/extraTypes.d.ts.map +1 -1
- package/dist/ui-components/src/types/extraTypes.js.map +1 -1
- package/dist/ui-components/src/types/rbac.d.ts +7 -1
- package/dist/ui-components/src/types/rbac.d.ts.map +1 -1
- package/dist/ui-components/src/types/rbac.js +6 -0
- package/dist/ui-components/src/types/rbac.js.map +1 -1
- package/dist/ui-components/src/utils/imageBuilds.d.ts +1 -0
- package/dist/ui-components/src/utils/imageBuilds.d.ts.map +1 -1
- package/dist/ui-components/src/utils/imageBuilds.js +20 -29
- package/dist/ui-components/src/utils/imageBuilds.js.map +1 -1
- package/dist/ui-components/src/utils/search.d.ts +2 -1
- package/dist/ui-components/src/utils/search.d.ts.map +1 -1
- package/dist/ui-components/src/utils/search.js +2 -2
- package/dist/ui-components/src/utils/search.js.map +1 -1
- package/package.json +2 -2
- package/src/components/AuthProvider/CreateAuthProvider/utils.ts +2 -2
- package/src/components/DetailsPage/Tables/ApplicationsTable.tsx +2 -2
- package/src/components/Device/DeviceDetails/DeviceDetailsPage.tsx +10 -4
- package/src/components/Device/DeviceDetails/TerminalTab.tsx +9 -1
- package/src/components/Device/EditDeviceWizard/deviceSpecUtils.ts +361 -425
- package/src/components/Device/EditDeviceWizard/steps/ApplicationContainerForm.tsx +19 -29
- package/src/components/Device/EditDeviceWizard/steps/ApplicationHelmForm.tsx +5 -13
- package/src/components/Device/EditDeviceWizard/steps/ApplicationImageForm.tsx +2 -16
- package/src/components/Device/EditDeviceWizard/steps/ApplicationInlineForm.tsx +8 -7
- package/src/components/Device/EditDeviceWizard/steps/ApplicationIntegritySettings.tsx +5 -5
- package/src/components/Device/EditDeviceWizard/steps/ApplicationTemplates.tsx +29 -101
- package/src/components/Device/EditDeviceWizard/steps/ApplicationVariablesForm.tsx +87 -0
- package/src/components/Device/EditDeviceWizard/steps/ApplicationVolumeForm.tsx +5 -10
- package/src/components/ErrorAlert/ErrorAlert.tsx +13 -3
- package/src/components/Fleet/CreateFleet/utils.ts +4 -5
- package/src/components/Fleet/ImportFleetWizard/steps/RepositoryStep.tsx +11 -8
- package/src/components/ImageBuilds/CancelImageBuildModal/CancelImageBuildModal.tsx +81 -0
- package/src/components/ImageBuilds/ConfirmImageExportModal/ConfirmImageExportModal.tsx +61 -0
- package/src/components/ImageBuilds/CreateImageBuildWizard/CreateImageBuildWizard.tsx +8 -3
- package/src/components/ImageBuilds/CreateImageBuildWizard/steps/OutputImageStep.tsx +1 -1
- package/src/components/ImageBuilds/CreateImageBuildWizard/steps/RegistrationStep.tsx +18 -10
- package/src/components/ImageBuilds/CreateImageBuildWizard/steps/ReviewStep.tsx +5 -1
- package/src/components/ImageBuilds/CreateImageBuildWizard/steps/SourceImageStep.tsx +13 -1
- package/src/components/ImageBuilds/CreateImageBuildWizard/types.ts +3 -6
- package/src/components/ImageBuilds/CreateImageBuildWizard/utils.ts +161 -37
- package/src/components/ImageBuilds/ImageBuildDetails/ImageBuildDetailsPage.tsx +36 -17
- package/src/components/ImageBuilds/ImageBuildDetails/ImageBuildExportsGallery.tsx +131 -44
- package/src/components/ImageBuilds/ImageBuildDetails/ImageBuildLogsTab.tsx +22 -26
- package/src/components/ImageBuilds/ImageBuildRow.tsx +41 -20
- package/src/components/ImageBuilds/ImageBuildsPage.tsx +34 -15
- package/src/components/ImageBuilds/ImageExportCards.tsx +198 -80
- package/src/components/Repository/CreateRepository/CreateRepositoryForm.css +5 -1
- package/src/components/Repository/CreateRepository/CreateRepositoryForm.tsx +14 -4
- package/src/components/Repository/CreateRepository/utils.ts +4 -4
- package/src/components/form/RepositorySelect.tsx +1 -0
- package/src/components/form/UploadField.tsx +29 -30
- package/src/components/form/validations.ts +156 -106
- package/src/components/modals/CreateRepositoryModal/CreateRepositoryModal.tsx +3 -1
- package/src/constants.ts +19 -6
- package/src/hooks/useWebSocket.ts +25 -3
- package/src/types/deviceSpec.ts +68 -108
- package/src/types/extraTypes.ts +2 -12
- package/src/types/rbac.ts +6 -0
- package/src/utils/imageBuilds.ts +22 -32
- package/src/utils/search.ts +2 -2
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import yaml from 'js-yaml';
|
|
2
2
|
import {
|
|
3
3
|
AppType,
|
|
4
|
-
|
|
4
|
+
ApplicationContent,
|
|
5
5
|
ApplicationProviderSpec,
|
|
6
6
|
ApplicationResourceLimits,
|
|
7
7
|
ApplicationVolume,
|
|
8
|
+
ApplicationVolumeReclaimPolicy,
|
|
9
|
+
ComposeApplication,
|
|
8
10
|
ConfigProviderSpec,
|
|
11
|
+
ContainerApplication,
|
|
9
12
|
DeviceSpec,
|
|
10
13
|
EncodingType,
|
|
11
14
|
FileSpec,
|
|
12
15
|
GitConfigProviderSpec,
|
|
16
|
+
HelmApplication,
|
|
13
17
|
HttpConfigProviderSpec,
|
|
14
18
|
ImageApplicationProviderSpec,
|
|
15
19
|
ImageMountVolumeProviderSpec,
|
|
@@ -18,42 +22,37 @@ import {
|
|
|
18
22
|
InlineConfigProviderSpec,
|
|
19
23
|
KubernetesSecretProviderSpec,
|
|
20
24
|
PatchRequest,
|
|
25
|
+
QuadletApplication,
|
|
21
26
|
} from '@flightctl/types';
|
|
22
27
|
import {
|
|
23
28
|
AppForm,
|
|
24
29
|
AppSpecType,
|
|
25
30
|
ApplicationVolumeForm,
|
|
26
|
-
|
|
27
|
-
ComposeInlineAppForm,
|
|
31
|
+
ComposeAppForm,
|
|
28
32
|
ConfigSourceProvider,
|
|
29
33
|
ConfigType,
|
|
30
34
|
GitConfigTemplate,
|
|
31
|
-
|
|
35
|
+
HelmAppForm,
|
|
32
36
|
HttpConfigTemplate,
|
|
33
37
|
InlineConfigTemplate,
|
|
38
|
+
InlineFileForm,
|
|
34
39
|
KubeSecretTemplate,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
RUN_AS_DEFAULT_USER,
|
|
40
|
+
QuadletAppForm,
|
|
41
|
+
RUN_AS_FLIGHTCTL_USER,
|
|
42
|
+
RUN_AS_ROOT_USER,
|
|
39
43
|
SingleContainerAppForm,
|
|
40
44
|
SpecConfigTemplate,
|
|
41
45
|
SystemdUnitFormValue,
|
|
42
|
-
isComposeImageAppForm,
|
|
43
46
|
isGitConfigTemplate,
|
|
44
47
|
isGitProviderSpec,
|
|
45
|
-
isHelmImageAppForm,
|
|
46
48
|
isHttpConfigTemplate,
|
|
47
49
|
isHttpProviderSpec,
|
|
48
|
-
|
|
50
|
+
isImageVariantApp,
|
|
49
51
|
isInlineProviderSpec,
|
|
52
|
+
isInlineVariantApp,
|
|
50
53
|
isKubeProviderSpec,
|
|
51
54
|
isKubeSecretTemplate,
|
|
52
|
-
isQuadletImageAppForm,
|
|
53
|
-
isQuadletInlineAppForm,
|
|
54
|
-
isSingleContainerAppForm,
|
|
55
55
|
} from '../../../types/deviceSpec';
|
|
56
|
-
import { InlineApplicationFileFixed } from '../../../types/extraTypes';
|
|
57
56
|
|
|
58
57
|
const DEFAULT_INLINE_FILE_MODE = 420; // In Octal: 0644
|
|
59
58
|
const DEFAULT_INLINE_FILE_USER = 'root';
|
|
@@ -220,366 +219,374 @@ export const getDeviceSpecConfigPatches = (
|
|
|
220
219
|
return allPatches;
|
|
221
220
|
};
|
|
222
221
|
|
|
223
|
-
|
|
224
|
-
if (
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
};
|
|
230
|
-
if (app.namespace) {
|
|
231
|
-
data.namespace = app.namespace;
|
|
232
|
-
}
|
|
233
|
-
if (app.valuesYaml) {
|
|
234
|
-
try {
|
|
235
|
-
const values = yaml.load(app.valuesYaml) as Record<string, unknown>;
|
|
236
|
-
if (values && Object.keys(values).length > 0) {
|
|
237
|
-
data.values = values;
|
|
238
|
-
}
|
|
239
|
-
} catch (error) {
|
|
240
|
-
throw new Error('Values content is not valid YAML.');
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
const fileNames = app.valuesFiles.filter((file) => file && file.trim() !== '');
|
|
244
|
-
if (fileNames.length > 0) {
|
|
245
|
-
data.valuesFiles = fileNames;
|
|
246
|
-
}
|
|
247
|
-
return data;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
const envVars = app.variables.reduce((acc, variable) => {
|
|
251
|
-
acc[variable.name] = variable.value;
|
|
252
|
-
return acc;
|
|
253
|
-
}, {});
|
|
254
|
-
|
|
255
|
-
const volumes = app.volumes?.map((v) => {
|
|
256
|
-
const volume: Partial<ApplicationVolume & ImageMountVolumeProviderSpec> = {
|
|
257
|
-
name: v.name || '',
|
|
258
|
-
};
|
|
259
|
-
|
|
260
|
-
if (v.imageRef) {
|
|
261
|
-
volume.image = {
|
|
262
|
-
reference: v.imageRef,
|
|
263
|
-
pullPolicy: v.imagePullPolicy || ImagePullPolicy.PullIfNotPresent,
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
|
-
if (v.mountPath) {
|
|
267
|
-
volume.mount = {
|
|
268
|
-
path: v.mountPath,
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
return volume as ApplicationVolume;
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
if (isSingleContainerAppForm(app)) {
|
|
275
|
-
const data: ImageApplicationProviderSpec & ApplicationProviderSpec = {
|
|
276
|
-
image: app.image,
|
|
277
|
-
appType: app.appType,
|
|
278
|
-
envVars,
|
|
279
|
-
volumes,
|
|
280
|
-
};
|
|
281
|
-
if (app.name) {
|
|
282
|
-
data.name = app.name;
|
|
283
|
-
}
|
|
284
|
-
if (app.ports) {
|
|
285
|
-
data.ports = app.ports.map((p) => `${p.hostPort}:${p.containerPort}`);
|
|
286
|
-
}
|
|
287
|
-
// Removed fields must not appear in the resources object
|
|
288
|
-
const appLimits: ApplicationResourceLimits = {};
|
|
289
|
-
if (app.limits?.cpu) {
|
|
290
|
-
appLimits.cpu = app.limits.cpu;
|
|
291
|
-
}
|
|
292
|
-
if (app.limits?.memory) {
|
|
293
|
-
appLimits.memory = app.limits.memory;
|
|
294
|
-
}
|
|
295
|
-
if (Object.keys(appLimits).length > 0) {
|
|
296
|
-
data.resources = {
|
|
297
|
-
limits: appLimits,
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
|
-
data.runAs = app.runAs || RUN_AS_DEFAULT_USER;
|
|
301
|
-
return data;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
if (isQuadletImageAppForm(app) || isComposeImageAppForm(app)) {
|
|
305
|
-
const data: ApplicationProviderSpec = {
|
|
306
|
-
image: app.image,
|
|
307
|
-
appType: app.appType,
|
|
308
|
-
envVars,
|
|
309
|
-
volumes,
|
|
310
|
-
};
|
|
311
|
-
if (app.name) {
|
|
312
|
-
data.name = app.name;
|
|
313
|
-
}
|
|
314
|
-
if (isQuadletImageAppForm(app) && app.runAs) {
|
|
315
|
-
data.runAs = app.runAs;
|
|
316
|
-
}
|
|
317
|
-
return data;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
// Inline applications (Quadlet or Compose)
|
|
321
|
-
const inlineData: ApplicationProviderSpec = {
|
|
322
|
-
name: app.name,
|
|
323
|
-
appType: app.appType,
|
|
324
|
-
inline: toAPIFiles(app.files),
|
|
325
|
-
envVars,
|
|
326
|
-
volumes,
|
|
327
|
-
};
|
|
328
|
-
if (isQuadletInlineAppForm(app) && app.runAs) {
|
|
329
|
-
inlineData.runAs = app.runAs;
|
|
330
|
-
}
|
|
331
|
-
return inlineData;
|
|
332
|
-
};
|
|
333
|
-
|
|
334
|
-
const hasInlineApplicationChanged = (
|
|
335
|
-
currentApp: InlineApplicationProviderSpec,
|
|
336
|
-
updatedApp: QuadletInlineAppForm | ComposeInlineAppForm,
|
|
337
|
-
) => {
|
|
338
|
-
if (currentApp.inline.length !== updatedApp.files.length) {
|
|
339
|
-
return true;
|
|
340
|
-
}
|
|
341
|
-
const filesChanged = currentApp.inline.some((file, index) => {
|
|
342
|
-
const updatedFile = updatedApp.files[index];
|
|
343
|
-
const isCurrentBase64 = file.contentEncoding === EncodingType.EncodingBase64;
|
|
222
|
+
const haveInlineFilesChanged = (current: ApplicationContent[], updated: ApplicationContent[]): boolean => {
|
|
223
|
+
if (current.length !== updated.length) return true;
|
|
224
|
+
return current.some((file, index) => {
|
|
225
|
+
const other = updated[index];
|
|
226
|
+
const aBase64 = file.contentEncoding === EncodingType.EncodingBase64;
|
|
227
|
+
const bBase64 = other.contentEncoding === EncodingType.EncodingBase64;
|
|
344
228
|
return (
|
|
345
|
-
(
|
|
346
|
-
updatedFile.path !== file.path ||
|
|
347
|
-
updatedFile.content !== file.content
|
|
229
|
+
aBase64 !== bBase64 || (file.path || '') !== (other.path || '') || (file.content || '') !== (other.content || '')
|
|
348
230
|
);
|
|
349
231
|
});
|
|
350
|
-
if (filesChanged) {
|
|
351
|
-
return true;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
// Check runAs for Quadlet inline apps
|
|
355
|
-
if (isQuadletInlineAppForm(updatedApp)) {
|
|
356
|
-
const currentAppWithRunAs = currentApp as InlineApplicationProviderSpec & { runAs?: string };
|
|
357
|
-
if ((currentAppWithRunAs.runAs || RUN_AS_DEFAULT_USER) !== (updatedApp.runAs || RUN_AS_DEFAULT_USER)) {
|
|
358
|
-
return true;
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
return !areVolumesEqual(currentApp.volumes || [], updatedApp.volumes || []);
|
|
363
232
|
};
|
|
364
233
|
|
|
365
|
-
const
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
const updatedFormVol = updatedFormVolumes[index];
|
|
372
|
-
const currentFullVol = currentVol as ApplicationVolume & ImageMountVolumeProviderSpec;
|
|
373
|
-
|
|
374
|
-
if (currentFullVol.name !== updatedFormVol.name) {
|
|
375
|
-
return false;
|
|
376
|
-
}
|
|
234
|
+
const haveEnvVarsChanged = (current: Record<string, string>, updated: Record<string, string>): boolean => {
|
|
235
|
+
const aKeys = Object.keys(current);
|
|
236
|
+
const bKeys = Object.keys(updated);
|
|
237
|
+
if (aKeys.length !== bKeys.length) return true;
|
|
238
|
+
return aKeys.some((key) => current[key] !== updated[key]);
|
|
239
|
+
};
|
|
377
240
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
241
|
+
const haveVolumesChanged = (current: ApplicationVolume[], updated: ApplicationVolume[]): boolean => {
|
|
242
|
+
if (current.length !== updated.length) return true;
|
|
243
|
+
return current.some((currentVol, index) => {
|
|
244
|
+
const updatedVol = updated[index];
|
|
245
|
+
if (currentVol.name !== updatedVol.name) return true;
|
|
246
|
+
if (
|
|
247
|
+
(currentVol.reclaimPolicy || ApplicationVolumeReclaimPolicy.RETAIN) !==
|
|
248
|
+
(updatedVol.reclaimPolicy || ApplicationVolumeReclaimPolicy.RETAIN)
|
|
249
|
+
)
|
|
250
|
+
return true;
|
|
383
251
|
|
|
252
|
+
const currentFull = currentVol as ApplicationVolume & ImageMountVolumeProviderSpec;
|
|
253
|
+
const updatedFull = updatedVol as ApplicationVolume & ImageMountVolumeProviderSpec;
|
|
254
|
+
const currentImageRef = currentFull.image?.reference || '';
|
|
255
|
+
const updatedImageRef = updatedFull.image?.reference || '';
|
|
256
|
+
if (currentImageRef !== updatedImageRef) return true;
|
|
384
257
|
if (currentImageRef || updatedImageRef) {
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
const currentMountPath = currentFullVol.mount?.path || '';
|
|
393
|
-
const updatedMountPath = updatedFormVol?.mountPath || '';
|
|
394
|
-
if (currentMountPath !== updatedMountPath) {
|
|
395
|
-
return false;
|
|
258
|
+
if (
|
|
259
|
+
(currentFull.image?.pullPolicy || ImagePullPolicy.PullIfNotPresent) !==
|
|
260
|
+
(updatedFull.image?.pullPolicy || ImagePullPolicy.PullIfNotPresent)
|
|
261
|
+
)
|
|
262
|
+
return true;
|
|
396
263
|
}
|
|
397
|
-
|
|
398
|
-
return true;
|
|
264
|
+
return (currentFull.mount?.path || '') !== (updatedFull.mount?.path || '');
|
|
399
265
|
});
|
|
400
266
|
};
|
|
401
267
|
|
|
402
|
-
const
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
268
|
+
const hasStringChanged = (
|
|
269
|
+
current: string | undefined,
|
|
270
|
+
updated: string | undefined,
|
|
271
|
+
defaultValue: string = '',
|
|
272
|
+
): boolean => (current || defaultValue) !== (updated || defaultValue);
|
|
406
273
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
return currentPort === `${updatedPort.hostPort}:${updatedPort.containerPort}`;
|
|
411
|
-
});
|
|
274
|
+
const havePortsChanged = (current: string[], updated: string[]): boolean => {
|
|
275
|
+
if (current.length !== updated.length) return true;
|
|
276
|
+
return current.some((port, index) => port !== updated[index]);
|
|
412
277
|
};
|
|
413
278
|
|
|
414
|
-
const
|
|
415
|
-
|
|
416
|
-
|
|
279
|
+
const haveResourceLimitsChanged = (
|
|
280
|
+
current: { cpu?: string; memory?: string } | undefined,
|
|
281
|
+
updated: { cpu?: string; memory?: string } | undefined,
|
|
417
282
|
): boolean => {
|
|
418
|
-
|
|
419
|
-
const updatedCpu = updatedLimits?.cpu || '';
|
|
420
|
-
const currentMemory = currentLimits?.memory || '';
|
|
421
|
-
const updatedMemory = updatedLimits?.memory || '';
|
|
422
|
-
|
|
423
|
-
return currentCpu === updatedCpu && currentMemory === updatedMemory;
|
|
283
|
+
return (current?.cpu || '') !== (updated?.cpu || '') || (current?.memory || '') !== (updated?.memory || '');
|
|
424
284
|
};
|
|
425
285
|
|
|
426
|
-
const
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
)
|
|
430
|
-
|
|
431
|
-
if (Object.keys(envVars).length !== updatedFormVars.length) {
|
|
432
|
-
return false;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
return updatedFormVars.every((variable) => {
|
|
436
|
-
// Envvars may have "falsy" values (eg. number 0) when they are defined
|
|
437
|
-
return variable.name in envVars && envVars[variable.name] === variable.value;
|
|
438
|
-
});
|
|
286
|
+
const haveValuesFilesChanged = (current: string[], updated: string[]): boolean => {
|
|
287
|
+
const a = current.filter((f) => f.trim() !== '');
|
|
288
|
+
const b = updated.filter((f) => f.trim() !== '');
|
|
289
|
+
if (a.length !== b.length) return true;
|
|
290
|
+
return a.some((file, i) => file !== b[i]);
|
|
439
291
|
};
|
|
440
292
|
|
|
441
|
-
const
|
|
442
|
-
|
|
443
|
-
return true;
|
|
444
|
-
}
|
|
293
|
+
const haveHelmValuesChanged = (current: Record<string, unknown>, updated: Record<string, unknown>): boolean =>
|
|
294
|
+
JSON.stringify(current) !== JSON.stringify(updated);
|
|
445
295
|
|
|
446
|
-
|
|
447
|
-
if (
|
|
296
|
+
const hasRunAsChanged = (current: string | undefined, updated: string | undefined): boolean => {
|
|
297
|
+
if (!current) {
|
|
298
|
+
// For empty "runAs", we mark the app as changed.
|
|
299
|
+
// This means that we'll set the field explicitly to the default user (currently "root").
|
|
448
300
|
return true;
|
|
449
301
|
}
|
|
302
|
+
return current !== updated;
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
// Single container apps always have an image, and it doesn't have an inline variant
|
|
306
|
+
const hasContainerAppChanged = (current: ContainerApplication, updated: ContainerApplication): boolean =>
|
|
307
|
+
hasStringChanged(current.name, updated.name) ||
|
|
308
|
+
hasStringChanged(current.image, updated.image) ||
|
|
309
|
+
havePortsChanged(current.ports || [], updated.ports || []) ||
|
|
310
|
+
haveResourceLimitsChanged(current.resources?.limits, updated.resources?.limits) ||
|
|
311
|
+
haveEnvVarsChanged(current.envVars || {}, updated.envVars || {}) ||
|
|
312
|
+
hasRunAsChanged(current.runAs, updated.runAs) ||
|
|
313
|
+
haveVolumesChanged(current.volumes || [], updated.volumes || []);
|
|
314
|
+
|
|
315
|
+
// Helm apps always have an image (chart), and it doesn't have an inline variant
|
|
316
|
+
const hasHelmAppChanged = (current: HelmApplication, updated: HelmApplication): boolean =>
|
|
317
|
+
hasStringChanged(current.name, updated.name) ||
|
|
318
|
+
hasStringChanged(current.image, updated.image) ||
|
|
319
|
+
hasStringChanged(current.namespace, updated.namespace) ||
|
|
320
|
+
haveValuesFilesChanged(current.valuesFiles || [], updated.valuesFiles || []) ||
|
|
321
|
+
haveHelmValuesChanged(current.values || {}, updated.values || {});
|
|
322
|
+
|
|
323
|
+
const hasComposeAppChanged = (
|
|
324
|
+
current: ComposeApplication,
|
|
325
|
+
updated: ComposeApplication,
|
|
326
|
+
specType: AppSpecType,
|
|
327
|
+
): boolean => {
|
|
328
|
+
const baseChanged =
|
|
329
|
+
hasStringChanged(current.name, updated.name) ||
|
|
330
|
+
haveEnvVarsChanged(current.envVars || {}, updated.envVars || {}) ||
|
|
331
|
+
haveVolumesChanged(current.volumes || [], updated.volumes || []);
|
|
450
332
|
|
|
451
|
-
if (
|
|
333
|
+
if (baseChanged) {
|
|
452
334
|
return true;
|
|
453
335
|
}
|
|
454
336
|
|
|
455
|
-
if (
|
|
456
|
-
return
|
|
337
|
+
if (specType === AppSpecType.OCI_IMAGE) {
|
|
338
|
+
return hasStringChanged(
|
|
339
|
+
(current as ImageApplicationProviderSpec).image,
|
|
340
|
+
(updated as ImageApplicationProviderSpec).image,
|
|
341
|
+
);
|
|
457
342
|
}
|
|
343
|
+
return haveInlineFilesChanged(
|
|
344
|
+
(current as InlineApplicationProviderSpec).inline,
|
|
345
|
+
(updated as InlineApplicationProviderSpec).inline,
|
|
346
|
+
);
|
|
347
|
+
};
|
|
458
348
|
|
|
459
|
-
|
|
349
|
+
// Quadlet apps are currently the same as Compose apps, plus an optional "runAs" field.
|
|
350
|
+
const hasQuadletAppChanged = (
|
|
351
|
+
current: QuadletApplication,
|
|
352
|
+
updated: QuadletApplication,
|
|
353
|
+
specType: AppSpecType,
|
|
354
|
+
): boolean => {
|
|
355
|
+
const baseChanged = hasComposeAppChanged(current, updated, specType);
|
|
356
|
+
if (baseChanged) {
|
|
460
357
|
return true;
|
|
461
358
|
}
|
|
359
|
+
return hasRunAsChanged(current.runAs, updated.runAs);
|
|
360
|
+
};
|
|
462
361
|
|
|
463
|
-
|
|
362
|
+
const hasApplicationChanged = (current: ApplicationProviderSpec, updated: ApplicationProviderSpec): boolean => {
|
|
363
|
+
if (current.appType !== updated.appType) {
|
|
464
364
|
return true;
|
|
465
365
|
}
|
|
466
|
-
return !areVolumesEqual(imageApp.volumes || [], updatedApp.volumes || []);
|
|
467
|
-
};
|
|
468
|
-
|
|
469
|
-
const hasApplicationChanged = (currentApp: ApplicationProviderSpec, updatedApp: AppForm): boolean => {
|
|
470
|
-
const isCurrentImageApp = isImageAppProvider(currentApp);
|
|
471
|
-
const currentAppSpecType = isCurrentImageApp ? AppSpecType.OCI_IMAGE : AppSpecType.INLINE;
|
|
472
366
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
currentApp.appType !== updatedApp.appType ||
|
|
477
|
-
currentApp.name !== updatedApp.name
|
|
478
|
-
) {
|
|
367
|
+
const currentSpectType = isImageVariantApp(current) ? AppSpecType.OCI_IMAGE : AppSpecType.INLINE;
|
|
368
|
+
const updatedSpectType = isImageVariantApp(updated) ? AppSpecType.OCI_IMAGE : AppSpecType.INLINE;
|
|
369
|
+
if (currentSpectType !== updatedSpectType) {
|
|
479
370
|
return true;
|
|
480
371
|
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
372
|
+
switch (current.appType) {
|
|
373
|
+
case AppType.AppTypeContainer:
|
|
374
|
+
return hasContainerAppChanged(current as ContainerApplication, updated as ContainerApplication);
|
|
375
|
+
case AppType.AppTypeHelm:
|
|
376
|
+
return hasHelmAppChanged(current as HelmApplication, updated as HelmApplication);
|
|
377
|
+
case AppType.AppTypeQuadlet:
|
|
378
|
+
return hasQuadletAppChanged(current as QuadletApplication, updated as QuadletApplication, currentSpectType);
|
|
379
|
+
case AppType.AppTypeCompose:
|
|
380
|
+
return hasComposeAppChanged(current as ComposeApplication, updated as ComposeApplication, currentSpectType);
|
|
485
381
|
}
|
|
382
|
+
};
|
|
486
383
|
|
|
487
|
-
|
|
488
|
-
if (
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
384
|
+
const variablesToEnvVars = (variables: { name: string; value: string }[]) => {
|
|
385
|
+
if (variables.length === 0) {
|
|
386
|
+
return undefined;
|
|
387
|
+
}
|
|
388
|
+
return variables.reduce(
|
|
389
|
+
(acc, v) => {
|
|
390
|
+
if (v.name) {
|
|
391
|
+
acc[v.name] = v.value || '';
|
|
392
|
+
}
|
|
393
|
+
return acc;
|
|
394
|
+
},
|
|
395
|
+
{} as Record<string, string>,
|
|
396
|
+
);
|
|
397
|
+
};
|
|
493
398
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
399
|
+
/**
|
|
400
|
+
* Converts form volumes to API volumes, ignoring fields that are not allowed for the given app type.
|
|
401
|
+
* Quadlet/Compose apps --> can only be image volumes (mount is not allowed)
|
|
402
|
+
* Container apps --> can either be mount or image mount volumes
|
|
403
|
+
*/
|
|
404
|
+
const formVolumesToApi = (volumes: ApplicationVolumeForm[], appType: AppType): ApplicationVolume[] => {
|
|
405
|
+
return volumes.map((v) => {
|
|
406
|
+
const vol: Partial<ApplicationVolume & ImageMountVolumeProviderSpec> = {
|
|
407
|
+
name: v.name || '',
|
|
408
|
+
};
|
|
409
|
+
if (v.imageRef) {
|
|
410
|
+
vol.image = {
|
|
411
|
+
reference: v.imageRef,
|
|
412
|
+
pullPolicy: v.imagePullPolicy || ImagePullPolicy.PullIfNotPresent,
|
|
413
|
+
};
|
|
499
414
|
}
|
|
500
|
-
if (
|
|
501
|
-
|
|
415
|
+
if (v.mountPath && appType === AppType.AppTypeContainer) {
|
|
416
|
+
vol.mount = { path: v.mountPath };
|
|
502
417
|
}
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
418
|
+
return vol as ApplicationVolume;
|
|
419
|
+
});
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
const formFilesToApi = (files: InlineFileForm[]) =>
|
|
423
|
+
files.map((f) => ({
|
|
424
|
+
path: f.path,
|
|
425
|
+
content: f.content || '',
|
|
426
|
+
contentEncoding: f.base64 ? EncodingType.EncodingBase64 : EncodingType.EncodingPlain,
|
|
427
|
+
}));
|
|
428
|
+
|
|
429
|
+
const toFormFiles = (files: ApplicationContent[]) =>
|
|
430
|
+
files.map((file) => ({
|
|
431
|
+
path: file.path || '',
|
|
432
|
+
content: file.content || '',
|
|
433
|
+
base64: file.contentEncoding === EncodingType.EncodingBase64,
|
|
434
|
+
}));
|
|
435
|
+
|
|
436
|
+
const toApiHelmApp = (app: HelmAppForm): HelmApplication => {
|
|
437
|
+
const helmApp: HelmApplication = {
|
|
438
|
+
image: app.image,
|
|
439
|
+
appType: app.appType,
|
|
440
|
+
};
|
|
441
|
+
if (app.name) {
|
|
442
|
+
helmApp.name = app.name;
|
|
443
|
+
}
|
|
444
|
+
if (app.namespace) {
|
|
445
|
+
helmApp.namespace = app.namespace;
|
|
446
|
+
}
|
|
447
|
+
if (app.valuesYaml) {
|
|
448
|
+
try {
|
|
449
|
+
const values = yaml.load(app.valuesYaml) as Record<string, unknown>;
|
|
450
|
+
if (values && Object.keys(values).length > 0) helmApp.values = values;
|
|
451
|
+
} catch {
|
|
452
|
+
// leave values unset on invalid YAML
|
|
506
453
|
}
|
|
507
|
-
return false;
|
|
508
454
|
}
|
|
455
|
+
const fileNames = (app.valuesFiles || []).filter((f) => f.trim() !== '');
|
|
456
|
+
if (fileNames.length > 0) {
|
|
457
|
+
helmApp.valuesFiles = fileNames;
|
|
458
|
+
}
|
|
459
|
+
return helmApp;
|
|
460
|
+
};
|
|
509
461
|
|
|
510
|
-
|
|
511
|
-
|
|
462
|
+
const toApiContainerApp = (app: SingleContainerAppForm): ContainerApplication => {
|
|
463
|
+
const containerApp: ContainerApplication = {
|
|
464
|
+
image: app.image,
|
|
465
|
+
appType: app.appType,
|
|
466
|
+
runAs: app.runAs || RUN_AS_ROOT_USER,
|
|
467
|
+
envVars: variablesToEnvVars(app.variables || []),
|
|
468
|
+
volumes: formVolumesToApi(app.volumes || [], AppType.AppTypeContainer),
|
|
469
|
+
};
|
|
470
|
+
if (app.name) {
|
|
471
|
+
containerApp.name = app.name;
|
|
472
|
+
}
|
|
473
|
+
if (app.ports.length > 0) {
|
|
474
|
+
containerApp.ports = app.ports.map((p) => `${p.hostPort}:${p.containerPort}`);
|
|
512
475
|
}
|
|
513
476
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
const
|
|
518
|
-
if (
|
|
519
|
-
|
|
477
|
+
const cpu = app.cpuLimit;
|
|
478
|
+
const memory = app.memoryLimit;
|
|
479
|
+
if (cpu || memory) {
|
|
480
|
+
const limits: ApplicationResourceLimits = {};
|
|
481
|
+
if (cpu) {
|
|
482
|
+
limits.cpu = cpu;
|
|
520
483
|
}
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
if (isQuadletImageAppForm(updatedApp)) {
|
|
524
|
-
if ((currentApp.runAs || RUN_AS_DEFAULT_USER) !== (updatedApp.runAs || RUN_AS_DEFAULT_USER)) {
|
|
525
|
-
return true;
|
|
526
|
-
}
|
|
484
|
+
if (memory) {
|
|
485
|
+
limits.memory = memory;
|
|
527
486
|
}
|
|
528
487
|
|
|
529
|
-
|
|
488
|
+
containerApp.resources = { limits };
|
|
530
489
|
}
|
|
490
|
+
return containerApp;
|
|
491
|
+
};
|
|
531
492
|
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
493
|
+
const toApiComposeApp = (app: ComposeAppForm): ComposeApplication => {
|
|
494
|
+
const formApp: Partial<ComposeApplication> = {
|
|
495
|
+
appType: app.appType,
|
|
496
|
+
envVars: variablesToEnvVars(app.variables || []),
|
|
497
|
+
volumes: formVolumesToApi(app.volumes || [], app.appType),
|
|
498
|
+
};
|
|
499
|
+
if (app.name) {
|
|
500
|
+
formApp.name = app.name;
|
|
501
|
+
}
|
|
502
|
+
if (app.specType === AppSpecType.OCI_IMAGE) {
|
|
503
|
+
(formApp as ImageApplicationProviderSpec).image = app.image;
|
|
504
|
+
} else {
|
|
505
|
+
(formApp as InlineApplicationProviderSpec).inline = formFilesToApi(app.files);
|
|
506
|
+
}
|
|
507
|
+
return formApp as ComposeApplication;
|
|
508
|
+
};
|
|
509
|
+
|
|
510
|
+
// Quadlet apps are currently the same as Compose apps, plus an optional "runAs" field.
|
|
511
|
+
const toApiQuadletApp = (app: QuadletAppForm): QuadletApplication => {
|
|
512
|
+
const baseApp = toApiComposeApp(app);
|
|
513
|
+
return { ...baseApp, appType: AppType.AppTypeQuadlet, runAs: app.runAs || RUN_AS_ROOT_USER };
|
|
514
|
+
};
|
|
515
|
+
|
|
516
|
+
export const toApiApplication = (app: AppForm): ApplicationProviderSpec => {
|
|
517
|
+
switch (app.appType) {
|
|
518
|
+
case AppType.AppTypeHelm:
|
|
519
|
+
return toApiHelmApp(app as HelmAppForm);
|
|
520
|
+
case AppType.AppTypeContainer:
|
|
521
|
+
return toApiContainerApp(app as SingleContainerAppForm);
|
|
522
|
+
case AppType.AppTypeQuadlet:
|
|
523
|
+
return toApiQuadletApp(app as QuadletAppForm);
|
|
524
|
+
case AppType.AppTypeCompose:
|
|
525
|
+
return toApiComposeApp(app as ComposeAppForm);
|
|
526
|
+
default:
|
|
527
|
+
throw new Error('Unknown application type');
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
|
|
531
|
+
const toFormVariables = (envVars: Record<string, string>): { name: string; value: string }[] =>
|
|
532
|
+
Object.entries(envVars).map(([name, value]) => ({ name, value: value || '' }));
|
|
533
|
+
|
|
534
|
+
const toFormVolumes = (volumes?: ApplicationVolume[]): ApplicationVolumeForm[] => {
|
|
535
|
+
if (!volumes) return [];
|
|
536
|
+
return volumes.map((vol) => {
|
|
537
|
+
const fullVolume = vol as ApplicationVolume & ImageMountVolumeProviderSpec;
|
|
538
|
+
return {
|
|
539
|
+
name: fullVolume.name,
|
|
540
|
+
imageRef: fullVolume.image?.reference || '',
|
|
541
|
+
mountPath: fullVolume.mount?.path || '',
|
|
542
|
+
imagePullPolicy: fullVolume.image?.pullPolicy || ImagePullPolicy.PullIfNotPresent,
|
|
543
|
+
};
|
|
544
|
+
});
|
|
545
|
+
};
|
|
546
|
+
|
|
547
|
+
const toFormApps = (app: ApplicationProviderSpec): AppForm => {
|
|
548
|
+
switch (app.appType) {
|
|
549
|
+
case AppType.AppTypeContainer:
|
|
550
|
+
return toContainerAppForm(app as ContainerApplication);
|
|
551
|
+
case AppType.AppTypeHelm:
|
|
552
|
+
return toHelmAppForm(app as HelmApplication);
|
|
553
|
+
case AppType.AppTypeQuadlet:
|
|
554
|
+
return toQuadletAppForm(app as QuadletApplication);
|
|
555
|
+
case AppType.AppTypeCompose:
|
|
556
|
+
return toComposeAppForm(app as ComposeApplication);
|
|
557
|
+
default:
|
|
558
|
+
throw new Error('Unknown application type');
|
|
559
|
+
}
|
|
537
560
|
};
|
|
538
561
|
|
|
539
562
|
export const getApplicationPatches = (
|
|
540
563
|
basePath: string,
|
|
541
564
|
currentApps: ApplicationProviderSpec[],
|
|
542
565
|
updatedApps: AppForm[],
|
|
543
|
-
) => {
|
|
566
|
+
): PatchRequest => {
|
|
544
567
|
const patches: PatchRequest = [];
|
|
545
|
-
|
|
546
568
|
const currentLen = currentApps.length;
|
|
547
569
|
const newLen = updatedApps.length;
|
|
548
570
|
|
|
549
571
|
if (currentLen === 0 && newLen > 0) {
|
|
550
|
-
|
|
551
|
-
patches.push({
|
|
552
|
-
path: `${basePath}/applications`,
|
|
553
|
-
op: 'add',
|
|
554
|
-
value: updatedApps.map(toAPIApplication),
|
|
555
|
-
});
|
|
572
|
+
patches.push({ path: `${basePath}/applications`, op: 'add', value: updatedApps.map(toApiApplication) });
|
|
556
573
|
} else if (currentLen > 0 && newLen === 0) {
|
|
557
|
-
|
|
558
|
-
patches.push({
|
|
559
|
-
path: `${basePath}/applications`,
|
|
560
|
-
op: 'remove',
|
|
561
|
-
});
|
|
574
|
+
patches.push({ path: `${basePath}/applications`, op: 'remove' });
|
|
562
575
|
} else if (currentLen !== newLen) {
|
|
563
|
-
|
|
564
|
-
patches.push({
|
|
565
|
-
path: `${basePath}/applications`,
|
|
566
|
-
op: 'replace',
|
|
567
|
-
value: updatedApps.map(toAPIApplication),
|
|
568
|
-
});
|
|
576
|
+
patches.push({ path: `${basePath}/applications`, op: 'replace', value: updatedApps.map(toApiApplication) });
|
|
569
577
|
} else {
|
|
570
|
-
// Apps length has not changed. We only PATCH the applications that have actually changed
|
|
571
578
|
currentApps.forEach((currentApp, index) => {
|
|
572
579
|
const updatedApp = updatedApps[index];
|
|
573
|
-
|
|
580
|
+
const updatedApi = toApiApplication(updatedApp);
|
|
581
|
+
if (hasApplicationChanged(currentApp, updatedApi)) {
|
|
574
582
|
patches.push({
|
|
575
583
|
path: `${basePath}/applications/${index}`,
|
|
576
584
|
op: 'replace',
|
|
577
|
-
value:
|
|
585
|
+
value: updatedApi,
|
|
578
586
|
});
|
|
579
587
|
}
|
|
580
588
|
});
|
|
581
589
|
}
|
|
582
|
-
|
|
583
590
|
return patches;
|
|
584
591
|
};
|
|
585
592
|
|
|
@@ -635,45 +642,16 @@ export const getApiConfig = (ct: SpecConfigTemplate): ConfigSourceProvider => {
|
|
|
635
642
|
};
|
|
636
643
|
};
|
|
637
644
|
|
|
638
|
-
const
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
base64: file.contentEncoding === EncodingType.EncodingBase64,
|
|
646
|
-
}));
|
|
647
|
-
};
|
|
648
|
-
|
|
649
|
-
const toAPIFiles = (files: ComposeInlineAppForm['files']) => {
|
|
650
|
-
return files.map((file) => ({
|
|
651
|
-
path: file.path,
|
|
652
|
-
content: file.content || '',
|
|
653
|
-
contentEncoding: file.base64 ? EncodingType.EncodingBase64 : EncodingType.EncodingPlain,
|
|
654
|
-
}));
|
|
655
|
-
};
|
|
656
|
-
|
|
657
|
-
const convertVolumesToForm = (volumes?: ApplicationVolume[]) => {
|
|
658
|
-
if (!volumes) return [];
|
|
659
|
-
return volumes.map((vol) => {
|
|
660
|
-
const fullVolume = vol as ApplicationVolume & ImageMountVolumeProviderSpec;
|
|
661
|
-
const volForm: ApplicationVolumeForm = {
|
|
662
|
-
name: fullVolume.name,
|
|
663
|
-
imageRef: fullVolume.image?.reference || '',
|
|
664
|
-
mountPath: fullVolume.mount?.path || '',
|
|
665
|
-
};
|
|
666
|
-
// Only set imagePullPolicy if there's an image
|
|
667
|
-
if (fullVolume.image) {
|
|
668
|
-
volForm.imagePullPolicy = fullVolume.image.pullPolicy || ImagePullPolicy.PullIfNotPresent;
|
|
669
|
-
}
|
|
670
|
-
return volForm;
|
|
671
|
-
});
|
|
645
|
+
const getRunAsUser = (app: ContainerApplication | QuadletApplication | undefined): string => {
|
|
646
|
+
if (app) {
|
|
647
|
+
// Existing apps that don't have a "runAs" user are actually running as the "root" user.
|
|
648
|
+
return app.runAs || RUN_AS_ROOT_USER;
|
|
649
|
+
}
|
|
650
|
+
// For new applications, we want to promote "flightctl" as the default user.
|
|
651
|
+
return RUN_AS_FLIGHTCTL_USER;
|
|
672
652
|
};
|
|
673
653
|
|
|
674
|
-
const
|
|
675
|
-
containerApp: (ApplicationProviderSpec & ImageApplicationProviderSpec) | undefined,
|
|
676
|
-
): SingleContainerAppForm => {
|
|
654
|
+
const toContainerAppForm = (containerApp: ContainerApplication | undefined): SingleContainerAppForm => {
|
|
677
655
|
const ports =
|
|
678
656
|
containerApp?.ports?.map((portString) => {
|
|
679
657
|
const [hostPort, containerPort] = portString.split(':');
|
|
@@ -681,136 +659,94 @@ const createContainerApp = (
|
|
|
681
659
|
}) || [];
|
|
682
660
|
|
|
683
661
|
const limits = containerApp?.resources?.limits;
|
|
662
|
+
|
|
684
663
|
return {
|
|
685
664
|
appType: AppType.AppTypeContainer,
|
|
686
665
|
specType: AppSpecType.OCI_IMAGE,
|
|
687
666
|
name: containerApp?.name || '',
|
|
688
667
|
image: containerApp?.image || '',
|
|
689
|
-
variables:
|
|
690
|
-
volumes:
|
|
668
|
+
variables: toFormVariables(containerApp?.envVars || {}),
|
|
669
|
+
volumes: toFormVolumes(containerApp?.volumes),
|
|
691
670
|
ports,
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
memory: limits.memory || '',
|
|
696
|
-
}
|
|
697
|
-
: undefined,
|
|
698
|
-
runAs: containerApp?.runAs || RUN_AS_DEFAULT_USER,
|
|
671
|
+
cpuLimit: limits?.cpu || '',
|
|
672
|
+
memoryLimit: limits?.memory || '',
|
|
673
|
+
runAs: getRunAsUser(containerApp),
|
|
699
674
|
};
|
|
700
675
|
};
|
|
701
676
|
|
|
702
|
-
const
|
|
703
|
-
|
|
704
|
-
): HelmImageAppForm => {
|
|
677
|
+
const toHelmAppForm = (helmApp: HelmApplication | undefined): HelmAppForm => {
|
|
678
|
+
// We want to always show at least one values file field, even when no files have been added yet.
|
|
705
679
|
const values = helmApp?.values || {};
|
|
680
|
+
const valuesFiles = helmApp?.valuesFiles?.length ? helmApp.valuesFiles : [''];
|
|
681
|
+
const valuesYaml = Object.keys(values || {}).length > 0 ? yaml.dump(values) : '';
|
|
682
|
+
|
|
706
683
|
return {
|
|
707
684
|
appType: AppType.AppTypeHelm,
|
|
708
685
|
specType: AppSpecType.OCI_IMAGE,
|
|
709
686
|
name: helmApp?.name || '',
|
|
710
687
|
image: helmApp?.image || '',
|
|
711
|
-
namespace: helmApp?.namespace,
|
|
712
|
-
valuesYaml
|
|
713
|
-
valuesFiles
|
|
688
|
+
namespace: helmApp?.namespace || '',
|
|
689
|
+
valuesYaml,
|
|
690
|
+
valuesFiles,
|
|
714
691
|
};
|
|
715
692
|
};
|
|
716
693
|
|
|
717
|
-
const
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
appType: AppType.
|
|
722
|
-
specType
|
|
723
|
-
name:
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
volumes: convertVolumesToForm(quadletApp?.volumes),
|
|
727
|
-
runAs: quadletApp?.runAs || RUN_AS_DEFAULT_USER,
|
|
694
|
+
const toComposeAppForm = (app: ComposeApplication | undefined): ComposeAppForm => {
|
|
695
|
+
const isInlineVariant = app && isInlineVariantApp(app);
|
|
696
|
+
const specType = isInlineVariant ? AppSpecType.INLINE : AppSpecType.OCI_IMAGE;
|
|
697
|
+
const formApp: Partial<QuadletAppForm | ComposeAppForm> = {
|
|
698
|
+
appType: AppType.AppTypeCompose,
|
|
699
|
+
specType,
|
|
700
|
+
name: app?.name || '',
|
|
701
|
+
variables: toFormVariables(app?.envVars || {}),
|
|
702
|
+
volumes: toFormVolumes(app?.volumes),
|
|
728
703
|
};
|
|
729
|
-
};
|
|
730
704
|
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
volumes: convertVolumesToForm(quadletApp?.volumes),
|
|
741
|
-
runAs: quadletApp?.runAs || RUN_AS_DEFAULT_USER,
|
|
742
|
-
};
|
|
705
|
+
// We want to have both fields initialized for the formik form
|
|
706
|
+
if (isInlineVariant) {
|
|
707
|
+
formApp.files = toFormFiles(app?.inline || []);
|
|
708
|
+
formApp.image = '';
|
|
709
|
+
} else {
|
|
710
|
+
formApp.image = app?.image || '';
|
|
711
|
+
formApp.files = [];
|
|
712
|
+
}
|
|
713
|
+
return formApp as ComposeAppForm;
|
|
743
714
|
};
|
|
744
715
|
|
|
745
|
-
const
|
|
746
|
-
|
|
747
|
-
): ComposeImageAppForm => {
|
|
748
|
-
return {
|
|
749
|
-
appType: AppType.AppTypeCompose,
|
|
750
|
-
specType: AppSpecType.OCI_IMAGE,
|
|
751
|
-
name: composeApp?.name || '',
|
|
752
|
-
image: composeApp?.image || '',
|
|
753
|
-
variables: getAppFormVariables(composeApp?.envVars),
|
|
754
|
-
volumes: convertVolumesToForm(composeApp?.volumes),
|
|
755
|
-
};
|
|
756
|
-
};
|
|
716
|
+
const toQuadletAppForm = (app: QuadletApplication | undefined): QuadletAppForm => {
|
|
717
|
+
const baseApp = toComposeAppForm(app);
|
|
757
718
|
|
|
758
|
-
const createComposeInlineApp = (
|
|
759
|
-
composeApp: (ApplicationProviderSpec & InlineApplicationProviderSpec) | undefined,
|
|
760
|
-
): ComposeInlineAppForm => {
|
|
761
719
|
return {
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
files: toFormFiles(composeApp?.inline || []),
|
|
766
|
-
variables: getAppFormVariables(composeApp?.envVars),
|
|
767
|
-
volumes: convertVolumesToForm(composeApp?.volumes),
|
|
720
|
+
...baseApp,
|
|
721
|
+
appType: AppType.AppTypeQuadlet,
|
|
722
|
+
runAs: getRunAsUser(app),
|
|
768
723
|
};
|
|
769
724
|
};
|
|
770
725
|
|
|
771
|
-
export const createInitialAppForm = (appType: AppType,
|
|
726
|
+
export const createInitialAppForm = (appType: AppType, name: string = ''): AppForm => {
|
|
772
727
|
let app: AppForm;
|
|
773
728
|
switch (appType) {
|
|
774
729
|
case AppType.AppTypeContainer:
|
|
775
|
-
app =
|
|
730
|
+
app = toContainerAppForm(undefined);
|
|
776
731
|
break;
|
|
777
732
|
case AppType.AppTypeHelm:
|
|
778
|
-
app =
|
|
733
|
+
app = toHelmAppForm(undefined);
|
|
779
734
|
break;
|
|
780
735
|
case AppType.AppTypeQuadlet:
|
|
781
|
-
app =
|
|
736
|
+
app = toQuadletAppForm(undefined);
|
|
782
737
|
break;
|
|
783
738
|
case AppType.AppTypeCompose:
|
|
784
|
-
app =
|
|
739
|
+
app = toComposeAppForm(undefined);
|
|
785
740
|
break;
|
|
741
|
+
default:
|
|
742
|
+
throw new Error('Unknown application type');
|
|
786
743
|
}
|
|
787
744
|
app.name = name;
|
|
788
745
|
return app;
|
|
789
746
|
};
|
|
790
747
|
|
|
791
|
-
export const getApplicationValues = (deviceSpec?: DeviceSpec): AppForm[] =>
|
|
792
|
-
|
|
793
|
-
return apps.map((app) => {
|
|
794
|
-
if (!app.appType) {
|
|
795
|
-
throw new Error('Application appType is required');
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
switch (app.appType) {
|
|
799
|
-
case AppType.AppTypeContainer:
|
|
800
|
-
return createContainerApp(app as ApplicationProviderSpec & ImageApplicationProviderSpec);
|
|
801
|
-
case AppType.AppTypeHelm:
|
|
802
|
-
return createHelmApp(app as ApplicationProviderSpec & ImageApplicationProviderSpec);
|
|
803
|
-
case AppType.AppTypeQuadlet:
|
|
804
|
-
return isImageAppProvider(app)
|
|
805
|
-
? createQuadletImageApp(app)
|
|
806
|
-
: createQuadletInlineApp(app as ApplicationProviderSpec & InlineApplicationProviderSpec & { runAs?: string });
|
|
807
|
-
case AppType.AppTypeCompose:
|
|
808
|
-
return isImageAppProvider(app)
|
|
809
|
-
? createComposeImageApp(app)
|
|
810
|
-
: createComposeInlineApp(app as ApplicationProviderSpec & InlineApplicationProviderSpec);
|
|
811
|
-
}
|
|
812
|
-
});
|
|
813
|
-
};
|
|
748
|
+
export const getApplicationValues = (deviceSpec?: DeviceSpec): AppForm[] =>
|
|
749
|
+
(deviceSpec?.applications || []).map(toFormApps);
|
|
814
750
|
|
|
815
751
|
export const getSystemdUnitsValues = (deviceSpec?: DeviceSpec): SystemdUnitFormValue[] => {
|
|
816
752
|
return (
|