Add ha to cloud manual upload

This commit is contained in:
SebClem 2024-07-22 11:20:43 +02:00
parent e5fa3e576f
commit d9aace4197
Signed by: sebclem
GPG Key ID: 5A4308F6A359EA50
5 changed files with 99 additions and 4 deletions

View File

@ -1,5 +1,7 @@
import express from "express"; import express from "express";
import * as haOsService from "../services/homeAssistantService.js"; import * as haOsService from "../services/homeAssistantService.js";
import { uploadToCloud } from "../services/orchestrator.js";
import logger from "../config/winston.js";
const homeAssistantRouter = express.Router(); const homeAssistantRouter = express.Router();
@ -29,6 +31,17 @@ homeAssistantRouter.get("/backup/:slug", (req, res) => {
}); });
}); });
homeAssistantRouter.post("/backup/:slug/upload", (req, res) => {
uploadToCloud(req.params.slug)
.then(() => {
logger.info("All good !");
})
.catch(() => {
logger.error("Something wrong !");
});
res.sendStatus(202);
});
homeAssistantRouter.get("/addons", (req, res) => { homeAssistantRouter.get("/addons", (req, res) => {
haOsService haOsService
.getAddonList() .getAddonList()

View File

@ -4,7 +4,10 @@ import logger from "../config/winston.js";
import messageManager from "../tools/messageManager.js"; import messageManager from "../tools/messageManager.js";
import * as statusTools from "../tools/status.js"; import * as statusTools from "../tools/status.js";
import { BackupType } from "../types/services/backupConfig.js"; import { BackupType } from "../types/services/backupConfig.js";
import type { AddonModel } from "../types/services/ha_os_response.js"; import type {
AddonModel,
BackupDetailModel,
} from "../types/services/ha_os_response.js";
import { WorkflowType } from "../types/services/orchecstrator.js"; import { WorkflowType } from "../types/services/orchecstrator.js";
import * as backupConfigService from "./backupConfigService.js"; import * as backupConfigService from "./backupConfigService.js";
import * as homeAssistantService from "./homeAssistantService.js"; import * as homeAssistantService from "./homeAssistantService.js";
@ -89,7 +92,10 @@ export function doBackupWorkflow(type: WorkflowType) {
}) })
.then(() => { .then(() => {
logger.info("Backup workflow finished successfully !"); logger.info("Backup workflow finished successfully !");
messageManager.info("Backup workflow finished successfully !"); messageManager.info(
"Backup workflow finished successfully !",
`name: ${name}`
);
const status = statusTools.getStatus(); const status = statusTools.getStatus();
status.last_backup.success = true; status.last_backup.success = true;
status.last_backup.last_try = DateTime.now(); status.last_backup.last_try = DateTime.now();
@ -105,6 +111,55 @@ export function doBackupWorkflow(type: WorkflowType) {
}); });
} }
export function uploadToCloud(slug: string) {
const webdavConfig = getWebdavConfig();
let tmpBackupFile = "";
let backupInfo = {} as BackupDetailModel;
return webDavService
.checkWebdavLogin(webdavConfig)
.then(() => {
return homeAssistantService.getBackupInfo(slug);
})
.then((response) => {
backupInfo = response.body.data;
return homeAssistantService.downloadSnapshot(slug);
})
.then((tmpFile) => {
tmpBackupFile = tmpFile;
if (webdavConfig.chunckedUpload) {
return webDavService.chunkedUpload(
tmpFile,
getBackupFolder(WorkflowType.MANUAL, webdavConfig) +
backupInfo.name +
".tar",
webdavConfig
);
} else {
return webDavService.webdavUploadFile(
tmpFile,
getBackupFolder(WorkflowType.MANUAL, webdavConfig) +
backupInfo.name +
".tar",
webdavConfig
);
}
})
.then(() => {
logger.info(`Successfully uploaded ${backupInfo.name} to cloud.`);
messageManager.info(
"Successfully uploaded backup to cloud.",
`Name: ${backupInfo.name}`
);
})
.catch(() => {
if (tmpBackupFile != "") {
unlinkSync(tmpBackupFile);
}
return Promise.reject(new Error());
});
}
// This methods remove addon that are no installed in HA from the conf array // This methods remove addon that are no installed in HA from the conf array
function sanitizeAddonList(addonInConf: string[], addonInHA: AddonModel[]) { function sanitizeAddonList(addonInConf: string[], addonInHA: AddonModel[]) {
return addonInConf.filter((value) => addonInHA.some((v) => v.slug == value)); return addonInConf.filter((value) => addonInHA.some((v) => v.slug == value));

View File

@ -37,6 +37,7 @@
:key="item.slug" :key="item.slug"
:item="item" :item="item"
:index="index" :index="index"
@upload="upload"
> >
</ha-list-item> </ha-list-item>
</v-list> </v-list>
@ -52,12 +53,18 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { BackupModel } from "@/types/homeAssistant"; import type { BackupModel } from "@/types/homeAssistant";
import { ref, onBeforeUnmount } from "vue"; import { ref, onBeforeUnmount } from "vue";
import { getBackups } from "@/services/homeAssistantService"; import {
getBackups,
uploadHomeAssistantBackup,
} from "@/services/homeAssistantService";
import HaListItem from "./HaListItem.vue"; import HaListItem from "./HaListItem.vue";
import { useAlertStore } from "@/store/alert";
const backups = ref<BackupModel[]>([]); const backups = ref<BackupModel[]>([]);
const loading = ref<boolean>(true); const loading = ref<boolean>(true);
const alertStore = useAlertStore();
function refreshBackup() { function refreshBackup() {
loading.value = true; loading.value = true;
getBackups() getBackups()
@ -70,6 +77,16 @@ function refreshBackup() {
}); });
} }
function upload(item: BackupModel) {
uploadHomeAssistantBackup(item.slug)
.then(() => {
alertStore.add("success", "Backup upload as started.");
})
.catch(() => {
alertStore.add("error", "Fail to start backup upload !");
});
}
refreshBackup(); refreshBackup();
defineExpose({ refreshBackup }); defineExpose({ refreshBackup });

View File

@ -156,7 +156,12 @@
<v-card-actions class="justify-center"> <v-card-actions class="justify-center">
<v-tooltip text="Upload to Cloud" location="bottom"> <v-tooltip text="Upload to Cloud" location="bottom">
<template v-slot:activator="{ props }"> <template v-slot:activator="{ props }">
<v-btn variant="outlined" color="success" v-bind="props"> <v-btn
variant="outlined"
color="success"
v-bind="props"
@click="emits('upload', item)"
>
<v-icon>mdi-cloud-upload</v-icon> <v-icon>mdi-cloud-upload</v-icon>
</v-btn> </v-btn>
</template> </template>
@ -193,5 +198,6 @@ watch(detail, (value) => {
const emits = defineEmits<{ const emits = defineEmits<{
(e: "delete", item: BackupModel): void; (e: "delete", item: BackupModel): void;
(e: "upload", item: BackupModel): void;
}>(); }>();
</script> </script>

View File

@ -21,3 +21,7 @@ export function getBackups() {
export function getBackupDetail(slug: string) { export function getBackupDetail(slug: string) {
return kyClient.get(`homeAssistant/backup/${slug}`).json<BackupDetailModel>(); return kyClient.get(`homeAssistant/backup/${slug}`).json<BackupDetailModel>();
} }
export function uploadHomeAssistantBackup(slug: string) {
return kyClient.post(`homeAssistant/backup/${slug}/upload`);
}