mirror of
https://github.com/IceWhaleTech/CasaOS.git
synced 2025-12-23 21:14:41 +00:00
Compare commits
368 Commits
v0.2.1
...
v0.4.1-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b9946db854 | ||
|
|
9eb650b444 | ||
|
|
84f17b4c4b | ||
|
|
8cff99f726 | ||
|
|
ea166f890b | ||
|
|
d350c3e96f | ||
|
|
ec0d98627d | ||
|
|
fd3cb5b0f0 | ||
|
|
0155dc1877 | ||
|
|
cd79e51f8f | ||
|
|
c6d89f9cb2 | ||
|
|
4b26631374 | ||
|
|
ba742b9fb2 | ||
|
|
57e5a710e0 | ||
|
|
062d95c1eb | ||
|
|
75643287a5 | ||
|
|
6bda9406fb | ||
|
|
be9a010d17 | ||
|
|
3875827b7a | ||
|
|
5338d4662e | ||
|
|
3b9c4b62c5 | ||
|
|
536eac788d | ||
|
|
fc371bf068 | ||
|
|
299b20a087 | ||
|
|
eb31bf5586 | ||
|
|
04d4eacc60 | ||
|
|
60608c5dc7 | ||
|
|
b582e8f53e | ||
|
|
5690ccc1b5 | ||
|
|
13c2967889 | ||
|
|
8a37f9c879 | ||
|
|
96e9284235 | ||
|
|
06f83d3d68 | ||
|
|
438b8a1dd2 | ||
|
|
29e701cb7c | ||
|
|
43cc7596d2 | ||
|
|
11f800d138 | ||
|
|
a58a9e5477 | ||
|
|
5f015e9038 | ||
|
|
3922296d9b | ||
|
|
908a16ace4 | ||
|
|
f7a3863720 | ||
|
|
e94c2ff5c5 | ||
|
|
89487eb5db | ||
|
|
0fb5cab480 | ||
|
|
f210f29ae5 | ||
|
|
7bd5c6a2b4 | ||
|
|
230f1585a3 | ||
|
|
ca967ec59c | ||
|
|
c0b3260a6c | ||
|
|
9ed82cd55e | ||
|
|
381fb85b1d | ||
|
|
2beb1c0d82 | ||
|
|
772c3e0bc0 | ||
|
|
bcda992322 | ||
|
|
8cec47e4db | ||
|
|
87de9cec0a | ||
|
|
6d47d4ff18 | ||
|
|
4bb81e4669 | ||
|
|
c05d837350 | ||
|
|
8908c39969 | ||
|
|
df0f015944 | ||
|
|
46a37f0510 | ||
|
|
6ea3cdb364 | ||
|
|
be80d0cd95 | ||
|
|
296e88d099 | ||
|
|
b61a3db611 | ||
|
|
0f3d3e82f5 | ||
|
|
dd66f73157 | ||
|
|
cbbb907d6a | ||
|
|
ff6cdb6fda | ||
|
|
2eac040875 | ||
|
|
b41d855f73 | ||
|
|
182bc25343 | ||
|
|
12d5e5db03 | ||
|
|
455d226dcd | ||
|
|
f0448cd1b9 | ||
|
|
aff18fa091 | ||
|
|
80c347ac01 | ||
|
|
8113f51cf7 | ||
|
|
4f491fa22f | ||
|
|
3935489d8b | ||
|
|
d14381e6a2 | ||
|
|
42ebd5f325 | ||
|
|
a51bf70b79 | ||
|
|
3787c7bf99 | ||
|
|
ec7f6573ad | ||
|
|
50d68f3f76 | ||
|
|
d9c6a5c875 | ||
|
|
4bace9b16a | ||
|
|
84dfa7f5bf | ||
|
|
582f85c3ba | ||
|
|
7f4562629a | ||
|
|
4776b76b16 | ||
|
|
466350dd21 | ||
|
|
fb39529e8f | ||
|
|
4434ba522b | ||
|
|
aac8fe85ba | ||
|
|
9f938f65b1 | ||
|
|
314dbdab57 | ||
|
|
4ccae3f67f | ||
|
|
9f2e8dae6f | ||
|
|
727aca564b | ||
|
|
70ba4d5e3d | ||
|
|
8d088afcc5 | ||
|
|
34f35bbf20 | ||
|
|
b6f413b9e9 | ||
|
|
091be6d12e | ||
|
|
aefa68d8f8 | ||
|
|
9aed323d8d | ||
|
|
eba607fc53 | ||
|
|
d064f20a04 | ||
|
|
079e431d33 | ||
|
|
cee34ec1c2 | ||
|
|
848ee63386 | ||
|
|
c12c6cc940 | ||
|
|
f31fb22039 | ||
|
|
a5133bdbfa | ||
|
|
1902b2d4f2 | ||
|
|
fc5e351f0b | ||
|
|
7f642a7a4c | ||
|
|
c36a046a15 | ||
|
|
8b2c9486da | ||
|
|
ce5ecfcf84 | ||
|
|
bd1a2f5751 | ||
|
|
d2e0695d73 | ||
|
|
8cd18c3218 | ||
|
|
cc0ba82c92 | ||
|
|
ddca242d23 | ||
|
|
eaa07ba95a | ||
|
|
39a4c29680 | ||
|
|
af6900b1c7 | ||
|
|
9ec43a7691 | ||
|
|
bd85cda9fa | ||
|
|
94eaba6ecb | ||
|
|
e207c9c75f | ||
|
|
81d3293991 | ||
|
|
364fbf01f5 | ||
|
|
87e66aae8a | ||
|
|
3a60db3729 | ||
|
|
d3f78b52fa | ||
|
|
7d67a66d6b | ||
|
|
cb9e1b9dd9 | ||
|
|
dc8282acbb | ||
|
|
cf6103a2b5 | ||
|
|
6f98995e7d | ||
|
|
5cc41fa040 | ||
|
|
cb289f5b8a | ||
|
|
1377d55407 | ||
|
|
06eca38022 | ||
|
|
c47c1e548c | ||
|
|
552ec4849d | ||
|
|
7386a9dce3 | ||
|
|
b2b1daf5ab | ||
|
|
bbc0181e23 | ||
|
|
c23bd3f3a3 | ||
|
|
8a1839c02e | ||
|
|
164bf66190 | ||
|
|
a4c2a4b992 | ||
|
|
e7e82e6ca3 | ||
|
|
574295470e | ||
|
|
b1061f19ad | ||
|
|
bdd9eaca9f | ||
|
|
ec4c672924 | ||
|
|
5d4717de4d | ||
|
|
e2de783152 | ||
|
|
09f68f4034 | ||
|
|
cec83fc048 | ||
|
|
33e1d8a806 | ||
|
|
2a8dafae28 | ||
|
|
a426b56306 | ||
|
|
6202d38bdb | ||
|
|
4626ceb048 | ||
|
|
1e7333118c | ||
|
|
9758436a1e | ||
|
|
ed67e977b7 | ||
|
|
b0b1b5e262 | ||
|
|
2796c37bf6 | ||
|
|
d48e24f652 | ||
|
|
3a8cf593d9 | ||
|
|
0ffa2f901a | ||
|
|
bd73141ddf | ||
|
|
346b0f5d97 | ||
|
|
d4b4b75012 | ||
|
|
cb33ffbb46 | ||
|
|
85188d0b05 | ||
|
|
1e60c26920 | ||
|
|
752134942a | ||
|
|
faf683a02c | ||
|
|
f99f49dd7e | ||
|
|
b0dc30277b | ||
|
|
d91fef0a19 | ||
|
|
6bb044ab04 | ||
|
|
78479f9604 | ||
|
|
8fe893847f | ||
|
|
f506d6ce49 | ||
|
|
5d7c5ba120 | ||
|
|
eedffd7c19 | ||
|
|
0885c1386d | ||
|
|
0297fe67af | ||
|
|
3f53e6f33b | ||
|
|
94d0efdb12 | ||
|
|
1e821d1c10 | ||
|
|
2c80b53ee8 | ||
|
|
c33af66c6e | ||
|
|
9d47874ae3 | ||
|
|
c7b7a30210 | ||
|
|
fde665cd4d | ||
|
|
eaf2341a2a | ||
|
|
d4bed3e5c7 | ||
|
|
fcb2b3f5a5 | ||
|
|
60349c941a | ||
|
|
11bc70a710 | ||
|
|
665766019f | ||
|
|
57cef9624c | ||
|
|
6bd41ad016 | ||
|
|
05425d638f | ||
|
|
bd5a2e35d4 | ||
|
|
123e7e8758 | ||
|
|
1ec3e2e9fb | ||
|
|
0719c3cc0c | ||
|
|
0a4ceb7c4c | ||
|
|
655f59f00a | ||
|
|
5289f471d6 | ||
|
|
59597befb6 | ||
|
|
df2477a12f | ||
|
|
b709abe682 | ||
|
|
d0f3dc806e | ||
|
|
92d085acf9 | ||
|
|
20dbae21c8 | ||
|
|
9258cb4b9e | ||
|
|
d9794851f9 | ||
|
|
1fcb530ff2 | ||
|
|
364d411438 | ||
|
|
0dacc5db12 | ||
|
|
fcbff194d2 | ||
|
|
04e93b0e3c | ||
|
|
2eff7fa8bc | ||
|
|
dd0645ee0f | ||
|
|
c93aa6286e | ||
|
|
bf7b32309f | ||
|
|
cd779448ce | ||
|
|
c3b2c1d599 | ||
|
|
b7949e100f | ||
|
|
80d24570d6 | ||
|
|
539b72a388 | ||
|
|
a7d15a896e | ||
|
|
9796c5aad7 | ||
|
|
892cd99eb3 | ||
|
|
02cb4cd392 | ||
|
|
9213f9e379 | ||
|
|
4473056d5c | ||
|
|
07e96511cd | ||
|
|
ce1dc52bc2 | ||
|
|
d890b16644 | ||
|
|
5737936318 | ||
|
|
33acfababd | ||
|
|
28c1a52171 | ||
|
|
892eef424c | ||
|
|
f3c73ba79b | ||
|
|
c6928c333d | ||
|
|
63c6c2cebb | ||
|
|
6cba025679 | ||
|
|
d25b93c972 | ||
|
|
b14861703c | ||
|
|
32604225ce | ||
|
|
f623b29c38 | ||
|
|
94ae6ee8ec | ||
|
|
5115bf72e1 | ||
|
|
e1a928cd78 | ||
|
|
3977519c43 | ||
|
|
2f87834ac9 | ||
|
|
53335012d8 | ||
|
|
9d6302f7e3 | ||
|
|
20950e2a60 | ||
|
|
0e0e507f8f | ||
|
|
46e14617b6 | ||
|
|
903c73fafb | ||
|
|
42a56df4a5 | ||
|
|
493dc5c032 | ||
|
|
9a73bc2a18 | ||
|
|
55a9acd9f6 | ||
|
|
d060968b7a | ||
|
|
88a7f53130 | ||
|
|
26e5b18a5d | ||
|
|
011ace96f6 | ||
|
|
5c00655d14 | ||
|
|
eb36c262db | ||
|
|
29d1861545 | ||
|
|
3c9b410693 | ||
|
|
4c3b41433b | ||
|
|
1fd13668c0 | ||
|
|
d1ab7261a6 | ||
|
|
0fc65bcb3a | ||
|
|
f1ce8bfd99 | ||
|
|
3f472f1864 | ||
|
|
229d94cae7 | ||
|
|
c28e1bbf93 | ||
|
|
a840029000 | ||
|
|
aad2646cf2 | ||
|
|
ca1f8ad73e | ||
|
|
dea02763a2 | ||
|
|
ea67385a64 | ||
|
|
fa2daa2767 | ||
|
|
fcb906aa85 | ||
|
|
489a617126 | ||
|
|
601e7ce10b | ||
|
|
4a6fc9a945 | ||
|
|
b377af1d24 | ||
|
|
3fc00f8da7 | ||
|
|
6e39fe5f8c | ||
|
|
20c240a123 | ||
|
|
3ea9fc0de0 | ||
|
|
b80b08ef07 | ||
|
|
505af8d101 | ||
|
|
ae35a6d291 | ||
|
|
2b95c07a47 | ||
|
|
27a011e715 | ||
|
|
476831a12f | ||
|
|
9675eff69e | ||
|
|
85a044246e | ||
|
|
5c41fbcf3d | ||
|
|
6baab7a525 | ||
|
|
ab3b5a9077 | ||
|
|
5811c271b2 | ||
|
|
cf5387346d | ||
|
|
8df63c6c5c | ||
|
|
1d17d27c96 | ||
|
|
bdcbae69a5 | ||
|
|
cdbc3437be | ||
|
|
8940b520e0 | ||
|
|
1d62fbd670 | ||
|
|
a0b56d809e | ||
|
|
f1f6d33e26 | ||
|
|
f292edd2ba | ||
|
|
caa9b50b65 | ||
|
|
61b824065b | ||
|
|
9a900b2ca0 | ||
|
|
4c1cbc98a4 | ||
|
|
8660b95756 | ||
|
|
e7ebdc040f | ||
|
|
6c235d3f2a | ||
|
|
997d912f4d | ||
|
|
2508a4e07d | ||
|
|
90b997337c | ||
|
|
0bb3c92335 | ||
|
|
7fd539c57e | ||
|
|
52bd22ab2b | ||
|
|
46e9458e82 | ||
|
|
3f5595e794 | ||
|
|
d22cc7d3f6 | ||
|
|
eb03a3e6c7 | ||
|
|
65cc1f4752 | ||
|
|
99db197a39 | ||
|
|
7e2a5d553c | ||
|
|
f02337b83b | ||
|
|
f66b67b0c9 | ||
|
|
91087b5341 | ||
|
|
c67191d8c2 | ||
|
|
0fac461783 | ||
|
|
ec5bc922e7 | ||
|
|
7194792c3f | ||
|
|
76c8bade7f | ||
|
|
126857fab0 | ||
|
|
9ca57e105e | ||
|
|
2651140095 | ||
|
|
14175bc438 | ||
|
|
956328da86 |
197
.all-contributorsrc
Normal file
197
.all-contributorsrc
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"README.md"
|
||||||
|
],
|
||||||
|
"imageSize": 100,
|
||||||
|
"badgeTemplate": "<a href=\"#credits\"><img alt=\"All Contributors\" src=\"https://img.shields.io/static/v1?label=All%20Contributors&message=<%= contributors.length %>&color=162453&style=flat-square&logo=Handshake&logoColor=fff\" /></a>",
|
||||||
|
"commit": false,
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"login": "jerrykuku",
|
||||||
|
"name": "老竭力",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/9485680?v=4",
|
||||||
|
"profile": "https://github.com/jerrykuku",
|
||||||
|
"contributions": [
|
||||||
|
"code",
|
||||||
|
"doc",
|
||||||
|
"ideas",
|
||||||
|
"infra",
|
||||||
|
"maintenance",
|
||||||
|
"platform",
|
||||||
|
"question",
|
||||||
|
"review"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "LinkLeong",
|
||||||
|
"name": "link",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/13556972?v=4",
|
||||||
|
"profile": "https://github.com/LinkLeong",
|
||||||
|
"contributions": [
|
||||||
|
"code",
|
||||||
|
"doc",
|
||||||
|
"ideas",
|
||||||
|
"infra",
|
||||||
|
"maintenance",
|
||||||
|
"question",
|
||||||
|
"review"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "tigerinus",
|
||||||
|
"name": "Tiger Wang (王豫)",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/7172560?v=4",
|
||||||
|
"profile": "https://github.com/tigerinus",
|
||||||
|
"contributions": [
|
||||||
|
"code",
|
||||||
|
"doc",
|
||||||
|
"ideas",
|
||||||
|
"infra",
|
||||||
|
"maintenance",
|
||||||
|
"mentoring",
|
||||||
|
"security",
|
||||||
|
"question",
|
||||||
|
"review"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "Lauren-ED209",
|
||||||
|
"name": "Lauren",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/8243355?v=4",
|
||||||
|
"profile": "https://github.com/Lauren-ED209",
|
||||||
|
"contributions": [
|
||||||
|
"ideas",
|
||||||
|
"fundingFinding",
|
||||||
|
"projectManagement",
|
||||||
|
"question",
|
||||||
|
"test"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "JohnGuan",
|
||||||
|
"name": "John Guan",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/3358477?v=4",
|
||||||
|
"profile": "https://JohnGuan.Cn",
|
||||||
|
"contributions": [
|
||||||
|
"blog",
|
||||||
|
"content",
|
||||||
|
"doc",
|
||||||
|
"ideas",
|
||||||
|
"eventOrganizing",
|
||||||
|
"mentoring",
|
||||||
|
"question",
|
||||||
|
"review"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "dtaivpp",
|
||||||
|
"name": "David Tippett",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/17506770?v=4",
|
||||||
|
"profile": "https://blog.tippybits.com",
|
||||||
|
"contributions": [
|
||||||
|
"doc",
|
||||||
|
"ideas",
|
||||||
|
"question"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "zarevskaya",
|
||||||
|
"name": "Skaya",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/60230221?v=4",
|
||||||
|
"profile": "https://github.com/zarevskaya",
|
||||||
|
"contributions": [
|
||||||
|
"mentoring",
|
||||||
|
"question",
|
||||||
|
"tutorial",
|
||||||
|
"translation"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "AuthorShin",
|
||||||
|
"name": "AuthorShin",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/4959043?v=4",
|
||||||
|
"profile": "https://github.com/AuthorShin",
|
||||||
|
"contributions": [
|
||||||
|
"test",
|
||||||
|
"bug",
|
||||||
|
"question",
|
||||||
|
"ideas"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "baptiste313",
|
||||||
|
"name": "baptiste313",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/93325157?v=4",
|
||||||
|
"profile": "https://github.com/baptiste313",
|
||||||
|
"contributions": [
|
||||||
|
"translation"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "DrMxrcy",
|
||||||
|
"name": "DrMxrcy",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/58747968?v=4",
|
||||||
|
"profile": "https://github.com/DrMxrcy",
|
||||||
|
"contributions": [
|
||||||
|
"test",
|
||||||
|
"ideas",
|
||||||
|
"question"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "Joooost",
|
||||||
|
"name": "Joooost",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/12090673?v=4",
|
||||||
|
"profile": "https://github.com/Joooost",
|
||||||
|
"contributions": [
|
||||||
|
"ideas"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "sio",
|
||||||
|
"name": "Vitaly Potyarkin",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/334908?v=4",
|
||||||
|
"profile": "https://potyarkin.ml",
|
||||||
|
"contributions": [
|
||||||
|
"ideas"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "bearfrieze",
|
||||||
|
"name": "Bjørn Friese",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/1023813?v=4",
|
||||||
|
"profile": "https://github.com/bearfrieze",
|
||||||
|
"contributions": [
|
||||||
|
"ideas"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "Protektor-Desura",
|
||||||
|
"name": "Protektor",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/1195496?v=4",
|
||||||
|
"profile": "https://github.com/Protektor-Desura",
|
||||||
|
"contributions": [
|
||||||
|
"bug",
|
||||||
|
"ideas",
|
||||||
|
"question"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "llwaini",
|
||||||
|
"name": "llwaini",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/59589857?v=4",
|
||||||
|
"profile": "https://github.com/llwaini",
|
||||||
|
"contributions": [
|
||||||
|
"projectManagement",
|
||||||
|
"test",
|
||||||
|
"tutorial"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"contributorsPerLine": 7,
|
||||||
|
"projectName": "CasaOS",
|
||||||
|
"projectOwner": "IceWhaleTech",
|
||||||
|
"repoType": "github",
|
||||||
|
"repoHost": "https://github.com",
|
||||||
|
"skipCi": true
|
||||||
|
}
|
||||||
26
.github/ISSUE_TEMPLATE/alpha_bug_report.yml
vendored
Normal file
26
.github/ISSUE_TEMPLATE/alpha_bug_report.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
name: "[Alpha Only] Bug Report"
|
||||||
|
description: CasaOS Alpha Testing specific bug report form.
|
||||||
|
title: "[Alpha][Bug] "
|
||||||
|
labels: ["alpha", "bug"]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thanks for taking the time to fill out this bug report!
|
||||||
|
> If you haven't joined CasaOS Alpha Team yet.
|
||||||
|
> Please join first on [Discord](https://discord.gg/knqAbbBbeX) to be updated on the Alpha test plan and test scope.
|
||||||
|
- type: textarea
|
||||||
|
id: what-happened
|
||||||
|
attributes:
|
||||||
|
label: What happened?
|
||||||
|
description: Also tell us, what did you expect to happen?
|
||||||
|
placeholder: Tell us what you see!
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: screenshots
|
||||||
|
attributes:
|
||||||
|
label: Screenshots
|
||||||
|
description: If applicable, add screenshots to help explain your problem.
|
||||||
|
placeholder: Screenshots would be very helpful!
|
||||||
|
|
||||||
53
.github/ISSUE_TEMPLATE/app_request.yml
vendored
Normal file
53
.github/ISSUE_TEMPLATE/app_request.yml
vendored
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
name: "App Request"
|
||||||
|
description: "Request to add an app to the app store."
|
||||||
|
title: "[App Request] AppName"
|
||||||
|
labels: ["App Request"]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
### ❤ Thanks for taking the time to fill out this app request!
|
||||||
|
> Before proceeding, please make sure that this app is not in App Store and no one has [requested](https://github.com/IceWhaleTech/CasaOS/labels/App%20Request) the same app before.
|
||||||
|
> If you have already requested the app, please ask your friends to help add a 👍 to this issue. Then be patient and wait for the developers to work on it.
|
||||||
|
> If you have any questions, please ask them on [Discord](https://discord.gg/knqAbbBbeX) or [Github Discussions](https://github.com/IceWhaleTech/CasaOS/discussions).
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: app-info
|
||||||
|
attributes:
|
||||||
|
label: "App Information"
|
||||||
|
description: "The formal information of this app, as detailed as possible."
|
||||||
|
value: |
|
||||||
|
- Name: <!-- eg. Nextcloud -->
|
||||||
|
- Short Description: <!-- eg. Personal cloud and file sharing solution -->
|
||||||
|
- Official Website: <!-- If available. eg. https://nextcloud.com -->
|
||||||
|
- GitHub Repository: <!-- If available. eg. https://github.com/nextcloud/server -->
|
||||||
|
- Docker Image: <!-- If available. eg. nextcloud/server:latest, ghcr.io/nextcloud/server:latest -->
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: why
|
||||||
|
attributes:
|
||||||
|
label: "Why do you want this app?"
|
||||||
|
description: "Detailed notes can help developers and others understand the importance of this app."
|
||||||
|
placeholder: |
|
||||||
|
As a [what role], it helps me solve [what problem], and especially [what function] is great!
|
||||||
|
or
|
||||||
|
It solves [what problem] and especially [what feature] works well, which is hard to do with other app.
|
||||||
|
or
|
||||||
|
This is the app that [some device/service] must use and will not work without it.
|
||||||
|
or
|
||||||
|
others
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: additional-info
|
||||||
|
attributes:
|
||||||
|
label: "Additional information?"
|
||||||
|
description: "Anything else you want to share with the developers and others?"
|
||||||
|
placeholder: |
|
||||||
|
Example:
|
||||||
|
- Noteworthy matters.
|
||||||
|
- Recommended Docker image.
|
||||||
|
- Validated Docker deployment instructions.
|
||||||
|
- Notable Docker setup details.
|
||||||
|
- Recommended config files, user data, accessible directory settings.
|
||||||
18
.github/ISSUE_TEMPLATE/bug_report.md
vendored
18
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
name: Bug report
|
name: Bug report
|
||||||
about: Create a report to help us improve
|
about: Create a report to help us improve
|
||||||
title: ''
|
title: '[Bug] '
|
||||||
labels: ''
|
labels: 'bug'
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -28,5 +28,19 @@ If applicable, add screenshots to help explain your problem.
|
|||||||
- Browser [e.g. chrome, safari]
|
- Browser [e.g. chrome, safari]
|
||||||
- Version [e.g. 22]
|
- Version [e.g. 22]
|
||||||
|
|
||||||
|
**Logs**
|
||||||
|
|
||||||
|
run following command to collect corresponding logs:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo journalctl -xef -u casaos-gateway
|
||||||
|
sudo journalctl -xef -u casaos-user-service
|
||||||
|
sudo journalctl -xef -u casaos-local-storage
|
||||||
|
sudo journalctl -xef -u casaos.service
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
Add any other context about the problem here.
|
Add any other context about the problem here.
|
||||||
|
|||||||
11
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
11
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: Feature/Enhancement Ideas
|
||||||
|
url: https://github.com/IceWhaleTech/CasaOS/discussions/164
|
||||||
|
about: Have an idea for a new feature/enhancement?
|
||||||
|
- name: Questions, Discussions
|
||||||
|
url: https://github.com/IceWhaleTech/CasaOS/discussions
|
||||||
|
about: Ask questions, propose ideas, or discuss anything related to CasaOS
|
||||||
|
- name: Discord
|
||||||
|
url: https://discord.gg/knqAbbBbeX
|
||||||
|
about: Get help or share great ideas on Discord!
|
||||||
23
.github/ISSUE_TEMPLATE/feedback.yml
vendored
Normal file
23
.github/ISSUE_TEMPLATE/feedback.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
name: "Feedback"
|
||||||
|
description: Feedback, showcases, thoughts, needs and questions, etc.
|
||||||
|
title: "[Feedback] "
|
||||||
|
labels: ["feedback"]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
### ❤️ Thanks for your feedback!
|
||||||
|
> Come join our [Discord community](https://discord.gg/knqAbbBbeX) and paint the ideal home cloud with us.
|
||||||
|
- type: textarea
|
||||||
|
id: description
|
||||||
|
attributes:
|
||||||
|
label: Description
|
||||||
|
placeholder: What do you want to tell us?
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: additional
|
||||||
|
attributes:
|
||||||
|
label: Additional Information
|
||||||
|
description: Please add logs/files/screenshots if you have them to help us better understanding.
|
||||||
|
|
||||||
33
.github/workflows/add_issues_to_projects.yml
vendored
Normal file
33
.github/workflows/add_issues_to_projects.yml
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
name: Add Issues To Projects
|
||||||
|
|
||||||
|
on:
|
||||||
|
issues:
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
add-issues:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Generate token
|
||||||
|
id: generate_token
|
||||||
|
uses: tibdex/github-app-token@36464acb844fc53b9b8b2401da68844f6b05ebb0
|
||||||
|
with:
|
||||||
|
app_id: ${{ secrets.ALPHA_BOT_ID }}
|
||||||
|
private_key: ${{ secrets.ALPHA_BOT_PEM }}
|
||||||
|
|
||||||
|
- name: Add Alpha Bug Issue To project
|
||||||
|
uses: actions/add-to-project@v0.3.0
|
||||||
|
with:
|
||||||
|
github-token: ${{ steps.generate_token.outputs.token }}
|
||||||
|
project-url: https://github.com/orgs/IceWhaleTech/projects/5
|
||||||
|
labeled: alpha, bug
|
||||||
|
label-operator: AND
|
||||||
|
|
||||||
|
- name: Add App Request Issue To project
|
||||||
|
uses: actions/add-to-project@v0.3.0
|
||||||
|
with:
|
||||||
|
github-token: ${{ steps.generate_token.outputs.token }}
|
||||||
|
project-url: https://github.com/orgs/IceWhaleTech/projects/8
|
||||||
|
labeled: "App Request"
|
||||||
|
label-operator: AND
|
||||||
6
.github/workflows/casa.yml
vendored
6
.github/workflows/casa.yml
vendored
@@ -63,7 +63,7 @@ jobs:
|
|||||||
# git clone $REPO_URL -b $REPO_BRANCH --recursive casa
|
# git clone $REPO_URL -b $REPO_BRANCH --recursive casa
|
||||||
# ln -sf /workdir/casa $GITHUB_WORKSPACE/casa
|
# ln -sf /workdir/casa $GITHUB_WORKSPACE/casa
|
||||||
# ls
|
# ls
|
||||||
|
|
||||||
|
|
||||||
- name: Set enviroment for github-release
|
- name: Set enviroment for github-release
|
||||||
run: |
|
run: |
|
||||||
@@ -76,7 +76,7 @@ jobs:
|
|||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: '14'
|
node-version: '14'
|
||||||
|
|
||||||
- name: Build frontend with nodejs and yarn
|
- name: Build frontend with nodejs and yarn
|
||||||
run: |
|
run: |
|
||||||
cd UI
|
cd UI
|
||||||
@@ -90,7 +90,7 @@ jobs:
|
|||||||
- name: Build with xgo
|
- name: Build with xgo
|
||||||
uses: crazy-max/ghaction-xgo@v1
|
uses: crazy-max/ghaction-xgo@v1
|
||||||
with:
|
with:
|
||||||
xgo_version: latest
|
xgo_version: v0.7.5
|
||||||
go_version: ${{ matrix.go_version }}
|
go_version: ${{ matrix.go_version }}
|
||||||
dest: build
|
dest: build
|
||||||
prefix: casa
|
prefix: casa
|
||||||
|
|||||||
79
.github/workflows/demo.yml
vendored
Normal file
79
.github/workflows/demo.yml
vendored
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
name: Demo Reset
|
||||||
|
|
||||||
|
# Controls when the workflow will run
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 * * * *"
|
||||||
|
|
||||||
|
# Allows you to run this workflow manually from the Actions tab
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
# OLD_INSTANCE_SNAPSHOT_NAME=$(aws lightsail get-instance-snapshots | grep '"name": "CasaOS-Demo-Snapshot-[0-9]' | sed 's/ //g' | sed 's/"//g' | sed 's/,//g' | sed 's/name://g')
|
||||||
|
# OLD_INSTANCE_NAME=$(aws lightsail get-instances | grep '"name": "CasaOS-Demo-[0-9]' | sed 's/ //g' | sed 's/"//g' | sed 's/,//g' | sed 's/name://g')
|
||||||
|
# NEW_INSTANCE_NAME=CasaOS-Demo-$(date +%s)
|
||||||
|
|
||||||
|
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||||
|
jobs:
|
||||||
|
# This workflow contains a single job called "build"
|
||||||
|
reset:
|
||||||
|
# The type of runner that the job will run on
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
# Steps represent a sequence of tasks that will be executed as part of the job
|
||||||
|
steps:
|
||||||
|
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Configure AWS credentials from Test account
|
||||||
|
uses: aws-actions/configure-aws-credentials@v1
|
||||||
|
with:
|
||||||
|
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
|
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
aws-region: us-west-2
|
||||||
|
|
||||||
|
- name: Get old instance and snapshot name, create new instance name
|
||||||
|
run: |
|
||||||
|
echo "OLD_INSTANCE_SNAPSHOT_NAME=$(aws lightsail get-instance-snapshots | grep '"name": "casaos-0.3.6-1666150291' | sed 's/ //g' | sed 's/"//g' | sed 's/,//g' | sed 's/name://g')" >> $GITHUB_ENV
|
||||||
|
echo "OLD_INSTANCE_NAME=$(aws lightsail get-instances | grep '"name": "CasaOS-Demo-[0-9]' | sed 's/ //g' | sed 's/"//g' | sed 's/,//g' | sed 's/name://g')" >> $GITHUB_ENV
|
||||||
|
echo "NEW_INSTANCE_NAME=CasaOS-Demo-$(date +%s)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Create instances from snapshot
|
||||||
|
run: |
|
||||||
|
aws lightsail create-instances-from-snapshot \
|
||||||
|
--instance-snapshot-name ${{ env.OLD_INSTANCE_SNAPSHOT_NAME }} \
|
||||||
|
--instance-names ${{ env.NEW_INSTANCE_NAME }} \
|
||||||
|
--availability-zone us-west-2a \
|
||||||
|
--bundle-id medium_2_0
|
||||||
|
|
||||||
|
- name: Wait for new instance running
|
||||||
|
run: |
|
||||||
|
TIMEOUT=$(($(date +%s)+600))
|
||||||
|
while [ $TIMEOUT -gt $(date +%s) ]
|
||||||
|
do
|
||||||
|
NEW_INSTANCE_STATE=$(aws lightsail get-instance-state --instance-name ${{ env.NEW_INSTANCE_NAME }} | grep '"name":' | sed 's/ //g' | sed 's/"//g' | sed 's/name://g')
|
||||||
|
if [ $NEW_INSTANCE_STATE == running ]
|
||||||
|
then
|
||||||
|
echo "New instance is running now"
|
||||||
|
sleep 10s
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Put instance public ports
|
||||||
|
run: |
|
||||||
|
aws lightsail put-instance-public-ports \
|
||||||
|
--port-infos fromPort=0,toPort=65535,protocol=all \
|
||||||
|
--instance-name ${{ env.NEW_INSTANCE_NAME }}
|
||||||
|
|
||||||
|
- name: Attach static ip
|
||||||
|
run: |
|
||||||
|
aws lightsail attach-static-ip \
|
||||||
|
--static-ip-name CasaOS-Demo-IP \
|
||||||
|
--instance-name ${{ env.NEW_INSTANCE_NAME }}
|
||||||
|
|
||||||
|
- name: Delete old instance
|
||||||
|
run: |
|
||||||
|
aws lightsail delete-instance \
|
||||||
|
--instance-name ${{ env.OLD_INSTANCE_NAME }}
|
||||||
|
|
||||||
|
|
||||||
27
.github/workflows/move_alpha_bug_to_project.yml
vendored
Normal file
27
.github/workflows/move_alpha_bug_to_project.yml
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# This is a basic workflow to help you get started with Actions
|
||||||
|
|
||||||
|
name: Move alpha bug to project
|
||||||
|
|
||||||
|
on:
|
||||||
|
issues:
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
track_issue:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Generate token
|
||||||
|
id: generate_token
|
||||||
|
uses: tibdex/github-app-token@36464acb844fc53b9b8b2401da68844f6b05ebb0
|
||||||
|
with:
|
||||||
|
app_id: ${{ secrets.ALPHA_BOT_ID }}
|
||||||
|
private_key: ${{ secrets.ALPHA_BOT_PEM }}
|
||||||
|
|
||||||
|
- name: Add Issue To GitHub Projects Beta
|
||||||
|
uses: actions/add-to-project@v0.1.0
|
||||||
|
with:
|
||||||
|
project-url: https://github.com/orgs/IceWhaleTech/projects/5
|
||||||
|
github-token: ${{ steps.generate_token.outputs.token }}
|
||||||
|
labeled: alpha, bug
|
||||||
|
label-operator: AND
|
||||||
48
.github/workflows/push_events_to_discord.yml
vendored
Normal file
48
.github/workflows/push_events_to_discord.yml
vendored
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
name: Push Events to Discord
|
||||||
|
|
||||||
|
on:
|
||||||
|
issues:
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
issue_comment:
|
||||||
|
types:
|
||||||
|
- created
|
||||||
|
discussion:
|
||||||
|
types:
|
||||||
|
- created
|
||||||
|
- transferred
|
||||||
|
- answered
|
||||||
|
discussion_comment:
|
||||||
|
types:
|
||||||
|
- created
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
push-events:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: General Discussions & Comments
|
||||||
|
if: ${{ ( github.event_name == 'discussion' || github.event_name == 'discussion_comment' ) && github.event.discussion.category.name == 'General' }}
|
||||||
|
uses: joseph-montanez/forward-event-action@v3.0.0
|
||||||
|
with:
|
||||||
|
webhook: ${{ secrets.Discord_CasaOS_General_Webhook }}
|
||||||
|
|
||||||
|
- name: App Request Issues & Comments
|
||||||
|
if: ${{ ( github.event_name == 'issues' || github.event_name == 'issue_comment' ) && contains(github.event.issue.labels.*.name, 'App Request') }}
|
||||||
|
uses: joseph-montanez/forward-event-action@v3.0.0
|
||||||
|
with:
|
||||||
|
webhook: ${{ secrets.Discord_CasaOS_App_Request_Webhook }}
|
||||||
|
|
||||||
|
- name: Bug Issues & Comments
|
||||||
|
if: ${{ ( github.event_name == 'issues' || github.event_name == 'issue_comment' ) && contains(github.event.issue.labels.*.name, 'bug') && !contains(github.event.issue.labels.*.name, 'alpha') }}
|
||||||
|
uses: joseph-montanez/forward-event-action@v3.0.0
|
||||||
|
with:
|
||||||
|
webhook: ${{ secrets.Discord_CasaOS_Bug_Webhook }}
|
||||||
|
|
||||||
|
- name: Alpha Issues & Comments
|
||||||
|
if: ${{ ( github.event_name == 'issues' || github.event_name == 'issue_comment' ) && contains(github.event.issue.labels.*.name, 'alpha') }}
|
||||||
|
uses: joseph-montanez/forward-event-action@v3.0.0
|
||||||
|
with:
|
||||||
|
webhook: ${{ secrets.Discord_CasaOS_Alpha_Webhook }}
|
||||||
71
.github/workflows/release.yml
vendored
Normal file
71
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
name: goreleaser
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- v*.*.*
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
goreleaser:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Install dependencies for cross-compiling
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt-get --no-install-recommends --yes install \
|
||||||
|
upx libc6-dev-amd64-cross \
|
||||||
|
gcc-aarch64-linux-gnu libc6-dev-arm64-cross \
|
||||||
|
gcc-arm-linux-gnueabihf libc6-dev-armhf-cross
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
-
|
||||||
|
name: Fetch all tags
|
||||||
|
run: git fetch --force --tags
|
||||||
|
|
||||||
|
- name: Get version
|
||||||
|
id: get_version
|
||||||
|
run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}
|
||||||
|
-
|
||||||
|
name: Set up Go
|
||||||
|
uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: 1.19
|
||||||
|
-
|
||||||
|
name: Run GoReleaser
|
||||||
|
uses: goreleaser/goreleaser-action@v2
|
||||||
|
with:
|
||||||
|
# either 'goreleaser' (default) or 'goreleaser-pro'
|
||||||
|
distribution: goreleaser
|
||||||
|
version: latest
|
||||||
|
args: release --rm-dist
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
# Your GoReleaser Pro key, if you are using the 'goreleaser-pro' distribution
|
||||||
|
# GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
|
||||||
|
|
||||||
|
- name: Upload to oss
|
||||||
|
id: upload_to_oss
|
||||||
|
uses: tvrcgo/upload-to-oss@master
|
||||||
|
with:
|
||||||
|
key-id: ${{ secrets.OSS_KEY_ID }}
|
||||||
|
key-secret: ${{ secrets.OSS_KEY_SECRET }}
|
||||||
|
region: oss-cn-shanghai
|
||||||
|
bucket: casaos
|
||||||
|
assets: |
|
||||||
|
dist/checksums.txt:/IceWhaleTech/CasaOS/releases/download/${{ steps.get_version.outputs.VERSION }}/checksums.txt
|
||||||
|
dist/linux-arm-7-casaos-${{ steps.get_version.outputs.VERSION }}.tar.gz:/IceWhaleTech/CasaOS/releases/download/${{ steps.get_version.outputs.VERSION }}/linux-arm-7-casaos-${{ steps.get_version.outputs.VERSION }}.tar.gz
|
||||||
|
dist/linux-arm64-casaos-${{ steps.get_version.outputs.VERSION }}.tar.gz:/IceWhaleTech/CasaOS/releases/download/${{ steps.get_version.outputs.VERSION }}/linux-arm64-casaos-${{ steps.get_version.outputs.VERSION }}.tar.gz
|
||||||
|
dist/linux-amd64-casaos-${{ steps.get_version.outputs.VERSION }}.tar.gz:/IceWhaleTech/CasaOS/releases/download/${{ steps.get_version.outputs.VERSION }}/linux-amd64-casaos-${{ steps.get_version.outputs.VERSION }}.tar.gz
|
||||||
|
dist/linux-arm-7-casaos-migration-tool-${{ steps.get_version.outputs.VERSION }}.tar.gz:/IceWhaleTech/CasaOS/releases/download/${{ steps.get_version.outputs.VERSION }}/linux-arm-7-casaos-migration-tool-${{ steps.get_version.outputs.VERSION }}.tar.gz
|
||||||
|
dist/linux-arm64-casaos-migration-tool-${{ steps.get_version.outputs.VERSION }}.tar.gz:/IceWhaleTech/CasaOS/releases/download/${{ steps.get_version.outputs.VERSION }}/linux-arm64-casaos-migration-tool-${{ steps.get_version.outputs.VERSION }}.tar.gz
|
||||||
|
dist/linux-amd64-casaos-migration-tool-${{ steps.get_version.outputs.VERSION }}.tar.gz:/IceWhaleTech/CasaOS/releases/download/${{ steps.get_version.outputs.VERSION }}/linux-amd64-casaos-migration-tool-${{ steps.get_version.outputs.VERSION }}.tar.gz
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
9
.gitignore
vendored
9
.gitignore
vendored
@@ -28,8 +28,15 @@ gen
|
|||||||
/sql/
|
/sql/
|
||||||
/out/
|
/out/
|
||||||
/db/
|
/db/
|
||||||
/docs/
|
|
||||||
/conf/conf.ini
|
/conf/conf.ini
|
||||||
|
/conf/conf.conf
|
||||||
|
/conf/conf.json
|
||||||
__debug_bin
|
__debug_bin
|
||||||
main
|
main
|
||||||
|
github.com
|
||||||
|
.all-contributorsrc
|
||||||
|
dist
|
||||||
CasaOS
|
CasaOS
|
||||||
|
|
||||||
|
# System Files
|
||||||
|
.DS_Store
|
||||||
|
|||||||
161
.goreleaser.debug.yaml
Normal file
161
.goreleaser.debug.yaml
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
# This is an example .goreleaser.yml file with some sensible defaults.
|
||||||
|
# Make sure to check the documentation at https://goreleaser.com
|
||||||
|
project_name: casaos
|
||||||
|
before:
|
||||||
|
hooks:
|
||||||
|
- go generate
|
||||||
|
- go run github.com/google/go-licenses@latest check . --disallowed_types=restricted
|
||||||
|
- go mod tidy
|
||||||
|
- go test -v ./...
|
||||||
|
|
||||||
|
builds:
|
||||||
|
- id: casaos-amd64
|
||||||
|
binary: build/sysroot/usr/bin/casaos
|
||||||
|
env:
|
||||||
|
- CC=x86_64-linux-gnu-gcc
|
||||||
|
gcflags:
|
||||||
|
- all=-N -l
|
||||||
|
ldflags:
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
- osusergo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
- id: casaos-arm64
|
||||||
|
binary: build/sysroot/usr/bin/casaos
|
||||||
|
env:
|
||||||
|
- CC=aarch64-linux-gnu-gcc
|
||||||
|
gcflags:
|
||||||
|
- all=-N -l
|
||||||
|
ldflags:
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
- osusergo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- arm64
|
||||||
|
- id: casaos-arm-7
|
||||||
|
binary: build/sysroot/usr/bin/casaos
|
||||||
|
env:
|
||||||
|
- CC=arm-linux-gnueabihf-gcc
|
||||||
|
gcflags:
|
||||||
|
- all=-N -l
|
||||||
|
ldflags:
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
- osusergo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- arm
|
||||||
|
goarm:
|
||||||
|
- "7"
|
||||||
|
- id: casaos-migration-tool-amd64
|
||||||
|
binary: build/sysroot/usr/bin/casaos-migration-tool
|
||||||
|
main: ./cmd/migration-tool
|
||||||
|
env:
|
||||||
|
- CC=x86_64-linux-gnu-gcc
|
||||||
|
gcflags:
|
||||||
|
- all=-N -l
|
||||||
|
ldflags:
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
- osusergo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
- id: casaos-migration-tool-arm64
|
||||||
|
binary: build/sysroot/usr/bin/casaos-migration-tool
|
||||||
|
main: ./cmd/migration-tool
|
||||||
|
env:
|
||||||
|
- CC=aarch64-linux-gnu-gcc
|
||||||
|
gcflags:
|
||||||
|
- all=-N -l
|
||||||
|
ldflags:
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
- osusergo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- arm64
|
||||||
|
- id: casaos-migration-tool-arm-7
|
||||||
|
binary: build/sysroot/usr/bin/casaos-migration-tool
|
||||||
|
main: ./cmd/migration-tool
|
||||||
|
env:
|
||||||
|
- CC=arm-linux-gnueabihf-gcc
|
||||||
|
gcflags:
|
||||||
|
- all=-N -l
|
||||||
|
ldflags:
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
- osusergo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- arm
|
||||||
|
goarm:
|
||||||
|
- "7"
|
||||||
|
archives:
|
||||||
|
- name_template: "{{ .Os }}-{{ .Arch }}-{{ .ProjectName }}-v{{ .Version }}"
|
||||||
|
id: casaos
|
||||||
|
builds:
|
||||||
|
- casaos-amd64
|
||||||
|
- casaos-arm64
|
||||||
|
- casaos-arm-7
|
||||||
|
replacements:
|
||||||
|
arm: arm-7
|
||||||
|
files:
|
||||||
|
- build/**/*
|
||||||
|
- name_template: "{{ .Os }}-{{ .Arch }}-{{ .ProjectName }}-migration-tool-v{{ .Version }}"
|
||||||
|
id: casaos-migration-tool
|
||||||
|
builds:
|
||||||
|
- casaos-migration-tool-amd64
|
||||||
|
- casaos-migration-tool-arm64
|
||||||
|
- casaos-migration-tool-arm-7
|
||||||
|
replacements:
|
||||||
|
arm: arm-7
|
||||||
|
files:
|
||||||
|
- build/sysroot/etc/**/*
|
||||||
|
checksum:
|
||||||
|
name_template: "checksums.txt"
|
||||||
|
snapshot:
|
||||||
|
name_template: "{{ incpatch .Version }}"
|
||||||
|
changelog:
|
||||||
|
sort: asc
|
||||||
|
filters:
|
||||||
|
exclude:
|
||||||
|
- "^docs:"
|
||||||
|
- "^test:"
|
||||||
|
# release:
|
||||||
|
# github:
|
||||||
|
# owner: IceWhaleTech
|
||||||
|
# name: CasaOS
|
||||||
|
# draft: true
|
||||||
|
# prerelease: auto
|
||||||
|
# mode: replace
|
||||||
|
# name_template: "v{{ .Version }}"
|
||||||
|
release:
|
||||||
|
github:
|
||||||
|
owner: IceWhaleTech
|
||||||
|
name: CasaOS
|
||||||
|
draft: true
|
||||||
|
prerelease: auto
|
||||||
|
mode: replace
|
||||||
|
name_template: "v{{ .Version }}"
|
||||||
191
.goreleaser.yaml
Normal file
191
.goreleaser.yaml
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
# This is an example .goreleaser.yml file with some sensible defaults.
|
||||||
|
# Make sure to check the documentation at https://goreleaser.com
|
||||||
|
project_name: casaos
|
||||||
|
before:
|
||||||
|
hooks:
|
||||||
|
- go generate
|
||||||
|
- go run github.com/google/go-licenses@latest check . --disallowed_types=restricted
|
||||||
|
- go mod tidy
|
||||||
|
- go test -v ./...
|
||||||
|
|
||||||
|
builds:
|
||||||
|
- id: casaos-amd64
|
||||||
|
binary: build/sysroot/usr/bin/casaos
|
||||||
|
hooks:
|
||||||
|
post:
|
||||||
|
- upx --best --lzma -v --no-progress "{{ .Path }}"
|
||||||
|
env:
|
||||||
|
- CC=x86_64-linux-gnu-gcc
|
||||||
|
ldflags:
|
||||||
|
- -X main.commit={{.Commit}}
|
||||||
|
- -X main.date={{.Date}}
|
||||||
|
- -s
|
||||||
|
- -w
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
- osusergo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
- id: casaos-arm64
|
||||||
|
binary: build/sysroot/usr/bin/casaos
|
||||||
|
hooks:
|
||||||
|
post:
|
||||||
|
- upx --best --lzma -v --no-progress "{{ .Path }}"
|
||||||
|
env:
|
||||||
|
- CC=aarch64-linux-gnu-gcc
|
||||||
|
ldflags:
|
||||||
|
- -X main.commit={{.Commit}}
|
||||||
|
- -X main.date={{.Date}}
|
||||||
|
- -s
|
||||||
|
- -w
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
- osusergo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- arm64
|
||||||
|
- id: casaos-arm-7
|
||||||
|
binary: build/sysroot/usr/bin/casaos
|
||||||
|
hooks:
|
||||||
|
post:
|
||||||
|
- upx --best --lzma -v --no-progress "{{ .Path }}"
|
||||||
|
env:
|
||||||
|
- CC=arm-linux-gnueabihf-gcc
|
||||||
|
ldflags:
|
||||||
|
- -X main.commit={{.Commit}}
|
||||||
|
- -X main.date={{.Date}}
|
||||||
|
- -s
|
||||||
|
- -w
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
- osusergo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- arm
|
||||||
|
goarm:
|
||||||
|
- "7"
|
||||||
|
- id: casaos-migration-tool-amd64
|
||||||
|
binary: build/sysroot/usr/bin/casaos-migration-tool
|
||||||
|
hooks:
|
||||||
|
post:
|
||||||
|
- upx --best --lzma -v --no-progress "{{ .Path }}"
|
||||||
|
main: ./cmd/migration-tool
|
||||||
|
env:
|
||||||
|
- CC=x86_64-linux-gnu-gcc
|
||||||
|
ldflags:
|
||||||
|
- -X main.commit={{.Commit}}
|
||||||
|
- -X main.date={{.Date}}
|
||||||
|
- -s
|
||||||
|
- -w
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
- osusergo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
- id: casaos-migration-tool-arm64
|
||||||
|
binary: build/sysroot/usr/bin/casaos-migration-tool
|
||||||
|
hooks:
|
||||||
|
post:
|
||||||
|
- upx --best --lzma -v --no-progress "{{ .Path }}"
|
||||||
|
main: ./cmd/migration-tool
|
||||||
|
env:
|
||||||
|
- CC=aarch64-linux-gnu-gcc
|
||||||
|
ldflags:
|
||||||
|
- -X main.commit={{.Commit}}
|
||||||
|
- -X main.date={{.Date}}
|
||||||
|
- -s
|
||||||
|
- -w
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
- osusergo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- arm64
|
||||||
|
- id: casaos-migration-tool-arm-7
|
||||||
|
binary: build/sysroot/usr/bin/casaos-migration-tool
|
||||||
|
hooks:
|
||||||
|
post:
|
||||||
|
- upx --best --lzma -v --no-progress "{{ .Path }}"
|
||||||
|
main: ./cmd/migration-tool
|
||||||
|
env:
|
||||||
|
- CC=arm-linux-gnueabihf-gcc
|
||||||
|
ldflags:
|
||||||
|
- -X main.commit={{.Commit}}
|
||||||
|
- -X main.date={{.Date}}
|
||||||
|
- -s
|
||||||
|
- -w
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
- osusergo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- arm
|
||||||
|
goarm:
|
||||||
|
- "7"
|
||||||
|
archives:
|
||||||
|
- name_template: "{{ .Os }}-{{ .Arch }}-{{ .ProjectName }}-v{{ .Version }}"
|
||||||
|
id: casaos
|
||||||
|
builds:
|
||||||
|
- casaos-amd64
|
||||||
|
- casaos-arm64
|
||||||
|
- casaos-arm-7
|
||||||
|
replacements:
|
||||||
|
arm: arm-7
|
||||||
|
files:
|
||||||
|
- build/**/*
|
||||||
|
- name_template: "{{ .Os }}-{{ .Arch }}-{{ .ProjectName }}-migration-tool-v{{ .Version }}"
|
||||||
|
id: casaos-migration-tool
|
||||||
|
builds:
|
||||||
|
- casaos-migration-tool-amd64
|
||||||
|
- casaos-migration-tool-arm64
|
||||||
|
- casaos-migration-tool-arm-7
|
||||||
|
replacements:
|
||||||
|
arm: arm-7
|
||||||
|
files:
|
||||||
|
- build/sysroot/etc/**/*
|
||||||
|
checksum:
|
||||||
|
name_template: "checksums.txt"
|
||||||
|
snapshot:
|
||||||
|
name_template: "{{ incpatch .Version }}"
|
||||||
|
changelog:
|
||||||
|
sort: asc
|
||||||
|
filters:
|
||||||
|
exclude:
|
||||||
|
- "^docs:"
|
||||||
|
- "^test:"
|
||||||
|
# release:
|
||||||
|
# github:
|
||||||
|
# owner: IceWhaleTech
|
||||||
|
# name: CasaOS
|
||||||
|
# draft: true
|
||||||
|
# prerelease: auto
|
||||||
|
# mode: replace
|
||||||
|
# name_template: "v{{ .Version }}"
|
||||||
|
release:
|
||||||
|
github:
|
||||||
|
owner: IceWhaleTech
|
||||||
|
name: CasaOS
|
||||||
|
draft: true
|
||||||
|
prerelease: auto
|
||||||
|
mode: replace
|
||||||
|
name_template: "v{{ .Version }}"
|
||||||
559
CHANGELOG.md
Normal file
559
CHANGELOG.md
Normal file
@@ -0,0 +1,559 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
## [0.4.0] - 2022-12-13
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- [Developer] Included `casaos-cli` command tool for debugging
|
||||||
|
- [Developer] Added message bus for events and actions - Use `casaos-cli message-bus` to manage.
|
||||||
|
- [Disk] Disk notification in Dashboard
|
||||||
|
- [System] Restart/shutdown directly from CasaOS Dashboard
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- [General] CasaOS new logo!
|
||||||
|
- [App] Redesign of Featured App
|
||||||
|
- [App] Now you can choose to delete userdata along with app uninstallation
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- [System] Fixed a shell injection issue for better security
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- [System] Re-instate default zone0 for CPU Temp ([#694](https://github.com/IceWhaleTech/CasaOS/issues/694))
|
||||||
|
- [Disk] Fixed storage name with extra `-1` after rebooting ([#698](https://github.com/IceWhaleTech/CasaOS/issues/698))
|
||||||
|
- [Disk] Fixed disk check so it does not impact disk going into idle ([#704](https://github.com/IceWhaleTech/CasaOS/issues/704))
|
||||||
|
|
||||||
|
## [0.3.8] 2022-11-21
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- [System] Add system announcement
|
||||||
|
- [App] Allow to turn off the display of "Existing Docker Apps" in the settings.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- [System] Improve the feedback function, you can submit feedback in the bottom right corner of WebUI.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- [System] Fix CPU Temp for other platforms ([#661](https://github.com/IceWhaleTech/CasaOS/issues/661))
|
||||||
|
|
||||||
|
## [0.3.7.1] 2022-11-04
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix memory leak issue ([#658](https://github.com/IceWhaleTech/CasaOS/issues/658)[#646](https://github.com/IceWhaleTech/CasaOS/issues/646))
|
||||||
|
- Solve the problem of local application import failure ([#490](https://github.com/IceWhaleTech/CasaOS/issues/490))
|
||||||
|
|
||||||
|
## [0.3.7] 2022-10-28
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- [Storage] Disk merge (Beta), you can merge multiple disks into a single storage space (currently you need to enable this feature from the command line)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- [Files] Changed the cache file storage location, now the file upload size is not limited by the system disk capacity.
|
||||||
|
- [Scripts] Updated installation and upgrade scripts to support more Debian-based Linux distributions.
|
||||||
|
- [Engineering] Refactored Local Storage into a standalone service as part of CasaOS modularization.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- [Apps] App list update mechanism improved, now you can see the latest apps in App Store immediately.
|
||||||
|
- [Storage] Fixed a lot of known issues
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- [Storage] Disk merge (Beta), you can merge multiple disks into a single storage space (currently you need to enable this feature from the command line)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- [Files] Changed the cache file storage location, now the file upload size is not limited by the system disk capacity.
|
||||||
|
- [Scripts] Updated installation and upgrade scripts to support more Debian-based Linux distributions.
|
||||||
|
- [Engineering] Refactored Local Storage into a standalone service as part of CasaOS modularization.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- [Apps] App list update mechanism improved, now you can see the latest apps in App Store immediately.
|
||||||
|
- [Storage] Fixed a lot of known issues
|
||||||
|
|
||||||
|
|
||||||
|
## [0.3.6] - 2022-09-06
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- [System] Added power and temperature info to performance widget (Intel)
|
||||||
|
- [Apps] Custom links can be added to Apps section
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- [Apps] Fixed the problem of not being able to modify some App settings ([#510](https://github.com/IceWhaleTech/CasaOS/issues/510))
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- [System] Architecture optimization. Improved performance.
|
||||||
|
|
||||||
|
## [0.3.5] - 2022-08-23
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- [File] Mount the shared samba
|
||||||
|
- [File] File sharing via Samba
|
||||||
|
- [System] You can share casaos on Twitter, facebook, reddit
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- [Disk] Support for mounting existing data disks
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- [App] fixed uninstalling imported docker container apps results in wiping ALL your config data from them ([#360](https://github.com/IceWhaleTech/CasaOS/issues/360))
|
||||||
|
|
||||||
|
## [0.3.4] - 2022-07-29(UTC)
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- SSH adds port-side options and prompts for connection status. ([#286](https://github.com/IceWhaleTech/CasaOS/issues/286))
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Normalize all routes
|
||||||
|
- Application names now support spaces ([#211](https://github.com/IceWhaleTech/CasaOS/issues/211))
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- Removed casaos connect
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- Adjustment of authentication method
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed storage format and remove password error issues ([#344](https://github.com/IceWhaleTech/CasaOS/issues/344) [#357](https://github.com/IceWhaleTech/CasaOS/issues/357))
|
||||||
|
|
||||||
|
## [0.3.3] - 2022-07-08(UTC)
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- [System]Add interface call log
|
||||||
|
- Adding Developing file ([#311](https://github.com/IceWhaleTech/CasaOS/pull/311))
|
||||||
|
- [App] add new tips for app section.
|
||||||
|
- [System] UI Configurable function modules: support turning off the search bar and recommended apps module in the settings.
|
||||||
|
- [System] Custom wallpapers: two new preset wallpapers, support for custom uploads, support for setting images from Files as wallpapers, Also support right click on dashboard to change wallpaper.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- [App] Cache app store index and category data
|
||||||
|
- [System] casaos master program adapted to FHS standards
|
||||||
|
- [App] Update casaos icons.
|
||||||
|
- [System] Update translation.
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- [System] Remove upnp function module
|
||||||
|
- [System] Remove ddns function module
|
||||||
|
- [System] Remove search function module
|
||||||
|
- [System] Remove zerotier function module
|
||||||
|
- [System] Remove task function module
|
||||||
|
- [System] Remove file share function module
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- [Disk] Fixed hard drive won't hibernate problem ([#202](https://github.com/IceWhaleTech/CasaOS/issues/202))
|
||||||
|
- [File] Fixed the backspace key that causes the folder to rewind ([#252](https://github.com/IceWhaleTech/CasaOS/issues/252))
|
||||||
|
- [App] Fixed app logo is not loading when imported. ([#320](https://github.com/IceWhaleTech/CasaOS/issues/320))
|
||||||
|
|
||||||
|
## [0.3.2.1] - 2022-06-16(UTC)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- [System] Adjusted the display style.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- [System] Fixed the issue of widgets displaying wrongly on mobile devices.
|
||||||
|
- [App] Fix the problem of application opening failure on non-80 ports ([#283](https://github.com/IceWhaleTech/CasaOS/issues/283) [#280](https://github.com/IceWhaleTech/CasaOS/issues/280))
|
||||||
|
- [System] Modify port failure problem ([#282](https://github.com/IceWhaleTech/CasaOS/issues/282))
|
||||||
|
- [App]Modify environment variables disappearing problem([#284](https://github.com/IceWhaleTech/CasaOS/issues/284))
|
||||||
|
- [System]Fix no update alert([#278](https://github.com/IceWhaleTech/CasaOS/issues/278))
|
||||||
|
- [System] Fixed some bugs of application cpu usage and memory staging([#272](https://github.com/IceWhaleTech/CasaOS/issues/272))
|
||||||
|
- [App] Fixed plex and HA network mode error issues ([#299](https://github.com/IceWhaleTech/CasaOS/issues/299))
|
||||||
|
- [App] Fix application terminal not working ([#266](https://github.com/IceWhaleTech/CasaOS/issues/266))
|
||||||
|
|
||||||
|
## [0.3.2] - 2022-06-10
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- [Files] Files can now be selected multiple files and downloaded, deleted, moved, etc.
|
||||||
|
- [Apps] Support to modify the application opening address.([#204](https://github.com/IceWhaleTech/CasaOS/issues/204))
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- [Apps] Hide the display of non-essential environment variables in the application.([#196](https://github.com/IceWhaleTech/CasaOS/issues/196))
|
||||||
|
- [System] Network, disk, cpu, memory, etc. information is modified to be pushed via socket.
|
||||||
|
- [System] Optimize opening speed.([#214](https://github.com/IceWhaleTech/CasaOS/issues/214))
|
||||||
|
- [Language] Update language pack [zarevskaya](https://github.com/zarevskaya) [patrickhilker](https://github.com/patrickhilker)
|
||||||
|
- [System] Interface path adjustment
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- [Files] Remove the online preview function of PDF files
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- [System] Fixed the problem that sync data cannot submit the device ID ([#68](https://github.com/IceWhaleTech/CasaOS/issues/68))
|
||||||
|
- [Files] Fixed the code editor center alignment display problem.([#210](https://github.com/IceWhaleTech/CasaOS/issues/210))
|
||||||
|
- [Files] Fixed the problem of wrong name when downloading files.([#240](https://github.com/IceWhaleTech/CasaOS/issues/240))
|
||||||
|
- [System] Fixed the network display as a negative number problem.([#224](https://github.com/IceWhaleTech/CasaOS/issues/224))
|
||||||
|
- [System] Fixed the problem of wireless network card traffic display.([#222](https://github.com/IceWhaleTech/CasaOS/issues/222))
|
||||||
|
|
||||||
|
|
||||||
|
## [0.3.1.1] - 2022-05-17
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix the data loss problem when importing local applications
|
||||||
|
|
||||||
|
## [0.3.1] - 2022-05-16
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- CasaConnect and file add image thumbnail function
|
||||||
|
- Import of docker applications
|
||||||
|
- List support custom sorting function
|
||||||
|
- CasaConnect gives priority to LAN connections
|
||||||
|
- USB auto-mount switch (Raspberry Pi is off by default)
|
||||||
|
- Application custom installation supports Docker Compose configuration import in YAML format
|
||||||
|
- You will see the new version changelog from the next version
|
||||||
|
- Added live preview for icons in custom installed applications
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Application data is no longer saved to the database
|
||||||
|
- Optimize app store speed issues
|
||||||
|
- Optimize the way WebUI is filled in
|
||||||
|
- Image preview has been completely upgraded and now supports switching between all images in the same folder, as well as dragging, zooming, rotating and resetting.
|
||||||
|
- Added color levels to the CPU and RAM charts
|
||||||
|
- Optimized the display of the Connect friends list right-click menu
|
||||||
|
- Change the initial display directory to /DATA
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- Historical Application Data
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed the problem that some Docker CLI commands failed to import
|
||||||
|
- Fix the problem that the application is not easily recognized in /DATA/AppData directory and docker command line after installation, it will be shown as application name
|
||||||
|
- Fix Pi-hole installation failure
|
||||||
|
- Fixed the issue that the app could not be updated using WatchTower
|
||||||
|
- Fixed the problem that the task status was lost after closing Files when there was an upload task
|
||||||
|
|
||||||
|
## [0.3.0] - 2022-04-08
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Add CasaConnect function, now you can share private files peer-to-peer with your friends.
|
||||||
|
- Add a widget for network traffic monitoring.
|
||||||
|
- 12 new popular apps added to App Center
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Updated the sidebar of Files.
|
||||||
|
- Updated the initial directory of Files to the Root directory.
|
||||||
|
- Armbian 22.02 armhf/arm64/amd64 platform tests passed [@igorpecovnik ](https://github.com/igorpecovnik)
|
||||||
|
- Elementary OS 6.1 Jólnir amd64 platform tests passed [@alvarosamudio ](https://github.com/alvarosamudio)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix an issue in Files where the backspace button would trigger a return to the previous level of the directory when creating a folder.
|
||||||
|
- Fix the display problem of application list in CPU widget.
|
||||||
|
- Fix the problem that the ipv6 of the application cannot be opened
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- Interfaces related to "zerotier"
|
||||||
|
|
||||||
|
## [0.2.10] - 2022-03-10
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Added CasaOS own file manager, now you can browse, upload, download files from the system, even edit code online, preview photos and videos through it. It will appear in the first position of Apps.
|
||||||
|
- Added CPU core count display and memory capacity display.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Optimized the rendering performance of the home page.
|
||||||
|
- Optimized the internationalization display of the time widget.
|
||||||
|
- Show the icon of the stopped application as gray.
|
||||||
|
- Unify the animation of the drop-down menu.
|
||||||
|
- Optimize the display of the application drop-down menu.
|
||||||
|
- Replaced the default font to optimize the display.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix the problem of failed to create storage space
|
||||||
|
|
||||||
|
## [0.2.9] - 2022-02-18
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Add a simple notification function
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Custom installation of new parameters(Capabilities,Hostname,Privileged)
|
||||||
|
- Update front-end translation [@SemVer](https://github.com/zarevskaya) [@koboldMaki](https://github.com/koboldMaki) [@sgastol](https://github.com/sgastol) [@delki8](https://github.com/delki8)
|
||||||
|
|
||||||
|
- Modify the default location and name of the usb mount
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix the problem of being indexed by search engines
|
||||||
|
- Fix some style display issues
|
||||||
|
- Solve hard drive can't be formatted, can't finish adding storage
|
||||||
|
|
||||||
|
## [0.2.8] - 2022-01-30
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Add USB disk device display
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update translation [@baptiste313](https://github.com/baptiste313) [@thueske](https://github.com/thueske)
|
||||||
|
- Compatible with more types of drives
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix the language initialization bug
|
||||||
|
- Fix the problem that the login page could not be displayed
|
||||||
|
- Fix missing translated content
|
||||||
|
|
||||||
|
## [0.2.7] - 2022.01.26
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Apply multilingual support
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- Fix an injectable execution bug
|
||||||
|
|
||||||
|
## [0.2.6] - 2022.01.26
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Add a bug report panel.
|
||||||
|
- App Store apps start supporting multiple languages
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix a disk that cannot be formatted under certain circumstances
|
||||||
|
|
||||||
|
## [0.2.5] - 2022.01.24
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Storage Manager
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update Disk widget
|
||||||
|
- Update language files [@ImOstrovskiy](https://github.com/ImOstrovskiy) [@baptiste313](https://github.com/baptiste313)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- File synchronization issues
|
||||||
|
- Fix the app store classification problem
|
||||||
|
|
||||||
|
## [0.2.4] - 2021.12.30
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Brand new App Store
|
||||||
|
- Optimize request method
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix Sync panel width display error.
|
||||||
|
- Fix App panel width display error.
|
||||||
|
|
||||||
|
## [0.2.3] - 2021.12.11
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Add detailed CPU and memory statistics.
|
||||||
|
- Add the multi-language function and add Chinese translation.
|
||||||
|
- Add the function to modify the search engine.
|
||||||
|
- Add the function of modifying the WebUI port
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update update script
|
||||||
|
- Preprocessing usb automounting
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Volume path problem when customizing the installation of applications
|
||||||
|
- Fix Cpu and Ram usage display error
|
||||||
|
- Fix translation errors
|
||||||
|
- Fixed an error when importing and exporting appfile.
|
||||||
|
|
||||||
|
## [0.2.2] - 2021.12.02
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- UI adjustment
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix the problem of data display error when manually installing apps
|
||||||
|
- Fix some spelling problems
|
||||||
|
- Fix the bug of synchronization module
|
||||||
|
|
||||||
|
## [0.2.1] - 2021.11.25
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix Sync display error
|
||||||
|
- Fix Sync Downoad url error
|
||||||
|
- Fix Smart Block display error
|
||||||
|
- Fix widgets settings dispaly error
|
||||||
|
- Fix application installation path error
|
||||||
|
|
||||||
|
## [0.2.0] - 2021.11.25
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Add sync function
|
||||||
|
|
||||||
|
|
||||||
|
## [0.1.11] - 2021.11.10
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Adaptation of cell phone terminals
|
||||||
|
- Optimize user experience
|
||||||
|
- Replaced the default background
|
||||||
|
- Optimized the display performance and fixed some bugs
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Resolve application installation path errors
|
||||||
|
|
||||||
|
## [0.1.10] - 2021.11.04
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Add application terminal
|
||||||
|
- Add application logs
|
||||||
|
- Add system logs
|
||||||
|
- Add App Store for installation
|
||||||
|
|
||||||
|
## [0.1.9] - 2021.11.01 [YANKED]
|
||||||
|
|
||||||
|
## [0.1.8] - 2021.10.27
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Add system terminal
|
||||||
|
- Add the ability to modify the user name and password
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Experience optimization
|
||||||
|
- Improve single user management function
|
||||||
|
- Fixed Disk widget display error
|
||||||
|
- Fixed Username display error after change
|
||||||
|
- Adaptation for mobile access
|
||||||
|
|
||||||
|
## [0.1.7] - 2021.10.22
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Add user authentication module, Login page and initialization page.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix the problem that the application could not start after the system restarted.
|
||||||
|
- Home storage space data display exception
|
||||||
|
- Script override causes application loss after installation
|
||||||
|
- Fix docker network error
|
||||||
|
|
||||||
|
## [0.1.6] - 2021.10.19
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Add app icon auto-fill via docker image name.
|
||||||
|
- Add a file selector for app install.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Modify import reminder.
|
||||||
|
- Optimize the application installation process
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed an issue with the app were it would disappear when the app was modified.
|
||||||
|
- Fixed device selector default dir to /dev
|
||||||
|
|
||||||
|
## [0.1.5] - 2021.10.15
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Add CPU RAM Status with widget
|
||||||
|
- Add Disk Info with widget
|
||||||
|
- Realize automatic loading of widgets
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Enhance the Docker cli import experience and automatically fill in the folders that need to be mounted
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- Remove Weather widget.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- AppFile upload does not pass verification
|
||||||
|
- The setting menu of the app is displayed abnormally when the browser window is too narrow
|
||||||
|
- The port is occupied and the program cannot start
|
||||||
|
- Fix display bugs when windows size less than 1024px
|
||||||
|
|
||||||
|
## [0.1.4] - 2021.09.30
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Import and export of application configuration files
|
||||||
|
- Automatic parsing of docker commands
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Improve the program release process
|
||||||
|
- Application installation process UX/UI optimization
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Authentication failure during the operation, resulting in the need to re-login
|
||||||
|
|
||||||
|
## [0.1.3] - 2021.09.29 [YANKED]
|
||||||
|
|
||||||
|
## [0.1.2] - 2021.09.28
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Application modification and new creation failure issues
|
||||||
|
|
||||||
|
## [0.1.1] - 2021.09.27
|
||||||
|
|
||||||
|
## [0.1.0] - 2021.09.26
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Application Center
|
||||||
33
DEVELOPING.md
Normal file
33
DEVELOPING.md
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# CasaOS Development
|
||||||
|
Here we will describe the steps required to setup a development environment with CasaOS.
|
||||||
|
|
||||||
|
- [Setting up development environment](#setting-up-development-environment)
|
||||||
|
- [Pre-requisites](#pre-requisites)
|
||||||
|
- [1. Fork the Repo](#1.-fork-the-repo)
|
||||||
|
- [2. Clone the repo down](#2.-clone-the-repo-down)
|
||||||
|
- [3. Install dependencies](#3.-install-dependencies)
|
||||||
|
|
||||||
|
|
||||||
|
## Setting up a development environment
|
||||||
|
In this section we will walk you through the general process of setting up your development environment to get started.
|
||||||
|
|
||||||
|
### Pre-requisites
|
||||||
|
The following must be installed in order to get started. The details of how to install them is outside the scope of this doc, but generally they should be able to be installed with your systems package manager (apt, yum, brew, choco, etc).
|
||||||
|
- Go > v1.17.0
|
||||||
|
- yarn
|
||||||
|
- node.js
|
||||||
|
|
||||||
|
### 1. Fork the Repo
|
||||||
|
[Fork the repo](https://docs.github.com/en/get-started/quickstart/fork-a-repo) onto your own GitHub account for developing.
|
||||||
|
|
||||||
|
### 2. Clone the repo down
|
||||||
|
1. Navigate into your go workspace (check with `go env GOPATH`).
|
||||||
|
2. Navigate to the appropriate path for github. It should look something like this: `<path from GOPATH>/github.com/<GitHub Username>/`. If it doesn't exist create it.
|
||||||
|
3. Clone down the repo with the following: `git clone --recurse-submodules --remote-submodules https://github.com/<your GitHub Username>/CasaOS.git`
|
||||||
|
|
||||||
|
### 3. Install dependencies
|
||||||
|
1. `cd UI`
|
||||||
|
2. `yarn install`
|
||||||
|
3. `yarn build`
|
||||||
|
4. `cd ..`
|
||||||
|
5. `go get`
|
||||||
225
README.md
225
README.md
@@ -1,63 +1,151 @@
|
|||||||
# CasaOS - A simple, easy-to-use, elegant open-source Home Cloud system.
|
# CasaOS - Your Home Cloud OS
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
[](https://github.com/IceWhaleTech/CasaOS)
|
<!-- Readme i18n links -->
|
||||||
[](https://github.com/IceWhaleTech/CasaOS/pulls)
|
<!-- > English | [中文](#) | [Français](#) -->
|
||||||
[](https://github.com/IceWhaleTech/CasaOS/issues)
|
|
||||||
[](https://github.com/IceWhaleTech/CasaOS/stargazers)
|
|
||||||
[](https://discord.gg/Gx4BCEtHjx)
|
|
||||||
|
|
||||||
CasaOS is an open-source Home Cloud system based on the Docker ecosystem and designed for home scenarios. It is committed to building the world's most simple, easy-to-use, and elegant Home Cloud system.
|
<p align="center">
|
||||||
|
<!-- CasaOS Banner -->
|
||||||
|
<picture>
|
||||||
|
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/IceWhaleTech/logo/main/casaos/casaos_banner_dark_night_800x300.png">
|
||||||
|
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/IceWhaleTech/logo/main/casaos/casaos_banner_twilight_blue_800x300.png">
|
||||||
|
<img alt="CasaOS" src="https://raw.githubusercontent.com/IceWhaleTech/logo/main/casaos/casaos_banner_twilight_blue_800x300.png">
|
||||||
|
</picture>
|
||||||
|
<br/>
|
||||||
|
<i>Connect with the community developing HOME CLOUD, creating self-sovereign, and defining the future of the distributed cloud.</i>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<!-- CasaOS Badges -->
|
||||||
|
<a href="https://github.com/IceWhaleTech/CasaOS" target="_blank">
|
||||||
|
<img alt="CasaOS Version" src="https://img.shields.io/github/v/release/IceWhaleTech/CasaOS?color=162453&style=flat-square&label=CasaOS" />
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/IceWhaleTech/CasaOS/blob/main/LICENSE" target="_blank">
|
||||||
|
<img alt="CasaOS License" src="https://img.shields.io/github/license/IceWhaleTech/CasaOS?color=162453&style=flat-square&label=License" />
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/IceWhaleTech/CasaOS/pulls" target="_blank">
|
||||||
|
<img alt="CasaOS Pull Requests" src="https://img.shields.io/github/issues-pr/IceWhaleTech/CasaOS?color=162453&style=flat-square&label=PRs" />
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/IceWhaleTech/CasaOS/issues" target="_blank">
|
||||||
|
<img alt="CasaOS Issues" src="https://img.shields.io/github/issues/IceWhaleTech/CasaOS?color=162453&style=flat-square&label=Issues" />
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/IceWhaleTech/CasaOS/stargazers" target="_blank">
|
||||||
|
<img alt="CasaOS Stargazers" src="https://img.shields.io/github/stars/IceWhaleTech/CasaOS?color=162453&style=flat-square&label=Stars" />
|
||||||
|
</a>
|
||||||
|
<!-- <a href="https://github.com/IceWhaleTech/CasaOS/releases" target="_blank">
|
||||||
|
<img alt="CasaOS Downloads" src="https://img.shields.io/github/downloads/IceWhaleTech/CasaOS/total?color=162453&style=flat-square" />
|
||||||
|
</a> -->
|
||||||
|
<br/>
|
||||||
|
<!-- CasaOS Community -->
|
||||||
|
<a href="https://discord.gg/knqAbbBbeX" target="_blank">
|
||||||
|
<img alt="IceWhale Discord" src="https://img.shields.io/discord/884667213326463016?color=162453&style=flat-square&label=Discord&logo=discord&logoColor=fff" />
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/IceWhaleTech/CasaOS/discussions" target="_blank">
|
||||||
|
<img alt="CasaOS GitHub Discussions" src="https://img.shields.io/github/discussions/IceWhaleTech/CasaOS?color=162453&style=flat-square&label=Discussions&logo=github" />
|
||||||
|
</a>
|
||||||
|
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||||
|
<a href="#credits"><img alt="All Contributors" src="https://img.shields.io/static/v1?label=All%20Contributors&message=15&color=162453&style=flat-square&logo=Handshake&logoColor=fff" /></a>
|
||||||
|
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||||
|
<br/>
|
||||||
|
<!-- CasaOS Links -->
|
||||||
|
<a href="https://www.casaos.io" target="_blank">Website</a> |
|
||||||
|
<a href="http://demo.casaos.io" target="_blank">Demo</a> |
|
||||||
|
<a href="https://github.com/IceWhaleTech/CasaOS" target="_blank">GitHub</a>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<!-- CasaOS Snapshots -->
|
||||||
|
<kbd>
|
||||||
|
<picture>
|
||||||
|
<source media="(prefers-color-scheme: dark)" srcset="snapshot-dark.jpg">
|
||||||
|
<source media="(prefers-color-scheme: light)" srcset="snapshot-light.jpg">
|
||||||
|
<img alt="CasaOS Snapshot" src="snapshot-light.jpg">
|
||||||
|
</picture>
|
||||||
|
</kbd>
|
||||||
|
</p>
|
||||||
|
|
||||||
IceWhale team believes that through community-driven collaborative innovation and open communication with global developers, we can reshape the digital home experience like never before.
|
## Why do we need Home Cloud?
|
||||||
|
|
||||||

|
Think about it seriously. Is control of our data, smart devices and digital assets now only in the hands of some big company?
|
||||||

|
|
||||||
|
- Is your photo album saved in their cloud service?
|
||||||
|
- Do your thermostats, monitors, lamps need to be used through their cloud services?
|
||||||
|
- Do your personal documents, memos, contacts, passwords, etc. reside in their cloud storage services?
|
||||||
|
- Are you just going to have to accept their decisions when they decide to change prices, review content or even discontinue services?
|
||||||
|
|
||||||
|
It sounds ridiculous, doesn't it? We are losing control of our own data!
|
||||||
|
|
||||||
|
Our ideal home cloud is one where you can manage all your data, devices and data assets very easily. In your own home, you have absolute control.
|
||||||
|
|
||||||
|
> If you think what we are doing is valuable. Please **give us a star ⭐** and **fork it 🤞**!
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Friendly UI designed for home scenarios
|
||||||
|
- No code, no forms, intuitive, design for humanity
|
||||||
|
- Multiple hardware and base system support
|
||||||
|
- ZimaBoard, NUC, RPi, old computers, whatever is available.
|
||||||
|
- Selected apps in the app store, one-click installation
|
||||||
|
- Nextcloud, HomeAssiant, AdGuard, Jellyfin, *arr and more!
|
||||||
|
- Easily install numerous Docker apps
|
||||||
|
- Over 100,000 apps from the Docker ecosystem can be easily installed
|
||||||
|
- Elegant drive and file management
|
||||||
|
- What you see is what you get. No technical background required.
|
||||||
|
- Well-designed system/app widgets
|
||||||
|
- What you care about, at a glance. Resource usage, app status, and more!
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
> ⚠️ Note:
|
CasaOS fully supports ZimaBoard, Intel NUC, and Raspberry Pi. Also, more computers and development boards and fully compatible with Ubuntu, Debian, Raspberry Pi OS, and CentOS with one-liner installation.
|
||||||
>
|
|
||||||
> CasaOS is still in the early development stage and may vary significantly with the final release. Feel free to test run and share your feedback in the [Discord server](https://discord.gg/Gx4BCEtHjx)!
|
### Hardware Compatibility
|
||||||
|
|
||||||
|
- amd64 / x86-64
|
||||||
|
- arm64
|
||||||
|
- armv7
|
||||||
|
|
||||||
|
### System Compatibility
|
||||||
|
|
||||||
|
Official Support
|
||||||
|
- Debian 11 (✅ Tested, Recommended)
|
||||||
|
- Ubuntu Server 20.04 (✅ Tested)
|
||||||
|
- Raspberry Pi OS (✅ Tested)
|
||||||
|
|
||||||
|
Community Support
|
||||||
|
- Elementary 6.1 (✅ Tested)
|
||||||
|
- Armbian 22.04 (✅ Tested)
|
||||||
|
- Alpine (🚧 Not Fully Tested Yet)
|
||||||
|
- OpenWrt (🚧 Not Fully Tested Yet)
|
||||||
|
- ArchLinux (🚧 Not Fully Tested Yet)
|
||||||
|
|
||||||
### Quick Setup CasaOS
|
### Quick Setup CasaOS
|
||||||
|
|
||||||
Fresh install a system from the list below and run the this command:
|
Freshly install a system from the list above and run this command:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
wget -qO- https://get.icewhale.io/casaos.sh | bash
|
wget -qO- https://get.casaos.io | sudo bash
|
||||||
```
|
```
|
||||||
|
|
||||||
or
|
or
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
curl -fsSL https://get.icewhale.io/casaos.sh | bash
|
curl -fsSL https://get.casaos.io | sudo bash
|
||||||
```
|
```
|
||||||
|
|
||||||
### System Compatibility
|
### Uninstall CasaOS
|
||||||
|
|
||||||
- Ubuntu Server 20.04 amd64 (✅ Recommend, Tested)
|
|
||||||
- Raspberry Pi Lite OS aarch64/arm64 (⚠️ Not Fully Tested Yet)
|
|
||||||
- Debian 11 amd64 (⚠️ Not Fully Tested Yet)
|
|
||||||
- OpenWrt 21.02 amd64 (⚠️ Not Fully Tested Yet)
|
|
||||||
- OpenWrt 21.02 aarch64/arm64 (⚠️ Not Fully Tested Yet)
|
|
||||||
|
|
||||||
|
|
||||||
## Key Features
|
v0.3.3 or newer
|
||||||
|
|
||||||
- UI designed for home scenarios - simple, elegant, and easy-to-use
|
```sh
|
||||||
- Quick Docker app installation with only three steps, plus automatic management
|
casaos-uninstall
|
||||||
- App Store for Home Cloud 🚧
|
```
|
||||||
- Home data/digital asset management 🚧
|
|
||||||
- Smart home manager 🚧
|
|
||||||
|
|
||||||
🚧 is under development.
|
Before v0.3.3
|
||||||
|
|
||||||
We are actively moving forward with development, and you are more than welcome to share any idea with us!
|
```sh
|
||||||
|
curl -fsSL https://get.icewhale.io/casaos-uninstall.sh | sudo bash
|
||||||
|
```
|
||||||
|
|
||||||
|
## Community
|
||||||
## Community
|
|
||||||
|
|
||||||
The word Casa comes from the Spanish word for "home". Project CasaOS originated as a pre-installed system for crowdfunded product [ZimaBoard](https://www.zimaboard.com) on Kickstarter.
|
The word Casa comes from the Spanish word for "home". Project CasaOS originated as a pre-installed system for crowdfunded product [ZimaBoard](https://www.zimaboard.com) on Kickstarter.
|
||||||
|
|
||||||
@@ -65,16 +153,67 @@ After looking at many systems and software on the market, the team found no serv
|
|||||||
|
|
||||||
So, we set out to build this open source project to develop CasaOS with our own hands, everyone in the community, and you.
|
So, we set out to build this open source project to develop CasaOS with our own hands, everyone in the community, and you.
|
||||||
|
|
||||||
> A warm welcome for you to share and discuss your great ideas in the [Discord server](https://discord.gg/Gx4BCEtHjx)!
|
We believes that through community-driven collaborative innovation and open communication with global developers, we can reshape the digital home experience like never before.
|
||||||
|
|
||||||
[](https://discord.gg/Gx4BCEtHjx)
|
**A warm welcome for you to get help or share great ideas in the [Discord](https://discord.gg/knqAbbBbeX)!**
|
||||||
|
|
||||||
|
[](https://discord.gg/knqAbbBbeX)
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
## Maintainers
|
CasaOS is a community-driven open source project and the people involved are CasaOS users. That means CasaOS will always need contributions from community members just like you!
|
||||||
- Jerry Liu
|
|
||||||
- Link Liang
|
- See <https://wiki.casaos.io/en/contribute> for ways of contribution to CasaOS
|
||||||
- Ober Zhang
|
- See <https://wiki.casaos.io/en/contribute/development> if you want to be involved in code contribution specificially
|
||||||
- Zyaire Ann
|
|
||||||
- John Guan
|
## Credits
|
||||||
- Right here, waiting for YOU!
|
|
||||||
|
Many thanks to everyone who has helped CasaOS so far!
|
||||||
|
|
||||||
|
Everyone's contribution is greatly appreciated. ([Emoji Key](https://allcontributors.org/docs/en/emoji-key))
|
||||||
|
|
||||||
|
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
||||||
|
<!-- prettier-ignore-start -->
|
||||||
|
<!-- markdownlint-disable -->
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td align="center"><a href="https://github.com/jerrykuku"><img src="https://avatars.githubusercontent.com/u/9485680?v=4?s=100" width="100px;" alt=""/><br /><sub><b>老竭力</b></sub></a><br /><a href="https://github.com/IceWhaleTech/CasaOS/commits?author=jerrykuku" title="Code">💻</a> <a href="https://github.com/IceWhaleTech/CasaOS/commits?author=jerrykuku" title="Documentation">📖</a> <a href="#ideas-jerrykuku" title="Ideas, Planning, & Feedback">🤔</a> <a href="#infra-jerrykuku" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#maintenance-jerrykuku" title="Maintenance">🚧</a> <a href="#platform-jerrykuku" title="Packaging/porting to new platform">📦</a> <a href="#question-jerrykuku" title="Answering Questions">💬</a> <a href="https://github.com/IceWhaleTech/CasaOS/pulls?q=is%3Apr+reviewed-by%3Ajerrykuku" title="Reviewed Pull Requests">👀</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/LinkLeong"><img src="https://avatars.githubusercontent.com/u/13556972?v=4?s=100" width="100px;" alt=""/><br /><sub><b>link</b></sub></a><br /><a href="https://github.com/IceWhaleTech/CasaOS/commits?author=LinkLeong" title="Code">💻</a> <a href="https://github.com/IceWhaleTech/CasaOS/commits?author=LinkLeong" title="Documentation">📖</a> <a href="#ideas-LinkLeong" title="Ideas, Planning, & Feedback">🤔</a> <a href="#infra-LinkLeong" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#maintenance-LinkLeong" title="Maintenance">🚧</a> <a href="#question-LinkLeong" title="Answering Questions">💬</a> <a href="https://github.com/IceWhaleTech/CasaOS/pulls?q=is%3Apr+reviewed-by%3ALinkLeong" title="Reviewed Pull Requests">👀</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/tigerinus"><img src="https://avatars.githubusercontent.com/u/7172560?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tiger Wang (王豫)</b></sub></a><br /><a href="https://github.com/IceWhaleTech/CasaOS/commits?author=tigerinus" title="Code">💻</a> <a href="https://github.com/IceWhaleTech/CasaOS/commits?author=tigerinus" title="Documentation">📖</a> <a href="#ideas-tigerinus" title="Ideas, Planning, & Feedback">🤔</a> <a href="#infra-tigerinus" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#maintenance-tigerinus" title="Maintenance">🚧</a> <a href="#mentoring-tigerinus" title="Mentoring">🧑🏫</a> <a href="#security-tigerinus" title="Security">🛡️</a> <a href="#question-tigerinus" title="Answering Questions">💬</a> <a href="https://github.com/IceWhaleTech/CasaOS/pulls?q=is%3Apr+reviewed-by%3Atigerinus" title="Reviewed Pull Requests">👀</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/Lauren-ED209"><img src="https://avatars.githubusercontent.com/u/8243355?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lauren</b></sub></a><br /><a href="#ideas-Lauren-ED209" title="Ideas, Planning, & Feedback">🤔</a> <a href="#fundingFinding-Lauren-ED209" title="Funding Finding">🔍</a> <a href="#projectManagement-Lauren-ED209" title="Project Management">📆</a> <a href="#question-Lauren-ED209" title="Answering Questions">💬</a> <a href="https://github.com/IceWhaleTech/CasaOS/commits?author=Lauren-ED209" title="Tests">⚠️</a></td>
|
||||||
|
<td align="center"><a href="https://JohnGuan.Cn"><img src="https://avatars.githubusercontent.com/u/3358477?v=4?s=100" width="100px;" alt=""/><br /><sub><b>John Guan</b></sub></a><br /><a href="#blog-JohnGuan" title="Blogposts">📝</a> <a href="#content-JohnGuan" title="Content">🖋</a> <a href="https://github.com/IceWhaleTech/CasaOS/commits?author=JohnGuan" title="Documentation">📖</a> <a href="#ideas-JohnGuan" title="Ideas, Planning, & Feedback">🤔</a> <a href="#eventOrganizing-JohnGuan" title="Event Organizing">📋</a> <a href="#mentoring-JohnGuan" title="Mentoring">🧑🏫</a> <a href="#question-JohnGuan" title="Answering Questions">💬</a> <a href="https://github.com/IceWhaleTech/CasaOS/pulls?q=is%3Apr+reviewed-by%3AJohnGuan" title="Reviewed Pull Requests">👀</a></td>
|
||||||
|
<td align="center"><a href="https://blog.tippybits.com"><img src="https://avatars.githubusercontent.com/u/17506770?v=4?s=100" width="100px;" alt=""/><br /><sub><b>David Tippett</b></sub></a><br /><a href="https://github.com/IceWhaleTech/CasaOS/commits?author=dtaivpp" title="Documentation">📖</a> <a href="#ideas-dtaivpp" title="Ideas, Planning, & Feedback">🤔</a> <a href="#question-dtaivpp" title="Answering Questions">💬</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/zarevskaya"><img src="https://avatars.githubusercontent.com/u/60230221?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Skaya</b></sub></a><br /><a href="#mentoring-zarevskaya" title="Mentoring">🧑🏫</a> <a href="#question-zarevskaya" title="Answering Questions">💬</a> <a href="#tutorial-zarevskaya" title="Tutorials">✅</a> <a href="#translation-zarevskaya" title="Translation">🌍</a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center"><a href="https://github.com/AuthorShin"><img src="https://avatars.githubusercontent.com/u/4959043?v=4?s=100" width="100px;" alt=""/><br /><sub><b>AuthorShin</b></sub></a><br /><a href="https://github.com/IceWhaleTech/CasaOS/commits?author=AuthorShin" title="Tests">⚠️</a> <a href="https://github.com/IceWhaleTech/CasaOS/issues?q=author%3AAuthorShin" title="Bug reports">🐛</a> <a href="#question-AuthorShin" title="Answering Questions">💬</a> <a href="#ideas-AuthorShin" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/baptiste313"><img src="https://avatars.githubusercontent.com/u/93325157?v=4?s=100" width="100px;" alt=""/><br /><sub><b>baptiste313</b></sub></a><br /><a href="#translation-baptiste313" title="Translation">🌍</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/DrMxrcy"><img src="https://avatars.githubusercontent.com/u/58747968?v=4?s=100" width="100px;" alt=""/><br /><sub><b>DrMxrcy</b></sub></a><br /><a href="https://github.com/IceWhaleTech/CasaOS/commits?author=DrMxrcy" title="Tests">⚠️</a> <a href="#ideas-DrMxrcy" title="Ideas, Planning, & Feedback">🤔</a> <a href="#question-DrMxrcy" title="Answering Questions">💬</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/Joooost"><img src="https://avatars.githubusercontent.com/u/12090673?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Joooost</b></sub></a><br /><a href="#ideas-Joooost" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||||
|
<td align="center"><a href="https://potyarkin.ml"><img src="https://avatars.githubusercontent.com/u/334908?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Vitaly Potyarkin</b></sub></a><br /><a href="#ideas-sio" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/bearfrieze"><img src="https://avatars.githubusercontent.com/u/1023813?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Bjørn Friese</b></sub></a><br /><a href="#ideas-bearfrieze" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/Protektor-Desura"><img src="https://avatars.githubusercontent.com/u/1195496?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Protektor</b></sub></a><br /><a href="https://github.com/IceWhaleTech/CasaOS/issues?q=author%3AProtektor-Desura" title="Bug reports">🐛</a> <a href="#ideas-Protektor-Desura" title="Ideas, Planning, & Feedback">🤔</a> <a href="#question-Protektor-Desura" title="Answering Questions">💬</a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center"><a href="https://github.com/llwaini"><img src="https://avatars.githubusercontent.com/u/59589857?v=4?s=100" width="100px;" alt=""/><br /><sub><b>llwaini</b></sub></a><br /><a href="#projectManagement-llwaini" title="Project Management">📆</a> <a href="https://github.com/IceWhaleTech/CasaOS/commits?author=llwaini" title="Tests">⚠️</a> <a href="#tutorial-llwaini" title="Tutorials">✅</a></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- markdownlint-restore -->
|
||||||
|
<!-- prettier-ignore-end -->
|
||||||
|
|
||||||
|
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||||
|
|
||||||
|
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
|
||||||
|
Detailed changes for each release are documented in the [release notes](https://github.com/IceWhaleTech/CasaOS/releases).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://dashboard.trackgit.com/token/l5q8egi92tfhlxd70l2l">
|
||||||
|
<img src="https://us-central1-trackgit-analytics.cloudfunctions.net/token/ping/l5q8egi92tfhlxd70l2l" alt="trackgit-views" />
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|||||||
1
UI
1
UI
Submodule UI deleted from a74be104eb
194
build/scripts/migration/script.d/03-migrate-casaos.sh
Normal file
194
build/scripts/migration/script.d/03-migrate-casaos.sh
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# functions
|
||||||
|
__info() {
|
||||||
|
echo -e "🟩 ${1}"
|
||||||
|
}
|
||||||
|
|
||||||
|
__info_done() {
|
||||||
|
echo -e "✅ ${1}"
|
||||||
|
}
|
||||||
|
|
||||||
|
__warning() {
|
||||||
|
echo -e "🟨 ${1}"
|
||||||
|
}
|
||||||
|
|
||||||
|
__error() {
|
||||||
|
echo "🟥 ${1}"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
__is_version_gt() {
|
||||||
|
test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" != "$1"
|
||||||
|
}
|
||||||
|
__normalize_version() {
|
||||||
|
local version
|
||||||
|
if [ "${1::1}" = "v" ]; then
|
||||||
|
version="${1:1}"
|
||||||
|
else
|
||||||
|
version="${1}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$version"
|
||||||
|
}
|
||||||
|
|
||||||
|
__is_migration_needed() {
|
||||||
|
local version1
|
||||||
|
local version2
|
||||||
|
|
||||||
|
version1=$(__normalize_version "${1}")
|
||||||
|
version2=$(__normalize_version "${2}")
|
||||||
|
|
||||||
|
if [ "${version1}" = "${version2}" ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "CURRENT_VERSION_NOT_FOUND" = "${version1}" ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "LEGACY_WITHOUT_VERSION" = "${version1}" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
__is_version_gt "${version2}" "${version1}"
|
||||||
|
}
|
||||||
|
|
||||||
|
__get_download_domain(){
|
||||||
|
local region
|
||||||
|
# Use ipconfig.io/country and https://ifconfig.io/country_code to get the country code
|
||||||
|
region=$(curl --connect-timeout 2 -s ipconfig.io/country || echo "")
|
||||||
|
if [ "${region}" = "" ]; then
|
||||||
|
region=$(curl --connect-timeout 2 -s https://ifconfig.io/country_code || echo "")
|
||||||
|
fi
|
||||||
|
if [[ "${region}" = "China" ]] || [[ "${region}" = "CN" ]]; then
|
||||||
|
echo "https://casaos.oss-cn-shanghai.aliyuncs.com/"
|
||||||
|
else
|
||||||
|
echo "https://github.com/"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
DOWNLOAD_DOMAIN=$(__get_download_domain)
|
||||||
|
|
||||||
|
BUILD_PATH=$(dirname "${BASH_SOURCE[0]}")/../../..
|
||||||
|
SOURCE_ROOT=${BUILD_PATH}/sysroot
|
||||||
|
|
||||||
|
APP_NAME="casaos"
|
||||||
|
|
||||||
|
# check if migration is needed
|
||||||
|
SOURCE_BIN_PATH=${SOURCE_ROOT}/usr/bin
|
||||||
|
SOURCE_BIN_FILE=${SOURCE_BIN_PATH}/${APP_NAME}
|
||||||
|
|
||||||
|
CURRENT_BIN_PATH=/usr/bin
|
||||||
|
CURRENT_BIN_PATH_LEGACY=/usr/local/bin
|
||||||
|
CURRENT_BIN_FILE=${CURRENT_BIN_PATH}/${APP_NAME}
|
||||||
|
CURRENT_BIN_FILE_LEGACY=$(realpath -e ${CURRENT_BIN_PATH_LEGACY}/${APP_NAME} || which ${APP_NAME} || echo CURRENT_BIN_FILE_LEGACY_NOT_FOUND)
|
||||||
|
|
||||||
|
SOURCE_VERSION="$(${SOURCE_BIN_FILE} -v)"
|
||||||
|
CURRENT_VERSION="$(${CURRENT_BIN_FILE} -v || ${CURRENT_BIN_FILE_LEGACY} -v || (stat "${CURRENT_BIN_FILE_LEGACY}" >/dev/null && echo LEGACY_WITHOUT_VERSION) || echo CURRENT_VERSION_NOT_FOUND)"
|
||||||
|
|
||||||
|
__info_done "CURRENT_VERSION: ${CURRENT_VERSION}"
|
||||||
|
__info_done "SOURCE_VERSION: ${SOURCE_VERSION}"
|
||||||
|
|
||||||
|
NEED_MIGRATION=$(__is_migration_needed "${CURRENT_VERSION}" "${SOURCE_VERSION}" && echo "true" || echo "false")
|
||||||
|
|
||||||
|
if [ "${NEED_MIGRATION}" = "false" ]; then
|
||||||
|
__info_done "Migration is not needed."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
ARCH="unknown"
|
||||||
|
|
||||||
|
case $(uname -m) in
|
||||||
|
x86_64)
|
||||||
|
ARCH="amd64"
|
||||||
|
;;
|
||||||
|
aarch64)
|
||||||
|
ARCH="arm64"
|
||||||
|
;;
|
||||||
|
armv7l)
|
||||||
|
ARCH="arm-7"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
__error "Unsupported architecture"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
__info "ARCH: ${ARCH}"
|
||||||
|
|
||||||
|
MIGRATION_SERVICE_DIR=${1}
|
||||||
|
|
||||||
|
if [ -z "${MIGRATION_SERVICE_DIR}" ]; then
|
||||||
|
MIGRATION_SERVICE_DIR=${BUILD_PATH}/scripts/migration/service.d/${APP_NAME}
|
||||||
|
fi
|
||||||
|
MIGRATION_LIST_FILE=${MIGRATION_SERVICE_DIR}/migration.list
|
||||||
|
MIGRATION_PATH=()
|
||||||
|
|
||||||
|
CURRENT_VERSION_FOUND="false"
|
||||||
|
|
||||||
|
# a VERSION_PAIR looks like "v0.3.5 <url>"
|
||||||
|
#
|
||||||
|
# - "v0.3.5" is the current version installed on this host
|
||||||
|
# - "<url>" is the url of the migration tool
|
||||||
|
while read -r VERSION_PAIR; do
|
||||||
|
if [ -z "${VERSION_PAIR}" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# obtain "v0.3.5" from "v0.3.5 v0.3.6-alpha2"
|
||||||
|
VER1=$(echo "${VERSION_PAIR}" | cut -d' ' -f1)
|
||||||
|
|
||||||
|
# obtain "<url>" from "v0.3.5 <url>"
|
||||||
|
URL=$(eval echo "${VERSION_PAIR}" | cut -d' ' -f2)
|
||||||
|
|
||||||
|
if [ "${CURRENT_VERSION}" = "${VER1// /}" ] || [ "${CURRENT_VERSION}" = "LEGACY_WITHOUT_VERSION" ]; then
|
||||||
|
CURRENT_VERSION_FOUND="true"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${CURRENT_VERSION_FOUND}" = "true" ]; then
|
||||||
|
MIGRATION_PATH+=("${URL// /}")
|
||||||
|
fi
|
||||||
|
done <"${MIGRATION_LIST_FILE}"
|
||||||
|
|
||||||
|
if [ ${#MIGRATION_PATH[@]} -eq 0 ]; then
|
||||||
|
__warning "No migration path found from ${CURRENT_VERSION} to ${SOURCE_VERSION}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
pushd "${MIGRATION_SERVICE_DIR}"
|
||||||
|
|
||||||
|
{
|
||||||
|
for URL in "${MIGRATION_PATH[@]}"; do
|
||||||
|
MIGRATION_TOOL_FILE=$(basename "${URL}")
|
||||||
|
|
||||||
|
if [ -f "${MIGRATION_TOOL_FILE}" ]; then
|
||||||
|
__info "Migration tool ${MIGRATION_TOOL_FILE} exists. Skip downloading."
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
__info "Dowloading ${URL}..."
|
||||||
|
curl -fsSL -o "${MIGRATION_TOOL_FILE}" -O "${URL}"
|
||||||
|
done
|
||||||
|
} || {
|
||||||
|
popd
|
||||||
|
__error "Failed to download migration tools"
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
for URL in "${MIGRATION_PATH[@]}"; do
|
||||||
|
MIGRATION_TOOL_FILE=$(basename "${URL}")
|
||||||
|
__info "Extracting ${MIGRATION_TOOL_FILE}..."
|
||||||
|
tar zxvf "${MIGRATION_TOOL_FILE}" || __error "Failed to extract ${MIGRATION_TOOL_FILE}"
|
||||||
|
|
||||||
|
MIGRATION_TOOL_PATH=build/sysroot/usr/bin/${APP_NAME}-migration-tool
|
||||||
|
__info "Running ${MIGRATION_TOOL_PATH}..."
|
||||||
|
${MIGRATION_TOOL_PATH}
|
||||||
|
done
|
||||||
|
} || {
|
||||||
|
popd
|
||||||
|
__error "Failed to extract and run migration tools"
|
||||||
|
}
|
||||||
|
|
||||||
|
popd
|
||||||
3
build/scripts/migration/service.d/casaos/migration.list
Normal file
3
build/scripts/migration/service.d/casaos/migration.list
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
LEGACY_WITHOUT_VERSION ${DOWNLOAD_DOMAIN}IceWhaleTech/CasaOS/releases/download/v0.3.6/linux-${ARCH}-casaos-migration-tool-v0.3.6.tar.gz
|
||||||
|
v0.3.5 ${DOWNLOAD_DOMAIN}IceWhaleTech/CasaOS/releases/download/v0.3.6/linux-${ARCH}-casaos-migration-tool-v0.3.6.tar.gz
|
||||||
|
v0.3.5.1 ${DOWNLOAD_DOMAIN}IceWhaleTech/CasaOS/releases/download/v0.3.6/linux-${ARCH}-casaos-migration-tool-v0.3.6.tar.gz
|
||||||
54
build/scripts/setup/script.d/03-setup-casaos.sh
Executable file
54
build/scripts/setup/script.d/03-setup-casaos.sh
Executable file
@@ -0,0 +1,54 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
BUILD_PATH=$(dirname "${BASH_SOURCE[0]}")/../../..
|
||||||
|
|
||||||
|
APP_NAME_SHORT=casaos
|
||||||
|
|
||||||
|
__get_setup_script_directory_by_os_release() {
|
||||||
|
pushd "$(dirname "${BASH_SOURCE[0]}")/../service.d/${APP_NAME_SHORT}" >/dev/null
|
||||||
|
|
||||||
|
{
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
{
|
||||||
|
source /etc/os-release
|
||||||
|
{
|
||||||
|
pushd "${ID}"/"${VERSION_CODENAME}" >/dev/null
|
||||||
|
} || {
|
||||||
|
pushd "${ID}" >/dev/null
|
||||||
|
} || {
|
||||||
|
pushd "${ID_LIKE}" >/dev/null
|
||||||
|
} || {
|
||||||
|
echo "Unsupported OS: ${ID} ${VERSION_CODENAME} (${ID_LIKE})"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
pwd
|
||||||
|
|
||||||
|
popd >/dev/null
|
||||||
|
|
||||||
|
} || {
|
||||||
|
echo "Unsupported OS: unknown"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
popd >/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
SETUP_SCRIPT_DIRECTORY=$(__get_setup_script_directory_by_os_release)
|
||||||
|
SETUP_SCRIPT_FILENAME="setup-${APP_NAME_SHORT}.sh"
|
||||||
|
|
||||||
|
SETUP_SCRIPT_FILEPATH="${SETUP_SCRIPT_DIRECTORY}/${SETUP_SCRIPT_FILENAME}"
|
||||||
|
|
||||||
|
{
|
||||||
|
echo "🟩 Running ${SETUP_SCRIPT_FILENAME}..."
|
||||||
|
$BASH "${SETUP_SCRIPT_FILEPATH}" "${BUILD_PATH}"
|
||||||
|
} || {
|
||||||
|
echo "🟥 ${SETUP_SCRIPT_FILENAME} failed."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "✅ ${SETUP_SCRIPT_FILENAME} finished."
|
||||||
40
build/scripts/setup/service.d/casaos/arch/setup-casaos.sh
Normal file
40
build/scripts/setup/service.d/casaos/arch/setup-casaos.sh
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
###
|
||||||
|
# @Author: LinkLeong link@icewhale.org
|
||||||
|
# @Date: 2022-08-25 11:41:22
|
||||||
|
# @LastEditors: LinkLeong
|
||||||
|
# @LastEditTime: 2022-08-31 17:54:17
|
||||||
|
# @FilePath: /CasaOS/build/scripts/setup/service.d/casaos/debian/setup-casaos.sh
|
||||||
|
# @Description:
|
||||||
|
|
||||||
|
# @Website: https://www.casaos.io
|
||||||
|
# Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
###
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
APP_NAME="casaos"
|
||||||
|
|
||||||
|
# copy config files
|
||||||
|
CONF_PATH=/etc/casaos
|
||||||
|
OLD_CONF_PATH=/etc/casaos.conf
|
||||||
|
CONF_FILE=${CONF_PATH}/${APP_NAME}.conf
|
||||||
|
CONF_FILE_SAMPLE=${CONF_PATH}/${APP_NAME}.conf.sample
|
||||||
|
|
||||||
|
|
||||||
|
if [ -f "${OLD_CONF_PATH}" ]; then
|
||||||
|
echo "copy old conf"
|
||||||
|
cp "${OLD_CONF_PATH}" "${CONF_FILE}"
|
||||||
|
fi
|
||||||
|
if [ ! -f "${CONF_FILE}" ]; then
|
||||||
|
echo "Initializing config file..."
|
||||||
|
cp -v "${CONF_FILE_SAMPLE}" "${CONF_FILE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf /etc/systemd/system/casaos.service # remove old service file
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
# enable service (without starting)
|
||||||
|
echo "Enabling service..."
|
||||||
|
systemctl enable --force --no-ask-password "${APP_NAME}.service"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../setup-casaos.sh
|
||||||
40
build/scripts/setup/service.d/casaos/debian/setup-casaos.sh
Normal file
40
build/scripts/setup/service.d/casaos/debian/setup-casaos.sh
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
###
|
||||||
|
# @Author: LinkLeong link@icewhale.org
|
||||||
|
# @Date: 2022-08-25 11:41:22
|
||||||
|
# @LastEditors: LinkLeong
|
||||||
|
# @LastEditTime: 2022-08-31 17:54:17
|
||||||
|
# @FilePath: /CasaOS/build/scripts/setup/service.d/casaos/debian/setup-casaos.sh
|
||||||
|
# @Description:
|
||||||
|
|
||||||
|
# @Website: https://www.casaos.io
|
||||||
|
# Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
###
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
APP_NAME="casaos"
|
||||||
|
|
||||||
|
# copy config files
|
||||||
|
CONF_PATH=/etc/casaos
|
||||||
|
OLD_CONF_PATH=/etc/casaos.conf
|
||||||
|
CONF_FILE=${CONF_PATH}/${APP_NAME}.conf
|
||||||
|
CONF_FILE_SAMPLE=${CONF_PATH}/${APP_NAME}.conf.sample
|
||||||
|
|
||||||
|
|
||||||
|
if [ -f "${OLD_CONF_PATH}" ]; then
|
||||||
|
echo "copy old conf"
|
||||||
|
cp "${OLD_CONF_PATH}" "${CONF_FILE}"
|
||||||
|
fi
|
||||||
|
if [ ! -f "${CONF_FILE}" ]; then
|
||||||
|
echo "Initializing config file..."
|
||||||
|
cp -v "${CONF_FILE_SAMPLE}" "${CONF_FILE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf /etc/systemd/system/casaos.service # remove old service file
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
# enable service (without starting)
|
||||||
|
echo "Enabling service..."
|
||||||
|
systemctl enable --force --no-ask-password "${APP_NAME}.service"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../setup-casaos.sh
|
||||||
1
build/scripts/setup/service.d/casaos/ubuntu/setup-casaos.sh
Symbolic link
1
build/scripts/setup/service.d/casaos/ubuntu/setup-casaos.sh
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../debian/setup-casaos.sh
|
||||||
22
build/sysroot/etc/casaos/casaos.conf.sample
Normal file
22
build/sysroot/etc/casaos/casaos.conf.sample
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
[app]
|
||||||
|
PAGE_SIZE = 10
|
||||||
|
RuntimeRootPath = runtime/
|
||||||
|
LogPath = /var/log/casaos/
|
||||||
|
LogSaveName = log
|
||||||
|
LogFileExt = log
|
||||||
|
DateStrFormat = 20060102
|
||||||
|
DateTimeFormat = 2006-01-02 15:04:05
|
||||||
|
TimeFormat = 15:04:05
|
||||||
|
DateFormat = 2006-01-02
|
||||||
|
DBPath = /var/lib/casaos
|
||||||
|
ShellPath = /usr/share/casaos/shell
|
||||||
|
UserDataPath = /var/lib/casaos/conf
|
||||||
|
|
||||||
|
[server]
|
||||||
|
RunMode = release
|
||||||
|
ServerApi = https://api.casaos.io/casaos-api
|
||||||
|
Handshake = socket.casaos.io
|
||||||
|
Token =
|
||||||
|
USBAutoMount =
|
||||||
|
|
||||||
|
[system]
|
||||||
13
build/sysroot/usr/lib/systemd/system/casaos.service
Normal file
13
build/sysroot/usr/lib/systemd/system/casaos.service
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[Unit]
|
||||||
|
After=casaos-gateway.service
|
||||||
|
ConditionFileNotEmpty=/etc/casaos/casaos.conf
|
||||||
|
Description=CasaOS Main Service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/bin/casaos -c /etc/casaos/casaos.conf
|
||||||
|
PIDFile=/var/run/casaos/casaos.pid
|
||||||
|
Restart=always
|
||||||
|
Type=notify
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
###
|
||||||
|
# @Author: LinkLeong link@icewhale.org
|
||||||
|
# @Date: 2022-11-15 15:51:44
|
||||||
|
# @LastEditors: LinkLeong
|
||||||
|
# @LastEditTime: 2022-11-15 15:53:37
|
||||||
|
# @FilePath: /CasaOS/build/sysroot/usr/share/casaos/cleanup/script.d/03-cleanup-casaos.sh
|
||||||
|
# @Description:
|
||||||
|
# @Website: https://www.casaos.io
|
||||||
|
# Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
###
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
readonly APP_NAME_SHORT=casaos
|
||||||
|
|
||||||
|
__get_setup_script_directory_by_os_release() {
|
||||||
|
pushd "$(dirname "${BASH_SOURCE[0]}")/../service.d/${APP_NAME_SHORT}" &>/dev/null
|
||||||
|
|
||||||
|
{
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
{
|
||||||
|
source /etc/os-release
|
||||||
|
{
|
||||||
|
pushd "${ID}"/"${VERSION_CODENAME}" &>/dev/null
|
||||||
|
} || {
|
||||||
|
pushd "${ID}" &>/dev/null
|
||||||
|
} || {
|
||||||
|
pushd "${ID_LIKE}" &>/dev/null
|
||||||
|
} || {
|
||||||
|
echo "Unsupported OS: ${ID} ${VERSION_CODENAME} (${ID_LIKE})"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
pwd
|
||||||
|
|
||||||
|
popd &>/dev/null
|
||||||
|
|
||||||
|
} || {
|
||||||
|
echo "Unsupported OS: unknown"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
popd &>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
SETUP_SCRIPT_DIRECTORY=$(__get_setup_script_directory_by_os_release)
|
||||||
|
|
||||||
|
readonly SETUP_SCRIPT_DIRECTORY
|
||||||
|
readonly SETUP_SCRIPT_FILENAME="cleanup-${APP_NAME_SHORT}.sh"
|
||||||
|
readonly SETUP_SCRIPT_FILEPATH="${SETUP_SCRIPT_DIRECTORY}/${SETUP_SCRIPT_FILENAME}"
|
||||||
|
|
||||||
|
echo "🟩 Running ${SETUP_SCRIPT_FILENAME}..."
|
||||||
|
$SHELL "${SETUP_SCRIPT_FILEPATH}" "${BUILD_PATH}"
|
||||||
@@ -0,0 +1,204 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
readonly CASA_SERVICES=(
|
||||||
|
"casaos.service"
|
||||||
|
"devmon@devmon.service"
|
||||||
|
)
|
||||||
|
|
||||||
|
readonly CASA_EXEC=casaos
|
||||||
|
readonly CASA_CONF=/etc/casaos/casaos.conf
|
||||||
|
readonly CASA_URL=/var/run/casaos/casaos.url
|
||||||
|
readonly CASA_SERVICE_USR=/usr/lib/systemd/system/casaos.service
|
||||||
|
readonly CASA_SERVICE_LIB=/lib/systemd/system/casaos.service
|
||||||
|
readonly CASA_SERVICE_ETC=/etc/systemd/system/casaos.service
|
||||||
|
|
||||||
|
# Old Casa Files
|
||||||
|
readonly CASA_PATH=/casaOS
|
||||||
|
readonly CASA_CONF_PATH_OLD=/etc/casaos.conf
|
||||||
|
|
||||||
|
readonly aCOLOUR=(
|
||||||
|
'\e[38;5;154m' # green | Lines, bullets and separators
|
||||||
|
'\e[1m' # Bold white | Main descriptions
|
||||||
|
'\e[90m' # Grey | Credits
|
||||||
|
'\e[91m' # Red | Update notifications Alert
|
||||||
|
'\e[33m' # Yellow | Emphasis
|
||||||
|
)
|
||||||
|
|
||||||
|
Show() {
|
||||||
|
# OK
|
||||||
|
if (($1 == 0)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[0]} OK $COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
# FAILED
|
||||||
|
elif (($1 == 1)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[3]}FAILED$COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
# INFO
|
||||||
|
elif (($1 == 2)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[0]} INFO $COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
# NOTICE
|
||||||
|
elif (($1 == 3)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[4]}NOTICE$COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
Warn() {
|
||||||
|
echo -e "${aCOLOUR[3]}$1$COLOUR_RESET"
|
||||||
|
}
|
||||||
|
|
||||||
|
trap 'onCtrlC' INT
|
||||||
|
onCtrlC() {
|
||||||
|
echo -e "${COLOUR_RESET}"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Detecting_CasaOS() {
|
||||||
|
if [[ ! -x "$(command -v ${CASA_EXEC})" ]]; then
|
||||||
|
Show 2 "CasaOS is not detected, exit the script."
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
Show 0 "This script will delete the containers you no longer use, and the CasaOS configuration files."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
Uninstall_Container() {
|
||||||
|
if [[ ${UNINSTALL_ALL_CONTAINER} == true && "$(docker ps -aq)" != "" ]]; then
|
||||||
|
Show 2 "Start deleting containers."
|
||||||
|
docker stop "$(docker ps -aq)" || Show 1 "Failed to stop all containers."
|
||||||
|
docker rm "$(docker ps -aq)" || Show 1 "Failed to delete all containers."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
Remove_Images() {
|
||||||
|
if [[ ${REMOVE_IMAGES} == "all" && "$(docker images -q)" != "" ]]; then
|
||||||
|
Show 2 "Start deleting all images."
|
||||||
|
docker rmi "$(docker images -q)" || Show 1 "Failed to delete all images."
|
||||||
|
elif [[ ${REMOVE_IMAGES} == "unuse" && "$(docker images -q)" != "" ]]; then
|
||||||
|
Show 2 "Start deleting unuse images."
|
||||||
|
docker image prune -af || Show 1 "Failed to delete unuse images."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Uninstall_Casaos() {
|
||||||
|
|
||||||
|
for SERVICE in "${CASA_SERVICES[@]}"; do
|
||||||
|
Show 2 "Stopping ${SERVICE}..."
|
||||||
|
systemctl disable --now "${SERVICE}" || Show 3 "Failed to disable ${SERVICE}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Remove Service file
|
||||||
|
if [[ -f ${CASA_SERVICE_USR} ]]; then
|
||||||
|
rm -rvf ${CASA_SERVICE_USR}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f ${CASA_SERVICE_LIB} ]]; then
|
||||||
|
rm -rvf ${CASA_SERVICE_LIB}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f ${CASA_SERVICE_ETC} ]]; then
|
||||||
|
rm -rvf ${CASA_SERVICE_ETC}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Old Casa Files
|
||||||
|
if [[ -d ${CASA_PATH} ]]; then
|
||||||
|
rm -rvf ${CASA_PATH} || Show 1 "Failed to delete legacy CasaOS files."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f ${CASA_CONF_PATH_OLD} ]]; then
|
||||||
|
rm -rvf ${CASA_CONF_PATH_OLD}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# New Casa Files
|
||||||
|
if [[ ${REMOVE_APP_DATA} = true ]]; then
|
||||||
|
rm -rvf /DATA/AppData || Show 1 "Failed to delete AppData."
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rvf "$(which ${CASA_EXEC})" || Show 3 "Failed to remove ${CASA_EXEC}"
|
||||||
|
rm -rvf ${CASA_CONF} || Show 3 "Failed to remove ${CASA_CONF}"
|
||||||
|
rm -rvf ${CASA_URL} || Show 3 "Failed to remove ${CASA_URL}"
|
||||||
|
|
||||||
|
rm -rvf /var/lib/casaos/app_category.json
|
||||||
|
rm -rvf /var/lib/casaos/app_list.json
|
||||||
|
rm -rvf /var/lib/casaos/docker_root
|
||||||
|
}
|
||||||
|
|
||||||
|
Detecting_CasaOS
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
echo -n -e " ${aCOLOUR[4]}Do you want delete all containers? Y/n :${COLOUR_RESET}"
|
||||||
|
read -r input
|
||||||
|
case $input in
|
||||||
|
[yY][eE][sS] | [yY])
|
||||||
|
UNINSTALL_ALL_CONTAINER=true
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
[nN][oO] | [nN])
|
||||||
|
UNINSTALL_ALL_CONTAINER=false
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
Warn " Invalid input..."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ ${UNINSTALL_ALL_CONTAINER} == true ]]; then
|
||||||
|
while true; do
|
||||||
|
echo -n -e " ${aCOLOUR[4]}Do you want delete all images? Y/n :${COLOUR_RESET}"
|
||||||
|
read -r input
|
||||||
|
case $input in
|
||||||
|
[yY][eE][sS] | [yY])
|
||||||
|
REMOVE_IMAGES="all"
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
[nN][oO] | [nN])
|
||||||
|
REMOVE_IMAGES="none"
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
Warn " Invalid input..."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
echo -n -e " ${aCOLOUR[4]}Do you want delete all AppData of CasaOS? Y/n :${COLOUR_RESET}"
|
||||||
|
read -r input
|
||||||
|
case $input in
|
||||||
|
[yY][eE][sS] | [yY])
|
||||||
|
REMOVE_APP_DATA=true
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
[nN][oO] | [nN])
|
||||||
|
REMOVE_APP_DATA=false
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
Warn " Invalid input..."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
else
|
||||||
|
while true; do
|
||||||
|
echo -n -e " ${aCOLOUR[4]}Do you want to delete all images that are not used by the container? Y/n :${COLOUR_RESET}"
|
||||||
|
read -r input
|
||||||
|
case $input in
|
||||||
|
[yY][eE][sS] | [yY])
|
||||||
|
REMOVE_IMAGES="unuse"
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
[nN][oO] | [nN])
|
||||||
|
REMOVE_IMAGES="none"
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
Warn " Invalid input..."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
Uninstall_Container
|
||||||
|
Remove_Images
|
||||||
|
Uninstall_Casaos
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../cleanup-casaos.sh
|
||||||
@@ -0,0 +1,204 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
readonly CASA_SERVICES=(
|
||||||
|
"casaos.service"
|
||||||
|
"devmon@devmon.service"
|
||||||
|
)
|
||||||
|
|
||||||
|
readonly CASA_EXEC=casaos
|
||||||
|
readonly CASA_CONF=/etc/casaos/casaos.conf
|
||||||
|
readonly CASA_URL=/var/run/casaos/casaos.url
|
||||||
|
readonly CASA_SERVICE_USR=/usr/lib/systemd/system/casaos.service
|
||||||
|
readonly CASA_SERVICE_LIB=/lib/systemd/system/casaos.service
|
||||||
|
readonly CASA_SERVICE_ETC=/etc/systemd/system/casaos.service
|
||||||
|
|
||||||
|
# Old Casa Files
|
||||||
|
readonly CASA_PATH=/casaOS
|
||||||
|
readonly CASA_CONF_PATH_OLD=/etc/casaos.conf
|
||||||
|
|
||||||
|
readonly aCOLOUR=(
|
||||||
|
'\e[38;5;154m' # green | Lines, bullets and separators
|
||||||
|
'\e[1m' # Bold white | Main descriptions
|
||||||
|
'\e[90m' # Grey | Credits
|
||||||
|
'\e[91m' # Red | Update notifications Alert
|
||||||
|
'\e[33m' # Yellow | Emphasis
|
||||||
|
)
|
||||||
|
|
||||||
|
Show() {
|
||||||
|
# OK
|
||||||
|
if (($1 == 0)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[0]} OK $COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
# FAILED
|
||||||
|
elif (($1 == 1)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[3]}FAILED$COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
# INFO
|
||||||
|
elif (($1 == 2)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[0]} INFO $COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
# NOTICE
|
||||||
|
elif (($1 == 3)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[4]}NOTICE$COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
Warn() {
|
||||||
|
echo -e "${aCOLOUR[3]}$1$COLOUR_RESET"
|
||||||
|
}
|
||||||
|
|
||||||
|
trap 'onCtrlC' INT
|
||||||
|
onCtrlC() {
|
||||||
|
echo -e "${COLOUR_RESET}"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Detecting_CasaOS() {
|
||||||
|
if [[ ! -x "$(command -v ${CASA_EXEC})" ]]; then
|
||||||
|
Show 2 "CasaOS is not detected, exit the script."
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
Show 0 "This script will delete the containers you no longer use, and the CasaOS configuration files."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
Uninstall_Container() {
|
||||||
|
if [[ ${UNINSTALL_ALL_CONTAINER} == true && "$(docker ps -aq)" != "" ]]; then
|
||||||
|
Show 2 "Start deleting containers."
|
||||||
|
docker stop "$(docker ps -aq)" || Show 1 "Failed to stop all containers."
|
||||||
|
docker rm "$(docker ps -aq)" || Show 1 "Failed to delete all containers."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
Remove_Images() {
|
||||||
|
if [[ ${REMOVE_IMAGES} == "all" && "$(docker images -q)" != "" ]]; then
|
||||||
|
Show 2 "Start deleting all images."
|
||||||
|
docker rmi "$(docker images -q)" || Show 1 "Failed to delete all images."
|
||||||
|
elif [[ ${REMOVE_IMAGES} == "unuse" && "$(docker images -q)" != "" ]]; then
|
||||||
|
Show 2 "Start deleting unuse images."
|
||||||
|
docker image prune -af || Show 1 "Failed to delete unuse images."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Uninstall_Casaos() {
|
||||||
|
|
||||||
|
for SERVICE in "${CASA_SERVICES[@]}"; do
|
||||||
|
Show 2 "Stopping ${SERVICE}..."
|
||||||
|
systemctl disable --now "${SERVICE}" || Show 3 "Failed to disable ${SERVICE}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Remove Service file
|
||||||
|
if [[ -f ${CASA_SERVICE_USR} ]]; then
|
||||||
|
rm -rvf ${CASA_SERVICE_USR}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f ${CASA_SERVICE_LIB} ]]; then
|
||||||
|
rm -rvf ${CASA_SERVICE_LIB}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f ${CASA_SERVICE_ETC} ]]; then
|
||||||
|
rm -rvf ${CASA_SERVICE_ETC}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Old Casa Files
|
||||||
|
if [[ -d ${CASA_PATH} ]]; then
|
||||||
|
rm -rvf ${CASA_PATH} || Show 1 "Failed to delete legacy CasaOS files."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f ${CASA_CONF_PATH_OLD} ]]; then
|
||||||
|
rm -rvf ${CASA_CONF_PATH_OLD}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# New Casa Files
|
||||||
|
if [[ ${REMOVE_APP_DATA} = true ]]; then
|
||||||
|
rm -rvf /DATA/AppData || Show 1 "Failed to delete AppData."
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rvf "$(which ${CASA_EXEC})" || Show 3 "Failed to remove ${CASA_EXEC}"
|
||||||
|
rm -rvf ${CASA_CONF} || Show 3 "Failed to remove ${CASA_CONF}"
|
||||||
|
rm -rvf ${CASA_URL} || Show 3 "Failed to remove ${CASA_URL}"
|
||||||
|
|
||||||
|
rm -rvf /var/lib/casaos/app_category.json
|
||||||
|
rm -rvf /var/lib/casaos/app_list.json
|
||||||
|
rm -rvf /var/lib/casaos/docker_root
|
||||||
|
}
|
||||||
|
|
||||||
|
Detecting_CasaOS
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
echo -n -e " ${aCOLOUR[4]}Do you want delete all containers? Y/n :${COLOUR_RESET}"
|
||||||
|
read -r input
|
||||||
|
case $input in
|
||||||
|
[yY][eE][sS] | [yY])
|
||||||
|
UNINSTALL_ALL_CONTAINER=true
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
[nN][oO] | [nN])
|
||||||
|
UNINSTALL_ALL_CONTAINER=false
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
Warn " Invalid input..."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ ${UNINSTALL_ALL_CONTAINER} == true ]]; then
|
||||||
|
while true; do
|
||||||
|
echo -n -e " ${aCOLOUR[4]}Do you want delete all images? Y/n :${COLOUR_RESET}"
|
||||||
|
read -r input
|
||||||
|
case $input in
|
||||||
|
[yY][eE][sS] | [yY])
|
||||||
|
REMOVE_IMAGES="all"
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
[nN][oO] | [nN])
|
||||||
|
REMOVE_IMAGES="none"
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
Warn " Invalid input..."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
echo -n -e " ${aCOLOUR[4]}Do you want delete all AppData of CasaOS? Y/n :${COLOUR_RESET}"
|
||||||
|
read -r input
|
||||||
|
case $input in
|
||||||
|
[yY][eE][sS] | [yY])
|
||||||
|
REMOVE_APP_DATA=true
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
[nN][oO] | [nN])
|
||||||
|
REMOVE_APP_DATA=false
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
Warn " Invalid input..."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
else
|
||||||
|
while true; do
|
||||||
|
echo -n -e " ${aCOLOUR[4]}Do you want to delete all images that are not used by the container? Y/n :${COLOUR_RESET}"
|
||||||
|
read -r input
|
||||||
|
case $input in
|
||||||
|
[yY][eE][sS] | [yY])
|
||||||
|
REMOVE_IMAGES="unuse"
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
[nN][oO] | [nN])
|
||||||
|
REMOVE_IMAGES="none"
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
Warn " Invalid input..."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
Uninstall_Container
|
||||||
|
Remove_Images
|
||||||
|
Uninstall_Casaos
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../debian/cleanup-casaos.sh
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../debian/bullseye/cleanup-casaos.sh
|
||||||
3
build/sysroot/usr/share/casaos/shell/assist.sh
Normal file
3
build/sysroot/usr/share/casaos/shell/assist.sh
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
|
||||||
105
build/sysroot/usr/share/casaos/shell/delete-old-service.sh
Normal file
105
build/sysroot/usr/share/casaos/shell/delete-old-service.sh
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
###
|
||||||
|
# @Author: LinkLeong link@icewhale.com
|
||||||
|
# @Date: 2022-06-30 10:08:33
|
||||||
|
# @LastEditors: LinkLeong
|
||||||
|
# @LastEditTime: 2022-07-01 11:17:54
|
||||||
|
# @FilePath: /CasaOS/shell/delete-old-service.sh
|
||||||
|
# @Description:
|
||||||
|
###
|
||||||
|
|
||||||
|
((EUID)) && sudo_cmd="sudo"
|
||||||
|
|
||||||
|
# SYSTEM INFO
|
||||||
|
readonly UNAME_M="$(uname -m)"
|
||||||
|
|
||||||
|
# CasaOS PATHS
|
||||||
|
readonly CASA_REPO=IceWhaleTech/CasaOS
|
||||||
|
readonly CASA_UNZIP_TEMP_FOLDER=/tmp/casaos
|
||||||
|
readonly CASA_BIN=casaos
|
||||||
|
readonly CASA_BIN_PATH=/usr/bin/casaos
|
||||||
|
readonly CASA_CONF_PATH=/etc/casaos.conf
|
||||||
|
readonly CASA_SERVICE_PATH=/etc/systemd/system/casaos.service
|
||||||
|
readonly CASA_HELPER_PATH=/usr/share/casaos/shell/
|
||||||
|
readonly CASA_USER_CONF_PATH=/var/lib/casaos/conf/
|
||||||
|
readonly CASA_DB_PATH=/var/lib/casaos/db/
|
||||||
|
readonly CASA_TEMP_PATH=/var/lib/casaos/temp/
|
||||||
|
readonly CASA_LOGS_PATH=/var/log/casaos/
|
||||||
|
readonly CASA_PACKAGE_EXT=".tar.gz"
|
||||||
|
readonly CASA_RELEASE_API="https://api.github.com/repos/${CASA_REPO}/releases"
|
||||||
|
readonly CASA_OPENWRT_DOCS="https://github.com/IceWhaleTech/CasaOS-OpenWrt"
|
||||||
|
|
||||||
|
readonly COLOUR_RESET='\e[0m'
|
||||||
|
readonly aCOLOUR=(
|
||||||
|
'\e[38;5;154m' # green | Lines, bullets and separators
|
||||||
|
'\e[1m' # Bold white | Main descriptions
|
||||||
|
'\e[90m' # Grey | Credits
|
||||||
|
'\e[91m' # Red | Update notifications Alert
|
||||||
|
'\e[33m' # Yellow | Emphasis
|
||||||
|
)
|
||||||
|
|
||||||
|
Target_Arch=""
|
||||||
|
Target_Distro="debian"
|
||||||
|
Target_OS="linux"
|
||||||
|
Casa_Tag=""
|
||||||
|
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Custom printing function
|
||||||
|
# Globals:
|
||||||
|
# None
|
||||||
|
# Arguments:
|
||||||
|
# $1 0:OK 1:FAILED 2:INFO 3:NOTICE
|
||||||
|
# message
|
||||||
|
# Returns:
|
||||||
|
# None
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
Show() {
|
||||||
|
# OK
|
||||||
|
if (($1 == 0)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[0]} OK $COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
# FAILED
|
||||||
|
elif (($1 == 1)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[3]}FAILED$COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
# INFO
|
||||||
|
elif (($1 == 2)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[0]} INFO $COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
# NOTICE
|
||||||
|
elif (($1 == 3)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[4]}NOTICE$COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
Warn() {
|
||||||
|
echo -e "${aCOLOUR[3]}$1$COLOUR_RESET"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 0 Check_exist
|
||||||
|
Check_Exist() {
|
||||||
|
#Create Dir
|
||||||
|
Show 2 "Create Folders."
|
||||||
|
${sudo_cmd} mkdir -p ${CASA_HELPER_PATH}
|
||||||
|
${sudo_cmd} mkdir -p ${CASA_LOGS_PATH}
|
||||||
|
${sudo_cmd} mkdir -p ${CASA_USER_CONF_PATH}
|
||||||
|
${sudo_cmd} mkdir -p ${CASA_DB_PATH}
|
||||||
|
${sudo_cmd} mkdir -p ${CASA_TEMP_PATH}
|
||||||
|
|
||||||
|
|
||||||
|
Show 2 "Start cleaning up the old version."
|
||||||
|
|
||||||
|
${sudo_cmd} rm -rf /usr/lib/systemd/system/casaos.service
|
||||||
|
|
||||||
|
${sudo_cmd} rm -rf /lib/systemd/system/casaos.service
|
||||||
|
|
||||||
|
${sudo_cmd} rm -rf /usr/local/bin/${CASA_BIN}
|
||||||
|
|
||||||
|
#Clean
|
||||||
|
if [[ -d "/casaOS" ]]; then
|
||||||
|
${sudo_cmd} rm -rf /casaOS
|
||||||
|
fi
|
||||||
|
Show 0 "Clearance completed."
|
||||||
|
|
||||||
|
$sudo_cmd systemctl restart ${CASA_BIN}
|
||||||
|
}
|
||||||
|
Check_Exist
|
||||||
388
build/sysroot/usr/share/casaos/shell/helper.sh
Normal file
388
build/sysroot/usr/share/casaos/shell/helper.sh
Normal file
@@ -0,0 +1,388 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# 获取系统信息
|
||||||
|
GetSysInfo() {
|
||||||
|
if [ -s "/etc/redhat-release" ]; then
|
||||||
|
SYS_VERSION=$(cat /etc/redhat-release)
|
||||||
|
elif [ -s "/etc/issue" ]; then
|
||||||
|
SYS_VERSION=$(cat /etc/issue)
|
||||||
|
fi
|
||||||
|
SYS_INFO=$(uname -a)
|
||||||
|
SYS_BIT=$(getconf LONG_BIT)
|
||||||
|
MEM_TOTAL=$(free -m | grep Mem | awk '{print $2}')
|
||||||
|
CPU_INFO=$(getconf _NPROCESSORS_ONLN)
|
||||||
|
|
||||||
|
echo -e ${SYS_VERSION}
|
||||||
|
echo -e Bit:${SYS_BIT} Mem:${MEM_TOTAL}M Core:${CPU_INFO}
|
||||||
|
echo -e ${SYS_INFO}
|
||||||
|
}
|
||||||
|
|
||||||
|
#获取网卡信息
|
||||||
|
GetNetCard() {
|
||||||
|
if [ "$1" == "1" ]; then
|
||||||
|
if [ -d "/sys/devices/virtual/net" ]; then
|
||||||
|
ls /sys/devices/virtual/net
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ -d "/sys/devices/virtual/net" ] && [ -d "/sys/class/net" ]; then
|
||||||
|
ls /sys/class/net/ | grep -v "$(ls /sys/devices/virtual/net/)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GetTimeZone(){
|
||||||
|
timedatectl | grep "Time zone" | awk '{printf $3}'
|
||||||
|
}
|
||||||
|
|
||||||
|
#查看网卡状态
|
||||||
|
#param 网卡名称
|
||||||
|
CatNetCardState() {
|
||||||
|
if [ -e "/sys/class/net/$1/operstate" ]; then
|
||||||
|
cat /sys/class/net/$1/operstate
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#获取docker根目录
|
||||||
|
GetDockerRootDir() {
|
||||||
|
if hash docker 2>/dev/null; then
|
||||||
|
docker info | grep 'Docker Root Dir' | awk -F ':' '{print $2}'
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#删除安装应用文件夹
|
||||||
|
#param 需要删除的文件夹路径
|
||||||
|
DelAppConfigDir() {
|
||||||
|
if [ -d $1 ]; then
|
||||||
|
rm -fr $1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#zerotier本机已加入的网络
|
||||||
|
#result start,end,sectors
|
||||||
|
GetLocalJoinNetworks() {
|
||||||
|
zerotier-cli listnetworks -j
|
||||||
|
}
|
||||||
|
|
||||||
|
#移除挂载点,删除已挂在的文件夹
|
||||||
|
UMountPorintAndRemoveDir() {
|
||||||
|
DEVICE=$1
|
||||||
|
MOUNT_POINT=$(mount | grep ${DEVICE} | awk '{ print $3 }')
|
||||||
|
if [[ -z ${MOUNT_POINT} ]]; then
|
||||||
|
${log} "Warning: ${DEVICE} is not mounted"
|
||||||
|
else
|
||||||
|
umount -lf ${DEVICE}
|
||||||
|
/bin/rmdir "${MOUNT_POINT}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#格式化fat32磁盘
|
||||||
|
#param 需要格式化的目录 /dev/sda1
|
||||||
|
#param 格式
|
||||||
|
FormatDisk() {
|
||||||
|
if [ "$2" == "fat32" ]; then
|
||||||
|
mkfs.vfat -F 32 $1
|
||||||
|
elif [ "$2" == "ntfs" ]; then
|
||||||
|
mkfs.ntfs $1
|
||||||
|
elif [ "$2" == "ext4" ]; then
|
||||||
|
mkfs.ext4 -m 1 -F $1
|
||||||
|
elif [ "$2" == "exfat" ]; then
|
||||||
|
mkfs.exfat $1
|
||||||
|
else
|
||||||
|
mkfs.ext4 -m 1 -F $1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#删除分区
|
||||||
|
#param 路径 /dev/sdb
|
||||||
|
#param 删除分区的区号
|
||||||
|
DelPartition() {
|
||||||
|
fdisk $1 <<EOF
|
||||||
|
d
|
||||||
|
$2
|
||||||
|
wq
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
#添加分区只有一个分区
|
||||||
|
#param 路径 /dev/sdb
|
||||||
|
#param 要挂载的目录
|
||||||
|
AddPartition() {
|
||||||
|
|
||||||
|
DelPartition $1
|
||||||
|
parted -s $1 mklabel gpt
|
||||||
|
|
||||||
|
parted -s $1 mkpart primary ext4 0 100%
|
||||||
|
P=`lsblk -r $1 | sort | grep part | head -n 1 | awk '{print $1}'`
|
||||||
|
mkfs.ext4 -m 1 -F /dev/${P}
|
||||||
|
|
||||||
|
partprobe $1
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#磁盘类型
|
||||||
|
GetDiskType() {
|
||||||
|
fdisk $1 -l | grep Disklabel | awk -F: '{print $2}'
|
||||||
|
}
|
||||||
|
|
||||||
|
#获磁盘的插入路径
|
||||||
|
#param 路径 /dev/sda
|
||||||
|
GetPlugInDisk() {
|
||||||
|
fdisk -l | grep 'Disk' | grep 'sd' | awk -F , '{print substr($1,11,3)}'
|
||||||
|
}
|
||||||
|
|
||||||
|
#获取磁盘状态
|
||||||
|
#param 磁盘路径
|
||||||
|
GetDiskHealthState() {
|
||||||
|
smartctl -H $1 | grep "SMART Health Status" | awk -F ":" '{print$2}'
|
||||||
|
}
|
||||||
|
|
||||||
|
#获取磁盘字节数量和扇区数量
|
||||||
|
#param 磁盘路径 /dev/sda
|
||||||
|
#result bytes
|
||||||
|
#result sectors
|
||||||
|
GetDiskSizeAndSectors() {
|
||||||
|
fdisk $1 -l | grep "$1:" | awk -F, 'BEGIN {OFS="\n"}{print $2,$3}' | awk '{print $1}'
|
||||||
|
}
|
||||||
|
|
||||||
|
#获取磁盘分区数据扇区
|
||||||
|
#param 磁盘路径 /dev/sda
|
||||||
|
#result start,end,sectors
|
||||||
|
GetPartitionSectors() {
|
||||||
|
fdisk $1 -l | grep "$1[1-9]" | awk 'BEGIN{OFS=","}{print $1,$2,$3,$4}'
|
||||||
|
}
|
||||||
|
|
||||||
|
#检查没有使用的挂载点删除文件夹
|
||||||
|
AutoRemoveUnuseDir() {
|
||||||
|
DIRECTORY="/DATA/"
|
||||||
|
dir=$(ls -l $DIRECTORY | grep "USB_Storage_sd[a-z][0-9]" | awk '/^d/ {print $NF}')
|
||||||
|
for i in $dir; do
|
||||||
|
|
||||||
|
path="$DIRECTORY$i"
|
||||||
|
mountStr=$(mountpoint $path)
|
||||||
|
notMountpoint="is not a mountpoint"
|
||||||
|
if [[ $mountStr =~ $notMountpoint ]]; then
|
||||||
|
if [ "$(ls -A $path)" = "" ]; then
|
||||||
|
rm -fr $path
|
||||||
|
else
|
||||||
|
echo "$path is not empty"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
#重载samba服务
|
||||||
|
ReloadSamba() {
|
||||||
|
/etc/init.d/smbd reload
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1=sda1
|
||||||
|
# $2=volume{1}
|
||||||
|
do_mount() {
|
||||||
|
DEVBASE=$1
|
||||||
|
DEVICE="${DEVBASE}"
|
||||||
|
# See if this drive is already mounted, and if so where
|
||||||
|
MOUNT_POINT=$(lsblk -o name,mountpoint | grep ${DEVICE} | awk '{print $2}')
|
||||||
|
|
||||||
|
if [ -n "${MOUNT_POINT}" ]; then
|
||||||
|
${log} "Warning: ${DEVICE} is already mounted at ${MOUNT_POINT}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get info for this drive: $ID_FS_LABEL and $ID_FS_TYPE
|
||||||
|
eval $(blkid -o udev ${DEVICE} | grep -i -e "ID_FS_LABEL" -e "ID_FS_TYPE")
|
||||||
|
|
||||||
|
LABEL=$2
|
||||||
|
if grep -q " ${LABEL} " /etc/mtab; then
|
||||||
|
# Already in use, make a unique one
|
||||||
|
LABEL+="-${DEVBASE}"
|
||||||
|
fi
|
||||||
|
DEV_LABEL="${LABEL}"
|
||||||
|
|
||||||
|
# Use the device name in case the drive doesn't have label
|
||||||
|
if [ -z ${DEV_LABEL} ]; then
|
||||||
|
DEV_LABEL="${DEVBASE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
MOUNT_POINT="${DEV_LABEL}"
|
||||||
|
|
||||||
|
${log} "Mount point: ${MOUNT_POINT}"
|
||||||
|
|
||||||
|
mkdir -p ${MOUNT_POINT}
|
||||||
|
|
||||||
|
case ${ID_FS_TYPE} in
|
||||||
|
vfat)
|
||||||
|
mount -t vfat -o rw,relatime,users,gid=100,umask=000,shortname=mixed,utf8=1,flush ${DEVICE} ${MOUNT_POINT}
|
||||||
|
;;
|
||||||
|
ext[2-4])
|
||||||
|
mount -o noatime ${DEVICE} ${MOUNT_POINT} >/dev/null 2>&1
|
||||||
|
;;
|
||||||
|
exfat)
|
||||||
|
mount -t exfat ${DEVICE} ${MOUNT_POINT} >/dev/null 2>&1
|
||||||
|
;;
|
||||||
|
ntfs)
|
||||||
|
ntfs-3g ${DEVICE} ${MOUNT_POINT}
|
||||||
|
;;
|
||||||
|
iso9660)
|
||||||
|
mount -t iso9660 ${DEVICE} ${MOUNT_POINT}
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
/bin/rmdir "${MOUNT_POINT}"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1=sda1
|
||||||
|
do_umount() {
|
||||||
|
log="logger -t usb-mount.sh -s "
|
||||||
|
DEVBASE=$1
|
||||||
|
DEVICE="${DEVBASE}"
|
||||||
|
MOUNT_POINT=$(mount | grep ${DEVICE} | awk '{ print $3 }')
|
||||||
|
|
||||||
|
if [[ -z ${MOUNT_POINT} ]]; then
|
||||||
|
${log} "Warning: ${DEVICE} is not mounted"
|
||||||
|
else
|
||||||
|
/bin/kill -9 $(lsof ${MOUNT_POINT})
|
||||||
|
umount -l ${DEVICE}
|
||||||
|
${log} "Unmounted ${DEVICE} from ${MOUNT_POINT}"
|
||||||
|
if [ "`ls -A ${MOUNT_POINT}`" = "" ]; then
|
||||||
|
/bin/rm -fr "${MOUNT_POINT}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
sed -i.bak "\@${MOUNT_POINT}@d" /var/log/usb-mount.track
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
# $1=/mnt/volume1/data.img
|
||||||
|
# $2=100G
|
||||||
|
PackageDocker() {
|
||||||
|
image=$1
|
||||||
|
docker="/mnt/casa_docker"
|
||||||
|
#判断目录docker存在不存在则创建,存在检查是否为空
|
||||||
|
|
||||||
|
if [ ! -d "$docker" ]; then
|
||||||
|
mkdir ${docker}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$(ls -A $docker)" = "" ]; then
|
||||||
|
echo "$docker count is 0"
|
||||||
|
else
|
||||||
|
mkdir ${docker}_bak
|
||||||
|
mv -r ${docker} ${docker}_bak
|
||||||
|
fi
|
||||||
|
|
||||||
|
daemon="/etc/docker/daemon.json"
|
||||||
|
#1创建img文件在挂载的目录
|
||||||
|
fallocate -l $2 $image
|
||||||
|
#2初始化img文件
|
||||||
|
mkfs -t ext4 $image
|
||||||
|
#3挂载img文件
|
||||||
|
sudo mount -o loop $image $docker
|
||||||
|
#4给移动/var/lib/docker数据到img挂载的目录
|
||||||
|
systemctl stop docker.socket
|
||||||
|
systemctl stop docker
|
||||||
|
cp -r /var/lib/docker/* ${docker}/
|
||||||
|
#5在/etc/docker写入daemon.json(需要检查)
|
||||||
|
if [ -d "$daemon" ]; then
|
||||||
|
mv -r $daemon ${daemon}.bak
|
||||||
|
fi
|
||||||
|
echo "{\"data-root\": \"$docker\"}" >$daemon
|
||||||
|
#删除老数据腾出空间
|
||||||
|
#rm -fr /var/lib/docker
|
||||||
|
systemctl start docker.socket
|
||||||
|
systemctl start docker
|
||||||
|
}
|
||||||
|
|
||||||
|
DockerImgMove() {
|
||||||
|
image=$1
|
||||||
|
systemctl stop docker.socket
|
||||||
|
systemctl stop docker
|
||||||
|
sudo umount -f $image
|
||||||
|
}
|
||||||
|
|
||||||
|
GetDockerDataRoot() {
|
||||||
|
docker info | grep "Docker Root Dir:"
|
||||||
|
}
|
||||||
|
|
||||||
|
SetLink() {
|
||||||
|
ln -s /mnt/casa_sda1/AppData /DATA/AppData
|
||||||
|
#删除所有软链
|
||||||
|
find /DATA -type l -delete
|
||||||
|
}
|
||||||
|
|
||||||
|
#压缩文件夹
|
||||||
|
|
||||||
|
TarFolder() {
|
||||||
|
#压缩
|
||||||
|
tar -zcvf data.tar.gz -C/DATA/ AppDataBak/
|
||||||
|
|
||||||
|
#解压
|
||||||
|
tar zxvf data.tar.gz
|
||||||
|
|
||||||
|
#查看某文件夹下的所有包括子文件夹文件
|
||||||
|
ls /DATA/Media -lR | grep "^-" | wc -l
|
||||||
|
# ls -lR|grep "^d"| wc -l 查看某个文件夹下文件夹的个数,包括子文件夹下的文件夹个数。
|
||||||
|
|
||||||
|
#查看固定文件夹大小
|
||||||
|
du -sh /DATA
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_Start_Auto() {
|
||||||
|
((EUID)) && sudo_cmd="sudo"
|
||||||
|
$sudo_cmd systemctl enable devmon@devmon
|
||||||
|
$sudo_cmd systemctl start devmon@devmon
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_Stop_Auto() {
|
||||||
|
((EUID)) && sudo_cmd="sudo"
|
||||||
|
$sudo_cmd systemctl stop devmon@devmon
|
||||||
|
$sudo_cmd systemctl disable devmon@devmon
|
||||||
|
$sudo_cmd udevil clean
|
||||||
|
}
|
||||||
|
|
||||||
|
GetDeviceTree(){
|
||||||
|
cat /proc/device-tree/model
|
||||||
|
}
|
||||||
|
|
||||||
|
# restart samba service
|
||||||
|
RestartSMBD(){
|
||||||
|
$sudo_cmd systemctl restart smbd
|
||||||
|
}
|
||||||
|
|
||||||
|
# edit user password $1:username
|
||||||
|
EditSmabaUserPassword(){
|
||||||
|
$sudo_cmd smbpasswd $1
|
||||||
|
}
|
||||||
|
|
||||||
|
AddSmabaUser(){
|
||||||
|
$sudo_cmd useradd $1
|
||||||
|
$sudo_cmd smbpasswd -a $1 <<EOF
|
||||||
|
$2
|
||||||
|
$2
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1:username $2:host $3:share $4:port $5:mountpoint $6:password
|
||||||
|
MountCIFS(){
|
||||||
|
$sudo_cmd mount -t cifs -o username=$1,password=$6,port=$4 //$2/$3 $5
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1:service name
|
||||||
|
CheckServiceStatus(){
|
||||||
|
rs="`systemctl status $1 |grep -E 'Active|PID'`"
|
||||||
|
#echo "$rs"
|
||||||
|
run="`echo "$rs" |grep -B 2 'running'`"
|
||||||
|
fai="`echo "$rs" |grep -E -B 2 'failed|inactive|dead'`"
|
||||||
|
if [ "$run" == "" ]
|
||||||
|
then
|
||||||
|
echo "failed"
|
||||||
|
else
|
||||||
|
echo "running"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
UDEVILUmount(){
|
||||||
|
$sudo_cmd udevil umount -f $1
|
||||||
|
}
|
||||||
12
build/sysroot/usr/share/casaos/shell/update.sh
Normal file
12
build/sysroot/usr/share/casaos/shell/update.sh
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
###
|
||||||
|
# @Author: LinkLeong link@icewhale.com
|
||||||
|
# @Date: 2022-06-30 10:08:33
|
||||||
|
# @LastEditors: LinkLeong
|
||||||
|
# @LastEditTime: 2022-09-01 22:33:06
|
||||||
|
# @FilePath: /CasaOS/build/sysroot/usr/share/casaos/shell/update.sh
|
||||||
|
# @Description:
|
||||||
|
###
|
||||||
|
|
||||||
|
|
||||||
|
curl -fsSL https://raw.githubusercontent.com/IceWhaleTech/get/main/update.sh | bash
|
||||||
@@ -1,12 +1,10 @@
|
|||||||
#!/bin/sh
|
#!/bin/bash
|
||||||
|
|
||||||
# copy to /oasis/util/shell path
|
# copy to /casaOS/util/shell path
|
||||||
# chmod 755
|
# chmod 755
|
||||||
|
|
||||||
log="logger -t usb-mount.sh -s "
|
log="logger -t usb-mount.sh -s "
|
||||||
|
|
||||||
${log} "变量:$1 $2"
|
|
||||||
|
|
||||||
ACTION=$1
|
ACTION=$1
|
||||||
|
|
||||||
DEVBASE=$2
|
DEVBASE=$2
|
||||||
@@ -14,14 +12,14 @@ DEVBASE=$2
|
|||||||
DEVICE="/dev/${DEVBASE}"
|
DEVICE="/dev/${DEVBASE}"
|
||||||
|
|
||||||
# See if this drive is already mounted, and if so where
|
# See if this drive is already mounted, and if so where
|
||||||
MOUNT_POINT=$(mount | grep ${DEVICE} | awk '{ print $3 }')
|
MOUNT_POINT=$(lsblk -l -p -o name,mountpoint | grep ${DEVICE} | awk '{print $2}')
|
||||||
|
|
||||||
do_mount() {
|
do_mount() {
|
||||||
|
|
||||||
if [[ -n ${MOUNT_POINT} ]]; then
|
if [ -n "${MOUNT_POINT}" ]; then
|
||||||
${log} "Warning: ${DEVICE} is already mounted at ${MOUNT_POINT}"
|
${log} "Warning: ${DEVICE} is already mounted at ${MOUNT_POINT}"
|
||||||
exit 1
|
exit 1
|
||||||
fib
|
fi
|
||||||
|
|
||||||
# Get info for this drive: $ID_FS_LABEL and $ID_FS_TYPE
|
# Get info for this drive: $ID_FS_LABEL and $ID_FS_TYPE
|
||||||
eval $(blkid -o udev ${DEVICE} | grep -i -e "ID_FS_LABEL" -e "ID_FS_TYPE")
|
eval $(blkid -o udev ${DEVICE} | grep -i -e "ID_FS_LABEL" -e "ID_FS_TYPE")
|
||||||
@@ -33,9 +31,9 @@ do_mount() {
|
|||||||
# Figure out a mount point to use
|
# Figure out a mount point to use
|
||||||
# LABEL=${ID_FS_LABEL}
|
# LABEL=${ID_FS_LABEL}
|
||||||
LABEL=${DEVBASE}
|
LABEL=${DEVBASE}
|
||||||
if grep -q " /media/${LABEL} " /etc/mtab; then
|
if grep -q " /DATA/USB_Storage_${LABEL} " /etc/mtab; then
|
||||||
# Already in use, make a unique one
|
# Already in use, make a unique one
|
||||||
LABEL+="-${DEVBASE}"
|
LABEL+="_${DEVBASE}"
|
||||||
fi
|
fi
|
||||||
DEV_LABEL="${LABEL}"
|
DEV_LABEL="${LABEL}"
|
||||||
|
|
||||||
@@ -44,12 +42,29 @@ do_mount() {
|
|||||||
DEV_LABEL="${DEVBASE}"
|
DEV_LABEL="${DEVBASE}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
MOUNT_POINT="/media/${DEV_LABEL}"
|
|
||||||
|
MOUNT_POINT="/DATA/USB_Storage_${DEV_LABEL}"
|
||||||
|
|
||||||
${log} "Mount point: ${MOUNT_POINT}"
|
${log} "Mount point: ${MOUNT_POINT}"
|
||||||
|
|
||||||
mkdir -p ${MOUNT_POINT}
|
mkdir -p ${MOUNT_POINT}
|
||||||
|
|
||||||
|
|
||||||
|
# MOUNT_POINT="/DATA/USB_Storage1"
|
||||||
|
# arr=("/DATA/USB_Storage1" "/DATA/USB_Storage2" "/DATA/USB_Storage3" "/DATA/USB_Storage4" "/DATA/USB_Storage5" "/DATA/USB_Storage6" "/DATA/USB_Storage7" "/DATA/USB_Storage8" "/DATA/USB_Storage9" "/DATA/USB_Storage10" "/DATA/USB_Storage11" "/DATA/USB_Storage12")
|
||||||
|
# for folder in ${arr[@]}; do
|
||||||
|
# #如果文件夹不存在,创建文件夹
|
||||||
|
# if [ ! -d "$folder" ]; then
|
||||||
|
# mkdir -p ${folder}
|
||||||
|
# MOUNT_POINT=$folder
|
||||||
|
# break
|
||||||
|
# fi
|
||||||
|
# done
|
||||||
|
|
||||||
|
# ${log} "Mount point: ${MOUNT_POINT}"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# # Global mount options
|
# # Global mount options
|
||||||
# OPTS="rw,relatime"
|
# OPTS="rw,relatime"
|
||||||
#
|
#
|
||||||
@@ -86,7 +101,7 @@ do_mount() {
|
|||||||
mount -t iso9660 ${DEVICE} ${MOUNT_POINT}
|
mount -t iso9660 ${DEVICE} ${MOUNT_POINT}
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
/bin/rmdir "${MOUNT_POINT}"
|
/bin/rmdir "${MOUNT_POINT}"
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@@ -97,9 +112,12 @@ do_umount() {
|
|||||||
if [[ -z ${MOUNT_POINT} ]]; then
|
if [[ -z ${MOUNT_POINT} ]]; then
|
||||||
${log} "Warning: ${DEVICE} is not mounted"
|
${log} "Warning: ${DEVICE} is not mounted"
|
||||||
else
|
else
|
||||||
|
#/bin/kill -9 $(lsof ${MOUNT_POINT})
|
||||||
umount -l ${DEVICE}
|
umount -l ${DEVICE}
|
||||||
${log} "Unmounted ${DEVICE} from ${MOUNT_POINT}"
|
${log} "Unmounted ${DEVICE} from ${MOUNT_POINT}"
|
||||||
/bin/rmdir "${MOUNT_POINT}"
|
if [ "`ls -A ${MOUNT_POINT}`" = "" ]; then
|
||||||
|
/bin/rm -fr "${MOUNT_POINT}"
|
||||||
|
fi
|
||||||
sed -i.bak "\@${MOUNT_POINT}@d" /var/log/usb-mount.track
|
sed -i.bak "\@${MOUNT_POINT}@d" /var/log/usb-mount.track
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -4,5 +4,5 @@ Description=Mount USB Drive on %i
|
|||||||
[Service]
|
[Service]
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
RemainAfterExit=true
|
RemainAfterExit=true
|
||||||
ExecStart=/oasis/util/shell/usb-mount.sh add %i
|
ExecStart=/casaOS/server/shell/usb-mount.sh add %i
|
||||||
ExecStop=/oasis/util/shell/usb-mount.sh remove %i
|
ExecStop=/casaOS/server/shell/usb-mount.sh remove %i
|
||||||
37
cmd/migration-tool/log.go
Normal file
37
cmd/migration-tool/log.go
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Logger struct {
|
||||||
|
DebugMode bool
|
||||||
|
|
||||||
|
_debug *log.Logger
|
||||||
|
_info *log.Logger
|
||||||
|
_error *log.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLogger() *Logger {
|
||||||
|
return &Logger{
|
||||||
|
DebugMode: false,
|
||||||
|
_debug: log.New(os.Stdout, "DEBUG: ", 0),
|
||||||
|
_info: log.New(os.Stdout, "", 0),
|
||||||
|
_error: log.New(os.Stderr, "ERROR: ", 0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Logger) Debug(format string, v ...interface{}) {
|
||||||
|
if l.DebugMode {
|
||||||
|
l._debug.Printf(format, v...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Logger) Info(format string, v ...interface{}) {
|
||||||
|
l._info.Printf(format, v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Logger) Error(format string, v ...interface{}) {
|
||||||
|
l._error.Printf(format, v...)
|
||||||
|
}
|
||||||
128
cmd/migration-tool/main.go
Normal file
128
cmd/migration-tool/main.go
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.org
|
||||||
|
* @Date: 2022-08-23 18:09:11
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-08-31 14:17:51
|
||||||
|
* @FilePath: /CasaOS/cmd/migration-tool/main.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
interfaces "github.com/IceWhaleTech/CasaOS-Common"
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/utils/systemctl"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/sqlite"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/types"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
casaosServiceName = "casaos.service"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
commit = "private build"
|
||||||
|
date = "private build"
|
||||||
|
|
||||||
|
_logger *Logger
|
||||||
|
sqliteDB *gorm.DB
|
||||||
|
|
||||||
|
configFlag = ""
|
||||||
|
dbFlag = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
versionFlag := flag.Bool("v", false, "version")
|
||||||
|
debugFlag := flag.Bool("d", true, "debug")
|
||||||
|
forceFlag := flag.Bool("f", true, "force")
|
||||||
|
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if *versionFlag {
|
||||||
|
fmt.Println("v" + types.CURRENTVERSION)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
println("git commit:", commit)
|
||||||
|
println("build date:", date)
|
||||||
|
|
||||||
|
_logger = NewLogger()
|
||||||
|
|
||||||
|
if os.Getuid() != 0 {
|
||||||
|
_logger.Info("Root privileges are required to run this program.")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if *debugFlag {
|
||||||
|
_logger.DebugMode = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !*forceFlag {
|
||||||
|
serviceEnabled, err := systemctl.IsServiceEnabled(casaosServiceName)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if serviceEnabled {
|
||||||
|
_logger.Info("%s is already enabled. If migration is still needed, try with -f.", casaosServiceName)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
config.InitSetup(configFlag)
|
||||||
|
|
||||||
|
if len(dbFlag) == 0 {
|
||||||
|
dbFlag = config.AppInfo.DBPath + "/db"
|
||||||
|
}
|
||||||
|
|
||||||
|
sqliteDB = sqlite.GetDb(dbFlag)
|
||||||
|
// gredis.GetRedisConn(config.RedisInfo),
|
||||||
|
|
||||||
|
service.MyService = service.NewService(sqliteDB, "", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
migrationTools := []interfaces.MigrationTool{
|
||||||
|
// nothing to migrate from last version
|
||||||
|
}
|
||||||
|
|
||||||
|
var selectedMigrationTool interfaces.MigrationTool
|
||||||
|
|
||||||
|
// look for the right migration tool matching current version
|
||||||
|
for _, tool := range migrationTools {
|
||||||
|
migrationNeeded, err := tool.IsMigrationNeeded()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if migrationNeeded {
|
||||||
|
selectedMigrationTool = tool
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if selectedMigrationTool == nil {
|
||||||
|
_logger.Error("selectedMigrationTool is null")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := selectedMigrationTool.PreMigrate(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := selectedMigrationTool.Migrate(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := selectedMigrationTool.PostMigrate(); err != nil {
|
||||||
|
_logger.Error("Migration succeeded, but post-migration failed: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
60
cmd/migration-tool/migration_dummy.go
Normal file
60
cmd/migration-tool/migration_dummy.go
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.org
|
||||||
|
* @Date: 2022-08-24 17:36:00
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-09-05 11:24:27
|
||||||
|
* @FilePath: /CasaOS/cmd/migration-tool/migration-034-035.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
interfaces "github.com/IceWhaleTech/CasaOS-Common"
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/utils/version"
|
||||||
|
)
|
||||||
|
|
||||||
|
type migrationTool struct{}
|
||||||
|
|
||||||
|
func (u *migrationTool) IsMigrationNeeded() (bool, error) {
|
||||||
|
majorVersion, minorVersion, patchVersion, err := version.DetectLegacyVersion()
|
||||||
|
if err != nil {
|
||||||
|
if err == version.ErrLegacyVersionNotFound {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if majorVersion > 0 {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if minorVersion > 3 {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if minorVersion == 3 && patchVersion > 5 {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.Info("Migration is needed for a CasaOS version 0.3.5 and older...")
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *migrationTool) PreMigrate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *migrationTool) Migrate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *migrationTool) PostMigrate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMigrationDummy() interfaces.MigrationTool {
|
||||||
|
return &migrationTool{}
|
||||||
|
}
|
||||||
25
conf/conf.conf.sample
Normal file
25
conf/conf.conf.sample
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
[app]
|
||||||
|
PAGE_SIZE = 10
|
||||||
|
RuntimeRootPath = runtime/
|
||||||
|
LogPath = /var/log/casaos/
|
||||||
|
LogSaveName = log
|
||||||
|
LogFileExt = log
|
||||||
|
DateStrFormat = 20060102
|
||||||
|
DateTimeFormat = 2006-01-02 15:04:05
|
||||||
|
TimeFormat = 15:04:05
|
||||||
|
DateFormat = 2006-01-02
|
||||||
|
DBPath = /var/lib/casaos
|
||||||
|
ShellPath = /usr/share/casaos/shell
|
||||||
|
UserDataPath = /var/lib/casaos/conf
|
||||||
|
|
||||||
|
[server]
|
||||||
|
RunMode = release
|
||||||
|
ServerApi = https://api.casaos.io/casaos-api
|
||||||
|
Handshake = socket.casaos.io
|
||||||
|
Token =
|
||||||
|
USBAutoMount =
|
||||||
|
|
||||||
|
[system]
|
||||||
|
|
||||||
|
[common]
|
||||||
|
RuntimePath=/var/run/casaos
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
[app]
|
|
||||||
PAGE_SIZE = 10
|
|
||||||
RuntimeRootPath = runtime/
|
|
||||||
LogSavePath = /casaOS/logs/server/
|
|
||||||
LogSaveName = log
|
|
||||||
LogFileExt = log
|
|
||||||
DateStrFormat = 20060102
|
|
||||||
DateTimeFormat = 2006-01-02 15:04:05
|
|
||||||
TimeFormat = 15:04:05
|
|
||||||
DateFormat = 2006-01-02
|
|
||||||
ProjectPath = /casaOS/server
|
|
||||||
|
|
||||||
|
|
||||||
[server]
|
|
||||||
HttpPort = 8089
|
|
||||||
RunMode = release
|
|
||||||
ServerApi = https://api.casaos.zimaboard.com
|
|
||||||
|
|
||||||
[user]
|
|
||||||
UserName = admin
|
|
||||||
PWD = zimaboard
|
|
||||||
Email = user@gmail.com
|
|
||||||
Description = description
|
|
||||||
Initialized = false
|
|
||||||
Token = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImVyZXJlIiwicGFzc3dvcmQiOiJhZHNmZGYiLCJleHAiOjE2MjQwMDU0ODEsImlzcyI6Imdpbi1ibG9nIn0.JNsCccZuFCwlSMLJg62iOIB2xymk_k7xGa11xhZ07bc
|
|
||||||
|
|
||||||
[zerotier]
|
|
||||||
UserName = user
|
|
||||||
PWD = pwd
|
|
||||||
Token = yBKYyavr2RdFAIVN7iTpzlsB1o6CqTgm
|
|
||||||
|
|
||||||
[redis]
|
|
||||||
Host = 127.0.0.1:6379
|
|
||||||
Password =
|
|
||||||
MaxIdle = 30
|
|
||||||
MaxActive = 30
|
|
||||||
IdleTimeout = 200
|
|
||||||
|
|
||||||
[system]
|
|
||||||
ConfigStr =
|
|
||||||
WidgetList =
|
|
||||||
|
|
||||||
88
go.mod
88
go.mod
@@ -3,70 +3,34 @@ module github.com/IceWhaleTech/CasaOS
|
|||||||
go 1.16
|
go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Microsoft/go-winio v0.5.0 // indirect
|
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d
|
||||||
github.com/Microsoft/hcsshim v0.8.22 // indirect
|
github.com/IceWhaleTech/CasaOS-Common v0.4.1-alpha2
|
||||||
github.com/PuerkitoBio/goquery v1.7.0
|
github.com/benbjohnson/clock v1.3.0 // indirect
|
||||||
github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect
|
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
|
||||||
github.com/bits-and-blooms/bitset v1.2.1 // indirect
|
github.com/disintegration/imaging v1.6.2
|
||||||
github.com/containerd/containerd v1.5.7
|
github.com/dsoprea/go-exif/v3 v3.0.0-20221012082141-d21ac8e2de85
|
||||||
github.com/containerd/continuity v0.2.0 // indirect
|
github.com/gin-contrib/gzip v0.0.6
|
||||||
github.com/docker/docker v20.10.7+incompatible
|
github.com/gin-gonic/gin v1.8.2
|
||||||
github.com/docker/go-connections v0.4.0
|
github.com/glebarez/sqlite v1.6.0
|
||||||
github.com/forease/gotld v0.0.0-20190808124948-c50ff635576b
|
github.com/go-ini/ini v1.67.0
|
||||||
github.com/gin-contrib/gzip v0.0.2 // indirect
|
github.com/golang/mock v1.6.0
|
||||||
github.com/gin-gonic/gin v1.7.2
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/go-ini/ini v1.62.0
|
github.com/gomodule/redigo v1.8.9
|
||||||
github.com/go-ole/go-ole v1.2.5 // indirect
|
|
||||||
github.com/go-openapi/spec v0.20.4 // indirect
|
|
||||||
github.com/go-playground/validator/v10 v10.6.1 // indirect
|
|
||||||
github.com/gogo/googleapis v1.4.1 // indirect
|
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible
|
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
|
||||||
github.com/gomodule/redigo v1.8.5
|
|
||||||
github.com/google/go-github/v36 v36.0.0
|
github.com/google/go-github/v36 v36.0.0
|
||||||
github.com/google/uuid v1.3.0 // indirect
|
github.com/googollee/go-socket.io v1.6.2
|
||||||
github.com/gorilla/mux v1.8.0 // indirect
|
github.com/gorilla/websocket v1.5.0
|
||||||
github.com/gorilla/websocket v1.4.2
|
github.com/hirochachacha/go-smb2 v1.1.0
|
||||||
github.com/jinzhu/copier v0.3.2
|
github.com/klauspost/compress v1.15.13 // indirect
|
||||||
github.com/json-iterator/go v1.1.11 // indirect
|
github.com/mholt/archiver/v3 v3.5.1
|
||||||
github.com/klauspost/compress v1.13.6 // indirect
|
|
||||||
github.com/leodido/go-urn v1.2.1 // indirect
|
|
||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
|
||||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
|
||||||
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
|
||||||
github.com/morikuni/aec v1.0.0 // indirect
|
|
||||||
github.com/opencontainers/selinux v1.8.5 // indirect
|
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||||
github.com/pkg/errors v0.9.1
|
|
||||||
github.com/prestonTao/upnp v0.0.0-20150206124352-f4370df5e109
|
|
||||||
github.com/prometheus/procfs v0.7.3 // indirect
|
|
||||||
github.com/robfig/cron v1.2.0
|
github.com/robfig/cron v1.2.0
|
||||||
github.com/satori/go.uuid v1.2.0
|
github.com/satori/go.uuid v1.2.0
|
||||||
github.com/shirou/gopsutil/v3 v3.21.5
|
github.com/shirou/gopsutil/v3 v3.22.11
|
||||||
github.com/sirupsen/logrus v1.8.1
|
github.com/stretchr/testify v1.8.1
|
||||||
github.com/smartystreets/assertions v1.2.0 // indirect
|
github.com/tidwall/gjson v1.14.4
|
||||||
github.com/smartystreets/goconvey v1.6.4 // indirect
|
go.uber.org/zap v1.24.0
|
||||||
github.com/swaggo/gin-swagger v1.3.0
|
golang.org/x/crypto v0.4.0
|
||||||
github.com/swaggo/swag v1.7.3
|
golang.org/x/oauth2 v0.3.0
|
||||||
github.com/tidwall/gjson v1.8.0
|
gorm.io/gorm v1.24.2
|
||||||
github.com/tidwall/pretty v1.2.0 // indirect
|
gotest.tools v2.2.0+incompatible
|
||||||
github.com/tklauser/go-sysconf v0.3.6 // indirect
|
|
||||||
github.com/ugorji/go v1.2.6 // indirect
|
|
||||||
go.opencensus.io v0.23.0 // indirect
|
|
||||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
|
|
||||||
golang.org/x/mod v0.5.0 // indirect
|
|
||||||
golang.org/x/net v0.0.0-20211020060615-d418f374d309 // indirect
|
|
||||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f
|
|
||||||
golang.org/x/sys v0.0.0-20211020174200-9d6173849985 // indirect
|
|
||||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect
|
|
||||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
|
||||||
golang.org/x/tools v0.1.7 // indirect
|
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
|
||||||
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0 // indirect
|
|
||||||
google.golang.org/grpc v1.41.0 // indirect
|
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
|
||||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
|
||||||
gorm.io/driver/sqlite v1.1.5
|
|
||||||
gorm.io/gorm v1.21.15
|
|
||||||
)
|
)
|
||||||
|
|||||||
18
interfaces/migrationTool.go
Normal file
18
interfaces/migrationTool.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.org
|
||||||
|
* @Date: 2022-08-24 17:37:36
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-08-24 17:38:48
|
||||||
|
* @FilePath: /CasaOS/interfaces/migrationTool.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package interfaces
|
||||||
|
|
||||||
|
type MigrationTool interface {
|
||||||
|
IsMigrationNeeded() (bool, error)
|
||||||
|
PostMigrate() error
|
||||||
|
Migrate() error
|
||||||
|
PreMigrate() error
|
||||||
|
}
|
||||||
157
main.go
157
main.go
@@ -3,35 +3,69 @@ package main
|
|||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/utils/constants"
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/cache"
|
"github.com/IceWhaleTech/CasaOS/pkg/cache"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/sqlite"
|
"github.com/IceWhaleTech/CasaOS/pkg/sqlite"
|
||||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
"github.com/IceWhaleTech/CasaOS/route"
|
"github.com/IceWhaleTech/CasaOS/route"
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/types"
|
||||||
|
"github.com/coreos/go-systemd/daemon"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
|
||||||
"github.com/robfig/cron"
|
"github.com/robfig/cron"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const LOCALHOST = "127.0.0.1"
|
||||||
|
|
||||||
var sqliteDB *gorm.DB
|
var sqliteDB *gorm.DB
|
||||||
|
|
||||||
var configFlag = flag.String("c", "", "config address")
|
var (
|
||||||
|
commit = "private build"
|
||||||
|
date = "private build"
|
||||||
|
|
||||||
var showUserInfo = flag.Bool("show-user-info", false, "show user info")
|
configFlag = flag.String("c", "", "config address")
|
||||||
|
dbFlag = flag.String("db", "", "db path")
|
||||||
|
versionFlag = flag.Bool("v", false, "version")
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
if *versionFlag {
|
||||||
|
fmt.Println("v" + types.CURRENTVERSION)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
println("git commit:", commit)
|
||||||
|
println("build date:", date)
|
||||||
|
|
||||||
config.InitSetup(*configFlag)
|
config.InitSetup(*configFlag)
|
||||||
config.UpdateSetup()
|
|
||||||
loger2.LogSetup()
|
logger.LogInit(config.AppInfo.LogPath, config.AppInfo.LogSaveName, config.AppInfo.LogFileExt)
|
||||||
sqliteDB = sqlite.GetDb(config.AppInfo.ProjectPath)
|
if len(*dbFlag) == 0 {
|
||||||
//gredis.GetRedisConn(config.RedisInfo),
|
*dbFlag = config.AppInfo.DBPath + "/db"
|
||||||
service.MyService = service.NewService(sqliteDB, loger2.NewOLoger())
|
}
|
||||||
|
|
||||||
|
sqliteDB = sqlite.GetDb(*dbFlag)
|
||||||
|
// gredis.GetRedisConn(config.RedisInfo),
|
||||||
|
|
||||||
|
service.MyService = service.NewService(sqliteDB, config.CommonInfo.RuntimePath, route.SocketIo())
|
||||||
|
|
||||||
service.Cache = cache.Init()
|
service.Cache = cache.Init()
|
||||||
|
|
||||||
|
service.GetCPUThermalZone()
|
||||||
|
|
||||||
route.InitFunction()
|
route.InitFunction()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,36 +81,97 @@ func init() {
|
|||||||
// @name Authorization
|
// @name Authorization
|
||||||
// @BasePath /v1
|
// @BasePath /v1
|
||||||
func main() {
|
func main() {
|
||||||
if *showUserInfo {
|
if *versionFlag {
|
||||||
fmt.Println("CasaOS User Info")
|
|
||||||
fmt.Println("UserName:" + config.UserInfo.UserName)
|
|
||||||
fmt.Println("Password:" + config.UserInfo.PWD)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//model.Setup()
|
// model.Setup()
|
||||||
//gredis.Setup()
|
// gredis.Setup()
|
||||||
|
|
||||||
r := route.InitRouter()
|
r := route.InitRouter()
|
||||||
//service.SyncTask(sqliteDB)
|
defer service.SocketServer.Close()
|
||||||
cron2 := cron.New() //创建一个cron实例
|
r.GET("/v1/socketio/*any", gin.WrapH(service.SocketServer))
|
||||||
//执行定时任务(每5秒执行一次)
|
r.POST("/v1/socketio/*any", gin.WrapH(service.SocketServer))
|
||||||
err := cron2.AddFunc("0 0 0 1/1 * *", func() {
|
|
||||||
//service.UpdataDDNSList(mysqldb)
|
// service.SyncTask(sqliteDB)
|
||||||
//service.SyncTask(sqliteDB)
|
cron2 := cron.New()
|
||||||
|
// every day execution
|
||||||
|
|
||||||
|
err := cron2.AddFunc("0/5 * * * * *", func() {
|
||||||
|
if service.ClientCount > 0 {
|
||||||
|
// route.SendNetINfoBySocket()
|
||||||
|
// route.SendCPUBySocket()
|
||||||
|
// route.SendMemBySocket()
|
||||||
|
// route.SendDiskBySocket()
|
||||||
|
// route.SendUSBBySocket()
|
||||||
|
route.SendAllHardwareStatusBySocket()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
//启动/关闭
|
|
||||||
cron2.Start()
|
cron2.Start()
|
||||||
defer cron2.Stop()
|
|
||||||
s := &http.Server{
|
|
||||||
Addr: fmt.Sprintf(":%v", config.ServerInfo.HttpPort),
|
|
||||||
Handler: r,
|
|
||||||
ReadTimeout: 60 * time.Second,
|
|
||||||
WriteTimeout: 60 * time.Second,
|
|
||||||
MaxHeaderBytes: 1 << 20,
|
|
||||||
}
|
|
||||||
s.ListenAndServe()
|
|
||||||
|
|
||||||
|
defer cron2.Stop()
|
||||||
|
|
||||||
|
listener, err := net.Listen("tcp", net.JoinHostPort(LOCALHOST, "0"))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
routers := []string{"sys", "port", "file", "folder", "batch", "image", "samba", "notify", "socketio"}
|
||||||
|
for _, v := range routers {
|
||||||
|
err = service.MyService.Gateway().CreateRoute(&model.Route{
|
||||||
|
Path: "/v1/" + v,
|
||||||
|
Target: "http://" + listener.Addr().String(),
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("err", err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
time.Sleep(time.Second * 2)
|
||||||
|
// v0.3.6
|
||||||
|
if config.ServerInfo.HttpPort != "" {
|
||||||
|
changePort := model.ChangePortRequest{}
|
||||||
|
changePort.Port = config.ServerInfo.HttpPort
|
||||||
|
err := service.MyService.Gateway().ChangePort(&changePort)
|
||||||
|
if err == nil {
|
||||||
|
config.Cfg.Section("server").Key("HttpPort").SetValue("")
|
||||||
|
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
urlFilePath := filepath.Join(config.CommonInfo.RuntimePath, "casaos.url")
|
||||||
|
if err := file.CreateFileAndWriteContent(urlFilePath, "http://"+listener.Addr().String()); err != nil {
|
||||||
|
logger.Error("error when creating address file", zap.Error(err),
|
||||||
|
zap.Any("address", listener.Addr().String()),
|
||||||
|
zap.Any("filepath", urlFilePath),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// run any script that needs to be executed
|
||||||
|
scriptDirectory := filepath.Join(constants.DefaultConfigPath, "start.d")
|
||||||
|
command.ExecuteScripts(scriptDirectory)
|
||||||
|
|
||||||
|
if supported, err := daemon.SdNotify(false, daemon.SdNotifyReady); err != nil {
|
||||||
|
logger.Error("Failed to notify systemd that casaos main service is ready", zap.Any("error", err))
|
||||||
|
} else if supported {
|
||||||
|
logger.Info("Notified systemd that casaos main service is ready")
|
||||||
|
} else {
|
||||||
|
logger.Info("This process is not running as a systemd service.")
|
||||||
|
}
|
||||||
|
|
||||||
|
s := &http.Server{
|
||||||
|
Handler: r,
|
||||||
|
ReadHeaderTimeout: 5 * time.Second, // fix G112: Potential slowloris attack (see https://github.com/securego/gosec)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("CasaOS main service is listening...", zap.Any("address", listener.Addr().String()))
|
||||||
|
|
||||||
|
err = s.Serve(listener) // not using http.serve() to fix G114: Use of net/http serve function that has no support for setting timeouts (see https://github.com/securego/gosec)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
package middleware
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Cors() gin.HandlerFunc {
|
|
||||||
return func(c *gin.Context) {
|
|
||||||
method := c.Request.Method
|
|
||||||
//origin := c.Request.Header.Get("Origin") //请求头部
|
|
||||||
//if origin != "" {
|
|
||||||
//接收客户端发送的origin (重要!)
|
|
||||||
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
|
|
||||||
c.Header("Access-Control-Allow-Origin", "*")
|
|
||||||
//服务器支持的所有跨域请求的方法
|
|
||||||
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE")
|
|
||||||
//允许跨域设置可以返回其他子段,可以自定义字段
|
|
||||||
c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session")
|
|
||||||
// 允许浏览器(客户端)可以解析的头部 (重要)
|
|
||||||
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers")
|
|
||||||
//设置缓存时间
|
|
||||||
c.Header("Access-Control-Max-Age", "172800")
|
|
||||||
//允许客户端传递校验信息比如 cookie (重要)
|
|
||||||
c.Header("Access-Control-Allow-Credentials", "true")
|
|
||||||
c.Set("content-type", "application/json")
|
|
||||||
//}
|
|
||||||
|
|
||||||
//允许类型校验
|
|
||||||
if method == "OPTIONS" {
|
|
||||||
c.JSON(http.StatusOK, "ok!")
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if err := recover(); err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
c.Next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
103
model/app.go
103
model/app.go
@@ -1,103 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql/driver"
|
|
||||||
"encoding/json"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ServerAppList struct {
|
|
||||||
Id uint `gorm:"column:id;primary_key" json:"id"`
|
|
||||||
Title string `json:"title"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
Tagline string `json:"tagline"`
|
|
||||||
Tags Strings `gorm:"type:json" json:"tags"`
|
|
||||||
Icon string `json:"icon"`
|
|
||||||
ScreenshotLink Strings `gorm:"type:json" json:"screenshot_link"`
|
|
||||||
Category string `json:"category"`
|
|
||||||
PortMap string `json:"port_map"`
|
|
||||||
ImageVersion string `json:"image_version"`
|
|
||||||
Tip string `json:"tip"`
|
|
||||||
Envs EnvArray `json:"envs"`
|
|
||||||
Ports PortArray `json:"ports"`
|
|
||||||
Volumes PathArray `json:"volumes"`
|
|
||||||
Devices PathArray `json:"devices"`
|
|
||||||
NetworkModel string `json:"network_model"`
|
|
||||||
Image string `json:"image"`
|
|
||||||
Index string `json:"index"`
|
|
||||||
CreatedAt time.Time `json:"created_at"`
|
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
|
||||||
State string `json:"state"`
|
|
||||||
Author string `json:"author"`
|
|
||||||
MinMemory int `json:"min_memory"`
|
|
||||||
MinDisk int `json:"min_disk"`
|
|
||||||
MaxMemory uint64 `json:"max_memory"`
|
|
||||||
Thumbnail string `json:"thumbnail"`
|
|
||||||
Healthy string `json:"healthy"`
|
|
||||||
Plugins Strings `json:"plugins"`
|
|
||||||
Origin string `json:"origin"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Ports struct {
|
|
||||||
ContainerPort uint `json:"container_port"`
|
|
||||||
CommendPort int `json:"commend_port"`
|
|
||||||
Desc string `json:"desc"`
|
|
||||||
Type int `json:"type"` // 1:必选 2:可选 3:默认值不必显示 4:系统处理 5:container内容也可编辑
|
|
||||||
}
|
|
||||||
|
|
||||||
type Volume struct {
|
|
||||||
ContainerPath string `json:"container_path"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
Desc string `json:"desc"`
|
|
||||||
Type int `json:"type"` // 1:必选 2:可选 3:默认值不必显示 4:系统处理 5:container内容也可编辑
|
|
||||||
}
|
|
||||||
|
|
||||||
type Envs struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Value string `json:"value"`
|
|
||||||
Desc string `json:"desc"`
|
|
||||||
Type int `json:"type"` // 1:必选 2:可选 3:默认值不必显示 4:系统处理 5:container内容也可编辑
|
|
||||||
}
|
|
||||||
|
|
||||||
type Devices struct {
|
|
||||||
ContainerPath string `json:"container_path"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
Desc string `json:"desc"`
|
|
||||||
Type int `json:"type"` // 1:必选 2:可选 3:默认值不必显示 4:系统处理 5:container内容也可编辑
|
|
||||||
}
|
|
||||||
|
|
||||||
type configures struct {
|
|
||||||
TcpPorts []Ports `json:"tcp_ports"`
|
|
||||||
UdpPorts []Ports `json:"udp_ports"`
|
|
||||||
Envs []Envs `json:"envs"`
|
|
||||||
Volumes []Volume `json:"volumes"`
|
|
||||||
Devices []Devices `json:"devices"`
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************使gorm支持[]string结构*******************/
|
|
||||||
type Strings []string
|
|
||||||
|
|
||||||
func (c Strings) Value() (driver.Value, error) {
|
|
||||||
b, err := json.Marshal(c)
|
|
||||||
return string(b), err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Strings) Scan(input interface{}) error {
|
|
||||||
return json.Unmarshal(input.([]byte), c)
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************使gorm支持[]string结构*******************/
|
|
||||||
|
|
||||||
/****************使gorm支持[]string结构*******************/
|
|
||||||
type MapStrings []map[string]string
|
|
||||||
|
|
||||||
func (c MapStrings) Value() (driver.Value, error) {
|
|
||||||
b, err := json.Marshal(c)
|
|
||||||
return string(b), err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *MapStrings) Scan(input interface{}) error {
|
|
||||||
return json.Unmarshal(input.([]byte), c)
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************使gorm支持[]string结构*******************/
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
type ServerCategoryList struct {
|
|
||||||
Id uint `gorm:"column:id;primary_key" json:"id"`
|
|
||||||
//CreatedAt time.Time `json:"created_at"`
|
|
||||||
//
|
|
||||||
//UpdatedAt time.Time `json:"updated_at"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Count uint `json:"count"`
|
|
||||||
}
|
|
||||||
20
model/connections.go
Normal file
20
model/connections.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.org
|
||||||
|
* @Date: 2022-07-27 10:30:43
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-08-04 20:06:04
|
||||||
|
* @FilePath: /CasaOS/model/connections.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package model
|
||||||
|
|
||||||
|
type Connections struct {
|
||||||
|
ID uint `json:"id"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
Password string `json:"password,omitempty"`
|
||||||
|
Host string `json:"host"`
|
||||||
|
Port string `json:"port"`
|
||||||
|
MountPoint string `json:"mount_point"`
|
||||||
|
}
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
type LSBLKModel struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
FsType string `json:"fstype"`
|
|
||||||
Size uint64 `json:"size"`
|
|
||||||
FSSize string `json:"fssize"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
Model string `json:"model"` //设备标识符
|
|
||||||
RM bool `json:"rm"` //是否为可移动设备
|
|
||||||
RO bool `json:"ro"` //是否为只读设备
|
|
||||||
State string `json:"state"`
|
|
||||||
PhySec int `json:"phy-sec"` //物理扇区大小
|
|
||||||
Type string `json:"type"`
|
|
||||||
Vendor string `json:"vendor"` //供应商
|
|
||||||
Rev string `json:"rev"` //修订版本
|
|
||||||
FSAvail string `json:"fsavail"` //可用空间
|
|
||||||
FSUse string `json:"fsuse%"` //已用百分比
|
|
||||||
MountPoint string `json:"mountpoint"`
|
|
||||||
Format string `json:"format"`
|
|
||||||
Health string `json:"health"`
|
|
||||||
HotPlug bool `json:"hotplug"`
|
|
||||||
FSUsed string `json:"fsused"`
|
|
||||||
Tran string `json:"tran"`
|
|
||||||
MinIO uint64 `json:"min-io"`
|
|
||||||
UsedPercent float64 `json:"used_percent"`
|
|
||||||
Children []LSBLKModel `json:"children"`
|
|
||||||
//详情特有
|
|
||||||
StartSector uint64 `json:"start_sector,omitempty"`
|
|
||||||
EndSector uint64 `json:"end_sector,omitempty"`
|
|
||||||
}
|
|
||||||
33
model/file.go
Normal file
33
model/file.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.com
|
||||||
|
* @Date: 2022-05-20 16:27:12
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-06-09 18:18:46
|
||||||
|
* @FilePath: /CasaOS/model/file.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package model
|
||||||
|
|
||||||
|
type FileOperate struct {
|
||||||
|
Type string `json:"type" binding:"required"`
|
||||||
|
Item []FileItem `json:"item" binding:"required"`
|
||||||
|
TotalSize int64 `json:"total_size"`
|
||||||
|
ProcessedSize int64 `json:"processed_size"`
|
||||||
|
To string `json:"to" binding:"required"`
|
||||||
|
Style string `json:"style"`
|
||||||
|
Finished bool `json:"finished"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileItem struct {
|
||||||
|
From string `json:"from" binding:"required"`
|
||||||
|
Finished bool `json:"finished"`
|
||||||
|
Size int64 `json:"size"`
|
||||||
|
ProcessedSize int64 `json:"processed_size"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileUpdate struct {
|
||||||
|
FilePath string `json:"path" binding:"required"`
|
||||||
|
FileContent string `json:"content" binding:"required"`
|
||||||
|
}
|
||||||
6
model/heart.go
Normal file
6
model/heart.go
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type CasaOSHeart struct {
|
||||||
|
UuId string `json:"uuid"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
}
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql/driver"
|
|
||||||
"encoding/json"
|
|
||||||
)
|
|
||||||
|
|
||||||
type TcpPorts struct {
|
|
||||||
Desc string `json:"desc"`
|
|
||||||
ContainerPort int `json:"container_port"`
|
|
||||||
}
|
|
||||||
type UdpPorts struct {
|
|
||||||
Desc string `json:"desc"`
|
|
||||||
ContainerPort int `json:"container_port"`
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************使用gorm支持json************************************/
|
|
||||||
|
|
||||||
type PortMap struct {
|
|
||||||
ContainerPort string `json:"container"`
|
|
||||||
CommendPort string `json:"host"`
|
|
||||||
Protocol string `json:"protocol"`
|
|
||||||
Desc string `json:"desc"`
|
|
||||||
Type int `json:"type"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type PortArray []PortMap
|
|
||||||
|
|
||||||
// Value 实现方法
|
|
||||||
func (p PortArray) Value() (driver.Value, error) {
|
|
||||||
return json.Marshal(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scan 实现方法
|
|
||||||
func (p *PortArray) Scan(input interface{}) error {
|
|
||||||
return json.Unmarshal(input.([]byte), p)
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
|
|
||||||
/*******************使用gorm支持json************************************/
|
|
||||||
|
|
||||||
type Env struct {
|
|
||||||
Name string `json:"container"`
|
|
||||||
Value string `json:"host"`
|
|
||||||
Desc string `json:"desc"`
|
|
||||||
Type int `json:"type"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type JSON json.RawMessage
|
|
||||||
|
|
||||||
type EnvArray []Env
|
|
||||||
|
|
||||||
// Value 实现方法
|
|
||||||
func (p EnvArray) Value() (driver.Value, error) {
|
|
||||||
return json.Marshal(p)
|
|
||||||
//return .MarshalJSON()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scan 实现方法
|
|
||||||
func (p *EnvArray) Scan(input interface{}) error {
|
|
||||||
return json.Unmarshal(input.([]byte), p)
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
|
|
||||||
/*******************使用gorm支持json************************************/
|
|
||||||
|
|
||||||
type PathMap struct {
|
|
||||||
ContainerPath string `json:"container"`
|
|
||||||
Path string `json:"host"`
|
|
||||||
Type int `json:"type"`
|
|
||||||
Desc string `json:"desc"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type PathArray []PathMap
|
|
||||||
|
|
||||||
// Value 实现方法
|
|
||||||
func (p PathArray) Value() (driver.Value, error) {
|
|
||||||
return json.Marshal(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scan 实现方法
|
|
||||||
func (p *PathArray) Scan(input interface{}) error {
|
|
||||||
return json.Unmarshal(input.([]byte), p)
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
|
|
||||||
//type PostData struct {
|
|
||||||
// Envs EnvArrey `json:"envs,omitempty"`
|
|
||||||
// Udp PortArrey `json:"udp_ports"`
|
|
||||||
// Tcp PortArrey `json:"tcp_ports"`
|
|
||||||
// Volumes PathArrey `json:"volumes"`
|
|
||||||
// Devices PathArrey `json:"devices"`
|
|
||||||
// Port string `json:"port,omitempty"`
|
|
||||||
// PortMap string `json:"port_map"`
|
|
||||||
// CpuShares int64 `json:"cpu_shares,omitempty"`
|
|
||||||
// Memory int64 `json:"memory,omitempty"`
|
|
||||||
// Restart string `json:"restart,omitempty"`
|
|
||||||
// EnableUPNP bool `json:"enable_upnp"`
|
|
||||||
// Label string `json:"label"`
|
|
||||||
// Position bool `json:"position"`
|
|
||||||
//}
|
|
||||||
|
|
||||||
type CustomizationPostData struct {
|
|
||||||
Origin string `json:"origin"`
|
|
||||||
NetworkModel string `json:"network_model"`
|
|
||||||
Index string `json:"index"`
|
|
||||||
Icon string `json:"icon"`
|
|
||||||
Image string `json:"image"`
|
|
||||||
Envs EnvArray `json:"envs"`
|
|
||||||
Ports PortArray `json:"ports"`
|
|
||||||
Volumes PathArray `json:"volumes"`
|
|
||||||
Devices PathArray `json:"devices"`
|
|
||||||
//Port string `json:"port,omitempty"`
|
|
||||||
PortMap string `json:"port_map"`
|
|
||||||
CpuShares int64 `json:"cpu_shares"`
|
|
||||||
Memory int64 `json:"memory"`
|
|
||||||
Restart string `json:"restart"`
|
|
||||||
EnableUPNP bool `json:"enable_upnp"`
|
|
||||||
Label string `json:"label"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
Position bool `json:"position"`
|
|
||||||
}
|
|
||||||
28
model/net.go
28
model/net.go
@@ -1,19 +1,17 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
type IOCountersStat struct {
|
type IOCountersStat struct {
|
||||||
Name string `json:"name"` // interface name
|
Name string `json:"name"` // interface name
|
||||||
BytesSent uint64 `json:"bytesSent"` // number of bytes sent
|
BytesSent uint64 `json:"bytesSent"` // number of bytes sent
|
||||||
BytesRecv uint64 `json:"bytesRecv"` // number of bytes received
|
BytesRecv uint64 `json:"bytesRecv"` // number of bytes received
|
||||||
PacketsSent uint64 `json:"packetsSent"` // number of packets sent
|
PacketsSent uint64 `json:"packetsSent"` // number of packets sent
|
||||||
PacketsRecv uint64 `json:"packetsRecv"` // number of packets received
|
PacketsRecv uint64 `json:"packetsRecv"` // number of packets received
|
||||||
Errin uint64 `json:"errin"` // total number of errors while receiving
|
Errin uint64 `json:"errin"` // total number of errors while receiving
|
||||||
Errout uint64 `json:"errout"` // total number of errors while sending
|
Errout uint64 `json:"errout"` // total number of errors while sending
|
||||||
Dropin uint64 `json:"dropin"` // total number of incoming packets which were dropped
|
Dropin uint64 `json:"dropin"` // total number of incoming packets which were dropped
|
||||||
Dropout uint64 `json:"dropout"` // total number of outgoing packets which were dropped (always 0 on OSX and BSD)
|
Dropout uint64 `json:"dropout"` // total number of outgoing packets which were dropped (always 0 on OSX and BSD)
|
||||||
Fifoin uint64 `json:"fifoin"` // total number of FIFO buffers errors while receiving
|
Fifoin uint64 `json:"fifoin"` // total number of FIFO buffers errors while receiving
|
||||||
Fifoout uint64 `json:"fifoout"` // total number of FIFO buffers errors while sending
|
Fifoout uint64 `json:"fifoout"` // total number of FIFO buffers errors while sending
|
||||||
State string `json:"state"`
|
State string `json:"state"`
|
||||||
DateTime time.Time `json:"date_time"`
|
Time int64 `json:"time"`
|
||||||
}
|
}
|
||||||
|
|||||||
6
model/notify.go
Normal file
6
model/notify.go
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type NotifyMssage struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Data string `json:"data"`
|
||||||
|
}
|
||||||
22
model/notify/file.go
Normal file
22
model/notify/file.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.com
|
||||||
|
* @Date: 2022-05-26 14:21:57
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-06-02 11:14:15
|
||||||
|
* @FilePath: /CasaOS/model/notify/file.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package notify
|
||||||
|
|
||||||
|
type File struct {
|
||||||
|
Finished bool `json:"finished"`
|
||||||
|
ProcessedSize int64 `json:"processed_size"`
|
||||||
|
ProcessingPath string `json:"processing_path"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
TotalSize int64 `json:"total_size"`
|
||||||
|
Id string `json:"id"`
|
||||||
|
To string `json:"to"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
}
|
||||||
18
model/notify/result.go
Normal file
18
model/notify/result.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.com
|
||||||
|
* @Date: 2022-05-26 14:21:11
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-05-27 11:15:59
|
||||||
|
* @FilePath: /CasaOS/model/notify/result.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package notify
|
||||||
|
|
||||||
|
// Notify struct for Notify
|
||||||
|
type NotifyModel struct {
|
||||||
|
Data interface{} `json:"data"`
|
||||||
|
State string `json:"state"`
|
||||||
|
}
|
||||||
19
model/notify/storage.go
Normal file
19
model/notify/storage.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.com
|
||||||
|
* @Date: 2022-07-15 10:43:00
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-07-15 10:56:17
|
||||||
|
* @FilePath: /CasaOS/model/notify/storage.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package notify
|
||||||
|
|
||||||
|
type StorageMessage struct {
|
||||||
|
Type string `json:"type"` //sata,usb
|
||||||
|
Action string `json:"action"` //remove add
|
||||||
|
Path string `json:"path"`
|
||||||
|
Volume string `json:"volume"`
|
||||||
|
Size uint64 `json:"size"`
|
||||||
|
}
|
||||||
17
model/share.go
Normal file
17
model/share.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.org
|
||||||
|
* @Date: 2022-07-26 11:12:12
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-07-27 14:58:55
|
||||||
|
* @FilePath: /CasaOS/model/share.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package model
|
||||||
|
|
||||||
|
type Shares struct {
|
||||||
|
ID uint `json:"id"`
|
||||||
|
Anonymous bool `json:"anonymous"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
}
|
||||||
69
model/smartctl_model.go
Normal file
69
model/smartctl_model.go
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
//
|
||||||
|
type SmartctlA struct {
|
||||||
|
Smartctl struct {
|
||||||
|
Version []int `json:"version"`
|
||||||
|
SvnRevision string `json:"svn_revision"`
|
||||||
|
PlatformInfo string `json:"platform_info"`
|
||||||
|
BuildInfo string `json:"build_info"`
|
||||||
|
Argv []string `json:"argv"`
|
||||||
|
ExitStatus int `json:"exit_status"`
|
||||||
|
} `json:"smartctl"`
|
||||||
|
Device struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
InfoName string `json:"info_name"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Protocol string `json:"protocol"`
|
||||||
|
} `json:"device"`
|
||||||
|
ModelName string `json:"model_name"`
|
||||||
|
SerialNumber string `json:"serial_number"`
|
||||||
|
FirmwareVersion string `json:"firmware_version"`
|
||||||
|
UserCapacity struct {
|
||||||
|
Blocks int `json:"blocks"`
|
||||||
|
Bytes int64 `json:"bytes"`
|
||||||
|
} `json:"user_capacity"`
|
||||||
|
SmartStatus struct {
|
||||||
|
Passed bool `json:"passed"`
|
||||||
|
} `json:"smart_status"`
|
||||||
|
AtaSmartData struct {
|
||||||
|
OfflineDataCollection struct {
|
||||||
|
Status struct {
|
||||||
|
Value int `json:"value"`
|
||||||
|
String string `json:"string"`
|
||||||
|
} `json:"status"`
|
||||||
|
CompletionSeconds int `json:"completion_seconds"`
|
||||||
|
} `json:"offline_data_collection"`
|
||||||
|
SelfTest struct {
|
||||||
|
Status struct {
|
||||||
|
Value int `json:"value"`
|
||||||
|
String string `json:"string"`
|
||||||
|
Passed bool `json:"passed"`
|
||||||
|
} `json:"status"`
|
||||||
|
PollingMinutes struct {
|
||||||
|
Short int `json:"short"`
|
||||||
|
Extended int `json:"extended"`
|
||||||
|
Conveyance int `json:"conveyance"`
|
||||||
|
} `json:"polling_minutes"`
|
||||||
|
} `json:"self_test"`
|
||||||
|
Capabilities struct {
|
||||||
|
Values []int `json:"values"`
|
||||||
|
ExecOfflineImmediateSupported bool `json:"exec_offline_immediate_supported"`
|
||||||
|
OfflineIsAbortedUponNewCmd bool `json:"offline_is_aborted_upon_new_cmd"`
|
||||||
|
OfflineSurfaceScanSupported bool `json:"offline_surface_scan_supported"`
|
||||||
|
SelfTestsSupported bool `json:"self_tests_supported"`
|
||||||
|
ConveyanceSelfTestSupported bool `json:"conveyance_self_test_supported"`
|
||||||
|
SelectiveSelfTestSupported bool `json:"selective_self_test_supported"`
|
||||||
|
AttributeAutosaveEnabled bool `json:"attribute_autosave_enabled"`
|
||||||
|
ErrorLoggingSupported bool `json:"error_logging_supported"`
|
||||||
|
GpLoggingSupported bool `json:"gp_logging_supported"`
|
||||||
|
} `json:"capabilities"`
|
||||||
|
} `json:"ata_smart_data"`
|
||||||
|
PowerOnTime struct {
|
||||||
|
Hours int `json:"hours"`
|
||||||
|
} `json:"power_on_time"`
|
||||||
|
PowerCycleCount int `json:"power_cycle_count"`
|
||||||
|
Temperature struct {
|
||||||
|
Current int `json:"current"`
|
||||||
|
} `json:"temperature"`
|
||||||
|
}
|
||||||
@@ -1,57 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.com
|
||||||
|
* @Date: 2022-05-13 18:15:46
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-09-02 22:12:34
|
||||||
|
* @FilePath: /CasaOS/model/sys_common.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
package model
|
package model
|
||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
//系统配置
|
// 系统配置
|
||||||
type SysInfoModel struct {
|
type SysInfoModel struct {
|
||||||
Name string //系统名称
|
Name string // 系统名称
|
||||||
}
|
}
|
||||||
|
|
||||||
//用户相关
|
// 服务配置
|
||||||
type UserModel struct {
|
|
||||||
UserName string
|
|
||||||
PWD string
|
|
||||||
Token string
|
|
||||||
Head string
|
|
||||||
Email string
|
|
||||||
Description string
|
|
||||||
Initialized bool
|
|
||||||
}
|
|
||||||
|
|
||||||
//服务配置
|
|
||||||
type ServerModel struct {
|
type ServerModel struct {
|
||||||
HttpPort string
|
HttpPort string
|
||||||
RunMode string
|
RunMode string
|
||||||
ServerApi string
|
ServerApi string
|
||||||
|
LockAccount bool
|
||||||
|
Token string
|
||||||
|
USBAutoMount string
|
||||||
|
UpdateUrl string
|
||||||
}
|
}
|
||||||
|
|
||||||
//服务配置
|
// 服务配置
|
||||||
type APPModel struct {
|
type APPModel struct {
|
||||||
LogSavePath string
|
LogPath string
|
||||||
LogSaveName string
|
LogSaveName string
|
||||||
LogFileExt string
|
LogFileExt string
|
||||||
DateStrFormat string
|
DateStrFormat string
|
||||||
DateTimeFormat string
|
DateTimeFormat string
|
||||||
|
UserDataPath string
|
||||||
TimeFormat string
|
TimeFormat string
|
||||||
DateFormat string
|
DateFormat string
|
||||||
ProjectPath string
|
DBPath string
|
||||||
|
ShellPath string
|
||||||
|
}
|
||||||
|
type CommonModel struct {
|
||||||
|
RuntimePath string
|
||||||
}
|
}
|
||||||
|
|
||||||
//公共返回模型
|
// 公共返回模型
|
||||||
type Result struct {
|
type Result struct {
|
||||||
Success int `json:"success" example:"200"`
|
Success int `json:"success" example:"200"`
|
||||||
Message string `json:"message" example:"ok"`
|
Message string `json:"message" example:"ok"`
|
||||||
Data interface{} `json:"data" example:"返回结果"`
|
Data interface{} `json:"data" example:"返回结果"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//zeritier相关
|
// redis配置文件
|
||||||
type ZeroTierModel struct {
|
|
||||||
UserName string
|
|
||||||
PWD string
|
|
||||||
Token string
|
|
||||||
}
|
|
||||||
|
|
||||||
//redis配置文件
|
|
||||||
type RedisModel struct {
|
type RedisModel struct {
|
||||||
Host string
|
Host string
|
||||||
Password string
|
Password string
|
||||||
@@ -61,9 +62,15 @@ type RedisModel struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SystemConfig struct {
|
type SystemConfig struct {
|
||||||
ConfigStr string `json:"config_str"`
|
|
||||||
WidgetList string `json:"widget_list"`
|
|
||||||
ConfigPath string `json:"config_path"`
|
ConfigPath string `json:"config_path"`
|
||||||
SyncPort string `json:"sync_port"`
|
}
|
||||||
SyncKey string `json:"sync_key"`
|
|
||||||
|
type FileSetting struct {
|
||||||
|
ShareDir []string `json:"share_dir" delim:"|"`
|
||||||
|
DownloadDir string `json:"download_dir"`
|
||||||
|
}
|
||||||
|
type BaseInfo struct {
|
||||||
|
Hash string `json:"i"`
|
||||||
|
Version string `json:"v"`
|
||||||
|
Channel string `json:"c,omitempty"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
|
|
||||||
17
model/system_model/verify_information.go
Normal file
17
model/system_model/verify_information.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.com
|
||||||
|
* @Date: 2022-06-15 11:30:47
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-06-23 18:40:40
|
||||||
|
* @FilePath: /CasaOS/model/system_model/verify_information.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package system_model
|
||||||
|
|
||||||
|
type VerifyInformation struct {
|
||||||
|
RefreshToken string `json:"refresh_token"`
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
ExpiresAt int64 `json:"expires_at"`
|
||||||
|
}
|
||||||
9
model/user.go
Normal file
9
model/user.go
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type UserInfo struct {
|
||||||
|
NickName string `json:"nick_name"`
|
||||||
|
Desc string `json:"desc"`
|
||||||
|
ShareId string `json:"share_id"`
|
||||||
|
Avatar string `json:"avatar"`
|
||||||
|
Version int `json:"version,omitempty"`
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ import "time"
|
|||||||
|
|
||||||
type Version struct {
|
type Version struct {
|
||||||
Id uint `gorm:"column:id;primary_key" json:"id"`
|
Id uint `gorm:"column:id;primary_key" json:"id"`
|
||||||
ChangLog string `json:"chang_log"`
|
ChangeLog string `json:"change_log"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
type ZeroTierUpData struct {
|
|
||||||
Config ZeroTierConfig `json:"config"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ZeroTierConfig struct {
|
|
||||||
Private bool `json:"private"`
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.org
|
||||||
|
* @Date: 2022-05-13 18:15:46
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-08-01 18:32:57
|
||||||
|
* @FilePath: /CasaOS/model/zima.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
package model
|
package model
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
type Path struct {
|
type Path struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"` //File name or document name
|
||||||
Path string `json:"path"`
|
Path string `json:"path"` //Full path to file or folder
|
||||||
IsDir bool `json:"is_dir"`
|
IsDir bool `json:"is_dir"` //Is it a folder
|
||||||
|
Date time.Time `json:"date"`
|
||||||
|
Size int64 `json:"size"` //File Size
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
Label string `json:"label,omitempty"`
|
||||||
|
Write bool `json:"write"`
|
||||||
|
Extensions map[string]interface{} `json:"extensions"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.com
|
||||||
|
* @Date: 2021-09-30 18:18:14
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-08-31 17:04:02
|
||||||
|
* @FilePath: /CasaOS/pkg/config/config.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
package config
|
package config
|
||||||
|
|
||||||
const (
|
const (
|
||||||
USERCONFIGURL = "conf/conf.ini"
|
USERCONFIGURL = "/etc/casaos/casaos.conf"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,3 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.com
|
||||||
|
* @Date: 2022-05-13 18:15:46
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-09-05 11:58:02
|
||||||
|
* @FilePath: /CasaOS/pkg/config/init.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -13,55 +23,74 @@ import (
|
|||||||
"github.com/go-ini/ini"
|
"github.com/go-ini/ini"
|
||||||
)
|
)
|
||||||
|
|
||||||
//系统配置
|
// 系统配置
|
||||||
var SysInfo = &model.SysInfoModel{}
|
var SysInfo = &model.SysInfoModel{}
|
||||||
|
|
||||||
//用户相关
|
// 用户相关
|
||||||
var UserInfo = &model.UserModel{}
|
|
||||||
|
|
||||||
//用户相关
|
|
||||||
var AppInfo = &model.APPModel{}
|
var AppInfo = &model.APPModel{}
|
||||||
|
|
||||||
//redis相关配置
|
var CommonInfo = &model.CommonModel{}
|
||||||
var RedisInfo = &model.RedisModel{}
|
|
||||||
|
|
||||||
//zerotier相关
|
// var RedisInfo = &model.RedisModel{}
|
||||||
var ZeroTierInfo = &model.ZeroTierModel{}
|
|
||||||
|
|
||||||
//server相关
|
// server相关
|
||||||
var ServerInfo = &model.ServerModel{}
|
var ServerInfo = &model.ServerModel{}
|
||||||
|
|
||||||
var SystemConfigInfo = &model.SystemConfig{}
|
var SystemConfigInfo = &model.SystemConfig{}
|
||||||
|
|
||||||
|
var FileSettingInfo = &model.FileSetting{}
|
||||||
|
|
||||||
var Cfg *ini.File
|
var Cfg *ini.File
|
||||||
|
|
||||||
//初始化设置,获取系统的部分信息。
|
// 初始化设置,获取系统的部分信息。
|
||||||
func InitSetup(config string) {
|
func InitSetup(config string) {
|
||||||
|
configDir := USERCONFIGURL
|
||||||
var configDir = USERCONFIGURL
|
|
||||||
if len(config) > 0 {
|
if len(config) > 0 {
|
||||||
configDir = config
|
configDir = config
|
||||||
}
|
}
|
||||||
|
if runtime.GOOS == "darwin" {
|
||||||
|
configDir = "./conf/conf.conf"
|
||||||
|
}
|
||||||
var err error
|
var err error
|
||||||
//读取文件
|
// 读取文件
|
||||||
Cfg, err = ini.Load(configDir)
|
Cfg, err = ini.Load(configDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Fail to read file: %v", err)
|
Cfg, err = ini.Load("/etc/casaos.conf")
|
||||||
os.Exit(1)
|
if err != nil {
|
||||||
|
Cfg, err = ini.Load("/casaOS/server/conf/conf.ini")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Fail to read file: %v", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mapTo("user", UserInfo)
|
|
||||||
mapTo("app", AppInfo)
|
mapTo("app", AppInfo)
|
||||||
mapTo("zerotier", ZeroTierInfo)
|
// mapTo("redis", RedisInfo)
|
||||||
mapTo("redis", RedisInfo)
|
|
||||||
mapTo("server", ServerInfo)
|
mapTo("server", ServerInfo)
|
||||||
mapTo("system", SystemConfigInfo)
|
mapTo("system", SystemConfigInfo)
|
||||||
|
mapTo("file", FileSettingInfo)
|
||||||
|
mapTo("common", CommonInfo)
|
||||||
SystemConfigInfo.ConfigPath = configDir
|
SystemConfigInfo.ConfigPath = configDir
|
||||||
|
if len(AppInfo.DBPath) == 0 {
|
||||||
|
AppInfo.DBPath = "/var/lib/casaos"
|
||||||
|
}
|
||||||
|
if len(AppInfo.LogPath) == 0 {
|
||||||
|
AppInfo.LogPath = "/var/log/casaos/"
|
||||||
|
}
|
||||||
|
if len(AppInfo.ShellPath) == 0 {
|
||||||
|
AppInfo.ShellPath = "/usr/share/casaos/shell"
|
||||||
|
}
|
||||||
|
if len(AppInfo.UserDataPath) == 0 {
|
||||||
|
AppInfo.UserDataPath = "/var/lib/casaos/conf"
|
||||||
|
}
|
||||||
|
if len(CommonInfo.RuntimePath) == 0 {
|
||||||
|
CommonInfo.RuntimePath = "/var/run/casaos"
|
||||||
|
}
|
||||||
|
Cfg.SaveTo(configDir)
|
||||||
// AppInfo.ProjectPath = getCurrentDirectory() //os.Getwd()
|
// AppInfo.ProjectPath = getCurrentDirectory() //os.Getwd()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//映射
|
// 映射
|
||||||
func mapTo(section string, v interface{}) {
|
func mapTo(section string, v interface{}) {
|
||||||
err := Cfg.Section(section).MapTo(v)
|
err := Cfg.Section(section).MapTo(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -78,6 +107,7 @@ func getCurrentAbPathByCaller() string {
|
|||||||
}
|
}
|
||||||
return abPath
|
return abPath
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCurrentDirectory() string {
|
func getCurrentDirectory() string {
|
||||||
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
|
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
package config
|
|
||||||
|
|
||||||
import "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
|
||||||
|
|
||||||
//检查目录是否存在
|
|
||||||
func mkdirDATAAll() {
|
|
||||||
dirArray := [7]string{"/DATA/AppData", "/DATA/Documents", "/DATA/Downloads", "/DATA/Gallery", "/DATA/Media/Movies", "/DATA/Media/TV Shows", "/DATA/Media/Music"}
|
|
||||||
for _, v := range dirArray {
|
|
||||||
file.IsNotExistMkDir(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func UpdateSetup() {
|
|
||||||
mkdirDATAAll()
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
package docker
|
|
||||||
|
|
||||||
const NETWORKNAME = "oasis"
|
|
||||||
@@ -1,403 +0,0 @@
|
|||||||
package docker
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
json2 "encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"regexp"
|
|
||||||
"strconv"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"golang.org/x/crypto/ssh"
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewSshClient(user, password string) (*ssh.Client, error) {
|
|
||||||
|
|
||||||
// connet to ssh
|
|
||||||
// addr = fmt.Sprintf("%s:%d", host, port)
|
|
||||||
|
|
||||||
config := &ssh.ClientConfig{
|
|
||||||
Timeout: time.Second * 5,
|
|
||||||
User: user,
|
|
||||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
|
||||||
//HostKeyCallback: ,
|
|
||||||
//HostKeyCallback: hostKeyCallBackFunc(h.Host),
|
|
||||||
}
|
|
||||||
//if h.Type == "password" {
|
|
||||||
config.Auth = []ssh.AuthMethod{ssh.Password(password)}
|
|
||||||
//} else {
|
|
||||||
// config.Auth = []ssh.AuthMethod{publicKeyAuthFunc(h.Key)}
|
|
||||||
//}
|
|
||||||
addr := fmt.Sprintf("%s:%d", "127.0.0.1", 22)
|
|
||||||
c, err := ssh.Dial("tcp", addr, config)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup ssh shell session
|
|
||||||
// set Session and StdinPipe here,
|
|
||||||
// and the Session.Stdout and Session.Sdterr are also set.
|
|
||||||
func NewSshConn(cols, rows int, sshClient *ssh.Client) (*SshConn, error) {
|
|
||||||
sshSession, err := sshClient.NewSession()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
stdinP, err := sshSession.StdinPipe()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
comboWriter := new(wsBufferWriter)
|
|
||||||
|
|
||||||
sshSession.Stdout = comboWriter
|
|
||||||
sshSession.Stderr = comboWriter
|
|
||||||
|
|
||||||
modes := ssh.TerminalModes{
|
|
||||||
ssh.ECHO: 1, // disable echo
|
|
||||||
ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
|
|
||||||
ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
|
|
||||||
}
|
|
||||||
// Request pseudo terminal
|
|
||||||
if err := sshSession.RequestPty("xterm", rows, cols, modes); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// Start remote shell
|
|
||||||
if err := sshSession.Shell(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &SshConn{StdinPipe: stdinP, ComboOutput: comboWriter, Session: sshSession}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type SshConn struct {
|
|
||||||
// calling Write() to write data into ssh server
|
|
||||||
StdinPipe io.WriteCloser
|
|
||||||
// Write() be called to receive data from ssh server
|
|
||||||
ComboOutput *wsBufferWriter
|
|
||||||
Session *ssh.Session
|
|
||||||
}
|
|
||||||
type wsBufferWriter struct {
|
|
||||||
buffer bytes.Buffer
|
|
||||||
mu sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *wsBufferWriter) Write(p []byte) (int, error) {
|
|
||||||
w.mu.Lock()
|
|
||||||
defer w.mu.Unlock()
|
|
||||||
return w.buffer.Write(p)
|
|
||||||
}
|
|
||||||
func (s *SshConn) Close() {
|
|
||||||
if s.Session != nil {
|
|
||||||
s.Session.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
wsMsgCmd = "cmd"
|
|
||||||
wsMsgResize = "resize"
|
|
||||||
)
|
|
||||||
|
|
||||||
//ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin
|
|
||||||
func ReceiveWsMsgUser(wsConn *websocket.Conn, logBuff *bytes.Buffer) string {
|
|
||||||
//tells other go routine quit
|
|
||||||
username := ""
|
|
||||||
for {
|
|
||||||
|
|
||||||
//read websocket msg
|
|
||||||
_, wsData, err := wsConn.ReadMessage()
|
|
||||||
if err != nil {
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
msgObj := wsMsg{}
|
|
||||||
if err := json2.Unmarshal(wsData, &msgObj); err != nil {
|
|
||||||
msgObj.Type = "cmd"
|
|
||||||
msgObj.Cmd = string(wsData)
|
|
||||||
}
|
|
||||||
//if err := json.Unmarshal(wsData, &msgObj); err != nil {
|
|
||||||
// logrus.WithError(err).WithField("wsData", string(wsData)).Error("unmarshal websocket message failed")
|
|
||||||
//}
|
|
||||||
switch msgObj.Type {
|
|
||||||
case wsMsgCmd:
|
|
||||||
//handle xterm.js stdin
|
|
||||||
//decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
|
|
||||||
decodeBytes := []byte(msgObj.Cmd)
|
|
||||||
if msgObj.Cmd == "\u007f" {
|
|
||||||
if len(username) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
wsConn.WriteMessage(websocket.TextMessage, []byte("\b\x1b[K"))
|
|
||||||
username = username[:len(username)-1]
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if msgObj.Cmd == "\r" {
|
|
||||||
return username
|
|
||||||
}
|
|
||||||
username += msgObj.Cmd
|
|
||||||
|
|
||||||
if err := wsConn.WriteMessage(websocket.TextMessage, decodeBytes); err != nil {
|
|
||||||
logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed")
|
|
||||||
}
|
|
||||||
//write input cmd to log buffer
|
|
||||||
if _, err := logBuff.Write(decodeBytes); err != nil {
|
|
||||||
logrus.WithError(err).Error("write received cmd into log buffer failed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReceiveWsMsgPassword(wsConn *websocket.Conn, logBuff *bytes.Buffer) string {
|
|
||||||
//tells other go routine quit
|
|
||||||
password := ""
|
|
||||||
for {
|
|
||||||
|
|
||||||
//read websocket msg
|
|
||||||
_, wsData, err := wsConn.ReadMessage()
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithError(err).Error("reading webSocket message failed")
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
msgObj := wsMsg{}
|
|
||||||
if err := json2.Unmarshal(wsData, &msgObj); err != nil {
|
|
||||||
msgObj.Type = "cmd"
|
|
||||||
msgObj.Cmd = string(wsData)
|
|
||||||
}
|
|
||||||
//if err := json.Unmarshal(wsData, &msgObj); err != nil {
|
|
||||||
// logrus.WithError(err).WithField("wsData", string(wsData)).Error("unmarshal websocket message failed")
|
|
||||||
//}
|
|
||||||
switch msgObj.Type {
|
|
||||||
case wsMsgCmd:
|
|
||||||
//handle xterm.js stdin
|
|
||||||
//decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
|
|
||||||
if msgObj.Cmd == "\r" {
|
|
||||||
return password
|
|
||||||
}
|
|
||||||
|
|
||||||
if msgObj.Cmd == "\u007f" {
|
|
||||||
if len(password) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
password = password[:len(password)-1]
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
password += msgObj.Cmd
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin
|
|
||||||
func (ssConn *SshConn) ReceiveWsMsg(wsConn *websocket.Conn, logBuff *bytes.Buffer, exitCh chan bool) {
|
|
||||||
//tells other go routine quit
|
|
||||||
defer setQuit(exitCh)
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-exitCh:
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
//read websocket msg
|
|
||||||
_, wsData, err := wsConn.ReadMessage()
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithError(err).Error("reading webSocket message failed")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//unmashal bytes into struct
|
|
||||||
//msgObj := wsMsg{
|
|
||||||
// Type: "cmd",
|
|
||||||
// Cmd: "",
|
|
||||||
// Rows: 50,
|
|
||||||
// Cols: 180,
|
|
||||||
//}
|
|
||||||
msgObj := wsMsg{}
|
|
||||||
if err := json2.Unmarshal(wsData, &msgObj); err != nil {
|
|
||||||
msgObj.Type = "cmd"
|
|
||||||
msgObj.Cmd = string(wsData)
|
|
||||||
}
|
|
||||||
//if err := json.Unmarshal(wsData, &msgObj); err != nil {
|
|
||||||
// logrus.WithError(err).WithField("wsData", string(wsData)).Error("unmarshal websocket message failed")
|
|
||||||
//}
|
|
||||||
switch msgObj.Type {
|
|
||||||
|
|
||||||
case wsMsgResize:
|
|
||||||
//handle xterm.js size change
|
|
||||||
if msgObj.Cols > 0 && msgObj.Rows > 0 {
|
|
||||||
if err := ssConn.Session.WindowChange(msgObj.Rows, msgObj.Cols); err != nil {
|
|
||||||
logrus.WithError(err).Error("ssh pty change windows size failed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case wsMsgCmd:
|
|
||||||
//handle xterm.js stdin
|
|
||||||
//decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
|
|
||||||
decodeBytes := []byte(msgObj.Cmd)
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithError(err).Error("websock cmd string base64 decoding failed")
|
|
||||||
}
|
|
||||||
if _, err := ssConn.StdinPipe.Write(decodeBytes); err != nil {
|
|
||||||
logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed")
|
|
||||||
}
|
|
||||||
//write input cmd to log buffer
|
|
||||||
if _, err := logBuff.Write(decodeBytes); err != nil {
|
|
||||||
logrus.WithError(err).Error("write received cmd into log buffer failed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ssConn *SshConn) SendComboOutput(wsConn *websocket.Conn, exitCh chan bool) {
|
|
||||||
//tells other go routine quit
|
|
||||||
//defer setQuit(exitCh)
|
|
||||||
|
|
||||||
//every 120ms write combine output bytes into websocket response
|
|
||||||
tick := time.NewTicker(time.Millisecond * time.Duration(120))
|
|
||||||
//for range time.Tick(120 * time.Millisecond){}
|
|
||||||
defer tick.Stop()
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-tick.C:
|
|
||||||
//write combine output bytes into websocket response
|
|
||||||
if err := flushComboOutput(ssConn.ComboOutput, wsConn); err != nil {
|
|
||||||
logrus.WithError(err).Error("ssh sending combo output to webSocket failed")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
case <-exitCh:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func flushComboOutput(w *wsBufferWriter, wsConn *websocket.Conn) error {
|
|
||||||
if w.buffer.Len() != 0 {
|
|
||||||
err := wsConn.WriteMessage(websocket.TextMessage, w.buffer.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
w.buffer.Reset()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin
|
|
||||||
func (ssConn *SshConn) Login(wsConn *websocket.Conn, logBuff *bytes.Buffer, exitCh chan bool) {
|
|
||||||
//tells other go routine quit
|
|
||||||
defer setQuit(exitCh)
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-exitCh:
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
//read websocket msg
|
|
||||||
_, wsData, err := wsConn.ReadMessage()
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithError(err).Error("reading webSocket message failed")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//unmashal bytes into struct
|
|
||||||
//msgObj := wsMsg{
|
|
||||||
// Type: "cmd",
|
|
||||||
// Cmd: "",
|
|
||||||
// Rows: 50,
|
|
||||||
// Cols: 180,
|
|
||||||
//}
|
|
||||||
msgObj := wsMsg{}
|
|
||||||
if err := json2.Unmarshal(wsData, &msgObj); err != nil {
|
|
||||||
msgObj.Type = "cmd"
|
|
||||||
msgObj.Cmd = string(wsData)
|
|
||||||
}
|
|
||||||
//if err := json.Unmarshal(wsData, &msgObj); err != nil {
|
|
||||||
// logrus.WithError(err).WithField("wsData", string(wsData)).Error("unmarshal websocket message failed")
|
|
||||||
//}
|
|
||||||
switch msgObj.Type {
|
|
||||||
|
|
||||||
case wsMsgResize:
|
|
||||||
//handle xterm.js size change
|
|
||||||
if msgObj.Cols > 0 && msgObj.Rows > 0 {
|
|
||||||
if err := ssConn.Session.WindowChange(msgObj.Rows, msgObj.Cols); err != nil {
|
|
||||||
logrus.WithError(err).Error("ssh pty change windows size failed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case wsMsgCmd:
|
|
||||||
//handle xterm.js stdin
|
|
||||||
//decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
|
|
||||||
decodeBytes := []byte(msgObj.Cmd)
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithError(err).Error("websock cmd string base64 decoding failed")
|
|
||||||
}
|
|
||||||
if _, err := ssConn.StdinPipe.Write(decodeBytes); err != nil {
|
|
||||||
logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed")
|
|
||||||
}
|
|
||||||
//write input cmd to log buffer
|
|
||||||
if _, err := logBuff.Write(decodeBytes); err != nil {
|
|
||||||
logrus.WithError(err).Error("write received cmd into log buffer failed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func (ssConn *SshConn) SessionWait(quitChan chan bool) {
|
|
||||||
if err := ssConn.Session.Wait(); err != nil {
|
|
||||||
logrus.WithError(err).Error("ssh session wait failed")
|
|
||||||
setQuit(quitChan)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func setQuit(ch chan bool) {
|
|
||||||
ch <- true
|
|
||||||
}
|
|
||||||
|
|
||||||
type wsMsg struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
Cmd string `json:"cmd"`
|
|
||||||
Cols int `json:"cols"`
|
|
||||||
Rows int `json:"rows"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将终端的输出转发到前端
|
|
||||||
func WsWriterCopy(reader io.Reader, writer *websocket.Conn) {
|
|
||||||
buf := make([]byte, 8192)
|
|
||||||
reg1 := regexp.MustCompile(`stty rows \d+ && stty cols \d+ `)
|
|
||||||
for {
|
|
||||||
nr, err := reader.Read(buf)
|
|
||||||
if nr > 0 {
|
|
||||||
result1 := reg1.FindIndex(buf[0:nr])
|
|
||||||
if len(result1) > 0 {
|
|
||||||
fmt.Println(result1)
|
|
||||||
} else {
|
|
||||||
err := writer.WriteMessage(websocket.BinaryMessage, buf[0:nr])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将前端的输入转发到终端
|
|
||||||
func WsReaderCopy(reader *websocket.Conn, writer io.Writer) {
|
|
||||||
for {
|
|
||||||
messageType, p, err := reader.ReadMessage()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if messageType == websocket.TextMessage {
|
|
||||||
msgObj := wsMsg{}
|
|
||||||
if err = json2.Unmarshal(p, &msgObj); err != nil {
|
|
||||||
writer.Write(p)
|
|
||||||
} else if msgObj.Type == wsMsgResize {
|
|
||||||
writer.Write([]byte("stty rows " + strconv.Itoa(msgObj.Rows) + " && stty cols " + strconv.Itoa(msgObj.Cols) + " \r"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package docker
|
|
||||||
|
|
||||||
import "strings"
|
|
||||||
|
|
||||||
func GetDir(id, envName string) string {
|
|
||||||
var path string
|
|
||||||
|
|
||||||
if len(id) == 0 {
|
|
||||||
id = "$AppID"
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case strings.Contains(strings.ToLower(envName), "config") || strings.Contains(strings.ToLower(envName), "photoprism/storage") || strings.Contains(strings.ToLower(envName), "config"):
|
|
||||||
path = "/DATA/AppData/" + id + "/"
|
|
||||||
case strings.Contains(strings.ToLower(envName), "media"):
|
|
||||||
path = "/DATA/Media/"
|
|
||||||
case strings.Contains(strings.ToLower(envName), "movie"):
|
|
||||||
path = "/DATA/Media/Movies/"
|
|
||||||
case strings.Contains(strings.ToLower(envName), "music"):
|
|
||||||
path = "/DATA/Media/Music/"
|
|
||||||
case strings.Contains(strings.ToLower(envName), "photoprism/originals"):
|
|
||||||
path = "/DATA/Gallery"
|
|
||||||
case strings.Contains(strings.ToLower(envName), "download"):
|
|
||||||
path = "/DATA/Downloads/"
|
|
||||||
case strings.Contains(strings.ToLower(envName), "photo") || strings.Contains(strings.ToLower(envName), "pictures"):
|
|
||||||
path = "/DATA/Downloads/"
|
|
||||||
case strings.ToLower(envName) == "/srv":
|
|
||||||
path = "/DATA/"
|
|
||||||
default:
|
|
||||||
//path = "/media"
|
|
||||||
}
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package docker
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGetDir(t *testing.T) {
|
|
||||||
fmt.Println(GetDir("", "config"))
|
|
||||||
}
|
|
||||||
@@ -6,11 +6,10 @@ import (
|
|||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
func GetGithubClient() *github.Client {
|
func GetGithubClient() *github.Client {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
ts := oauth2.StaticTokenSource(
|
ts := oauth2.StaticTokenSource(
|
||||||
&oauth2.Token{AccessToken: "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"},
|
&oauth2.Token{AccessToken: ""},
|
||||||
)
|
)
|
||||||
tc := oauth2.NewClient(ctx, ts)
|
tc := oauth2.NewClient(ctx, ts)
|
||||||
client := github.NewClient(tc)
|
client := github.NewClient(tc)
|
||||||
|
|||||||
75
pkg/samba/smaba.go
Normal file
75
pkg/samba/smaba.go
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.org
|
||||||
|
* @Date: 2022-07-27 10:35:29
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-08-01 13:56:44
|
||||||
|
* @FilePath: /CasaOS/pkg/samba/smaba.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package samba
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/hirochachacha/go-smb2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ConnectSambaService(host, port, username, password, directory string) error {
|
||||||
|
conn, err := net.Dial("tcp", host+":"+port)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
d := &smb2.Dialer{
|
||||||
|
Initiator: &smb2.NTLMInitiator{
|
||||||
|
User: username,
|
||||||
|
Password: password,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
s, err := d.Dial(conn)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer s.Logoff()
|
||||||
|
names, err := s.ListSharenames()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, name := range names {
|
||||||
|
if name == directory {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errors.New("directory not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
//get share name list
|
||||||
|
func GetSambaSharesList(host, port, username, password string) ([]string, error) {
|
||||||
|
conn, err := net.Dial("tcp", host+":"+port)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
d := &smb2.Dialer{
|
||||||
|
Initiator: &smb2.NTLMInitiator{
|
||||||
|
User: username,
|
||||||
|
Password: password,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
s, err := d.Dial(conn)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer s.Logoff()
|
||||||
|
names, err := s.ListSharenames()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return names, err
|
||||||
|
}
|
||||||
@@ -1,38 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.com
|
||||||
|
* @Date: 2022-05-13 18:15:46
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-08-31 13:39:24
|
||||||
|
* @FilePath: /CasaOS/pkg/sqlite/db.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
package sqlite
|
package sqlite
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"time"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
"gorm.io/driver/sqlite"
|
"github.com/glebarez/sqlite"
|
||||||
|
"go.uber.org/zap"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var gdb *gorm.DB
|
var gdb *gorm.DB
|
||||||
|
|
||||||
func GetDb(projectPath string) *gorm.DB {
|
func GetDb(dbPath string) *gorm.DB {
|
||||||
if gdb != nil {
|
if gdb != nil {
|
||||||
return gdb
|
return gdb
|
||||||
}
|
}
|
||||||
// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
|
// Refer https://github.com/go-sql-driver/mysql#dsn-data-source-name
|
||||||
//dsn := fmt.Sprintf("%v:%v@tcp(%v:%v)/%v?charset=utf8mb4&parseTime=True&loc=Local", m.User, m.PWD, m.IP, m.Port, m.DBName)
|
// dsn := fmt.Sprintf("%v:%v@tcp(%v:%v)/%v?charset=utf8mb4&parseTime=True&loc=Local", m.User, m.PWD, m.IP, m.Port, m.DBName)
|
||||||
//db, err := gorm.Open(mysql2.Open(dsn), &gorm.Config{})
|
// db, err := gorm.Open(mysql2.Open(dsn), &gorm.Config{})
|
||||||
file.IsNotExistMkDir(projectPath + "/db/")
|
file.IsNotExistMkDir(dbPath)
|
||||||
db, err := gorm.Open(sqlite.Open(projectPath+"/db/casaOS.db"), &gorm.Config{})
|
db, err := gorm.Open(sqlite.Open(dbPath+"/casaOS.db"), &gorm.Config{})
|
||||||
c, _ := db.DB()
|
c, _ := db.DB()
|
||||||
c.SetMaxIdleConns(10)
|
c.SetMaxIdleConns(10)
|
||||||
c.SetMaxOpenConns(100)
|
c.SetMaxOpenConns(1)
|
||||||
c.SetConnMaxIdleTime(time.Second * 1000)
|
c.SetConnMaxIdleTime(time.Second * 1000)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("连接数据失败!")
|
logger.Error("sqlite connect error", zap.Any("db connect error", err))
|
||||||
panic("数据库连接失败")
|
panic("sqlite connect error")
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
gdb = db
|
gdb = db
|
||||||
err = db.AutoMigrate(&model2.TaskDBModel{}, &model2.AppNotify{}, &model2.AppListDBModel{})
|
|
||||||
|
err = db.AutoMigrate(&model2.AppNotify{}, model2.SharesDBModel{}, model2.ConnectionsDBModel{})
|
||||||
|
db.Exec("DROP TABLE IF EXISTS o_application")
|
||||||
|
db.Exec("DROP TABLE IF EXISTS o_friend")
|
||||||
|
db.Exec("DROP TABLE IF EXISTS o_person_download")
|
||||||
|
db.Exec("DROP TABLE IF EXISTS o_person_down_record")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("检查和创建数据库出错", err)
|
logger.Error("check or create db error", zap.Any("error", err))
|
||||||
}
|
}
|
||||||
return db
|
return db
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,89 +0,0 @@
|
|||||||
package upnp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/xml"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetCtrlUrl(host,device string) string {
|
|
||||||
request := ctrlUrlRequest(host, device)
|
|
||||||
response, _ := http.DefaultClient.Do(request)
|
|
||||||
resultBody, _ := ioutil.ReadAll(response.Body)
|
|
||||||
defer response.Body.Close()
|
|
||||||
if response.StatusCode == 200 {
|
|
||||||
return resolve(string(resultBody))
|
|
||||||
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func ctrlUrlRequest(host string, deviceDescUrl string) *http.Request {
|
|
||||||
//请求头
|
|
||||||
header := http.Header{}
|
|
||||||
header.Set("Accept", "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2")
|
|
||||||
header.Set("User-Agent", "preston")
|
|
||||||
header.Set("Host", host)
|
|
||||||
header.Set("Connection", "keep-alive")
|
|
||||||
request, _ := http.NewRequest("GET", "http://"+host+deviceDescUrl, nil)
|
|
||||||
request.Header = header
|
|
||||||
return request
|
|
||||||
}
|
|
||||||
|
|
||||||
func resolve(resultStr string) string {
|
|
||||||
inputReader := strings.NewReader(resultStr)
|
|
||||||
|
|
||||||
// 从文件读取,如可以如下:
|
|
||||||
// content, err := ioutil.ReadFile("studygolang.xml")
|
|
||||||
// decoder := xml.NewDecoder(bytes.NewBuffer(content))
|
|
||||||
|
|
||||||
lastLabel := ""
|
|
||||||
|
|
||||||
ISUpnpServer := false
|
|
||||||
|
|
||||||
IScontrolURL := false
|
|
||||||
var controlURL string //`controlURL`
|
|
||||||
// var eventSubURL string //`eventSubURL`
|
|
||||||
// var SCPDURL string //`SCPDURL`
|
|
||||||
|
|
||||||
decoder := xml.NewDecoder(inputReader)
|
|
||||||
for t, err := decoder.Token(); err == nil && !IScontrolURL; t, err = decoder.Token() {
|
|
||||||
switch token := t.(type) {
|
|
||||||
// 处理元素开始(标签)
|
|
||||||
case xml.StartElement:
|
|
||||||
if ISUpnpServer {
|
|
||||||
name := token.Name.Local
|
|
||||||
lastLabel = name
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理元素结束(标签)
|
|
||||||
case xml.EndElement:
|
|
||||||
// log.Println("结束标记:", token.Name.Local)
|
|
||||||
// 处理字符数据(这里就是元素的文本)
|
|
||||||
case xml.CharData:
|
|
||||||
//得到url后其他标记就不处理了
|
|
||||||
content := string([]byte(token))
|
|
||||||
//找到提供端口映射的服务
|
|
||||||
if content == "urn:schemas-upnp-org:service:WANIPConnection:1" {
|
|
||||||
ISUpnpServer = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if ISUpnpServer {
|
|
||||||
switch lastLabel {
|
|
||||||
case "controlURL":
|
|
||||||
controlURL = content
|
|
||||||
IScontrolURL = true
|
|
||||||
case "eventSubURL":
|
|
||||||
// eventSubURL = content
|
|
||||||
case "SCPDURL":
|
|
||||||
// SCPDURL = content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return controlURL
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
package upnp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
ip_helper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGetCtrlUrl(t *testing.T) {
|
|
||||||
upnp, err := Gateway()
|
|
||||||
if err == nil {
|
|
||||||
upnp.CtrlUrl = GetCtrlUrl(upnp.GatewayHost, upnp.DeviceDescUrl)
|
|
||||||
upnp.LocalHost = ip_helper2.GetLoclIp()
|
|
||||||
upnp.AddPortMapping(8090, 8090, "TCP")
|
|
||||||
//upnp.DelPortMapping(9999, "TCP")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
package upnp
|
|
||||||
|
|
||||||
import (
|
|
||||||
ip_helper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"net"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Gateway() (*Upnp, error) {
|
|
||||||
result, error := send()
|
|
||||||
if result == "" || error != nil {
|
|
||||||
return nil, error
|
|
||||||
}
|
|
||||||
upnp := resolvesss(result)
|
|
||||||
return upnp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func send() (string, error) {
|
|
||||||
var str = "M-SEARCH * HTTP/1.1\r\n" +
|
|
||||||
"HOST: 239.255.255.250:1900\r\n" +
|
|
||||||
"ST: urn:schemas-upnp-org:service:WANIPConnection:1\r\n" +
|
|
||||||
"MAN: \"ssdp:discover\"\r\n" + "MX: 3\r\n\r\n"
|
|
||||||
var conn *net.UDPConn
|
|
||||||
remotAddr, err := net.ResolveUDPAddr("udp", "239.255.255.250:1900")
|
|
||||||
if err != nil {
|
|
||||||
return "", errors.New("组播地址格式不正确")
|
|
||||||
}
|
|
||||||
locaAddr, err := net.ResolveUDPAddr("udp", ip_helper2.GetLoclIp()+":")
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return "", errors.New("本地ip地址格式不正确")
|
|
||||||
}
|
|
||||||
conn, err = net.ListenUDP("udp", locaAddr)
|
|
||||||
defer conn.Close()
|
|
||||||
if err != nil {
|
|
||||||
return "", errors.New("监听udp出错")
|
|
||||||
}
|
|
||||||
_, err = conn.WriteToUDP([]byte(str), remotAddr)
|
|
||||||
if err != nil {
|
|
||||||
return "", errors.New("发送msg到组播地址出错")
|
|
||||||
}
|
|
||||||
buf := make([]byte, 1024)
|
|
||||||
n, _, err := conn.ReadFromUDP(buf)
|
|
||||||
if err != nil {
|
|
||||||
return "", errors.New("从组播地址接搜消息出错")
|
|
||||||
}
|
|
||||||
result := string(buf[:n])
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func resolvesss(result string) *Upnp {
|
|
||||||
var upnp = &Upnp{}
|
|
||||||
lines := strings.Split(result, "\r\n")
|
|
||||||
for _, line := range lines {
|
|
||||||
//按照第一个冒号分为两个字符串
|
|
||||||
nameValues := strings.SplitAfterN(line, ":", 2)
|
|
||||||
if len(nameValues) < 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
switch strings.ToUpper(strings.Trim(strings.Split(nameValues[0], ":")[0], " ")) {
|
|
||||||
case "ST":
|
|
||||||
//fmt.Println(nameValues[1])
|
|
||||||
case "CACHE-CONTROL":
|
|
||||||
//fmt.Println(nameValues[1])
|
|
||||||
case "LOCATION":
|
|
||||||
urls := strings.Split(strings.Split(nameValues[1], "//")[1], "/")
|
|
||||||
upnp.GatewayHost = (urls[0])
|
|
||||||
upnp.DeviceDescUrl = ("/" + urls[1])
|
|
||||||
case "SERVER":
|
|
||||||
upnp.GatewayName = (nameValues[1])
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return upnp
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
package upnp
|
|
||||||
|
|
||||||
import "testing"
|
|
||||||
|
|
||||||
func TestGateway(t *testing.T) {
|
|
||||||
|
|
||||||
Gateway()
|
|
||||||
}
|
|
||||||
@@ -1,163 +0,0 @@
|
|||||||
package upnp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
//
|
|
||||||
////添加一个端口映射
|
|
||||||
func (n *Upnp)AddPortMapping(localPort, remotePort int, protocol string) (err error) {
|
|
||||||
defer func(err error) {
|
|
||||||
if errTemp := recover(); errTemp != nil {
|
|
||||||
//log.Println("upnp模块报错了", errTemp)
|
|
||||||
err = errTemp.(error)
|
|
||||||
}
|
|
||||||
}(err)
|
|
||||||
if issuccess := addSend(localPort, remotePort, protocol,n.GatewayHost, n.CtrlUrl,n.LocalHost); issuccess {
|
|
||||||
return nil
|
|
||||||
} else {
|
|
||||||
return errors.New("添加一个端口映射失败")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func addSend(localPort, remotePort int, protocol, host, ctrUrl,localHost string) bool {
|
|
||||||
request := addRequest(localPort, remotePort, protocol, host, ctrUrl,localHost)
|
|
||||||
response, _ := http.DefaultClient.Do(request)
|
|
||||||
defer response.Body.Close()
|
|
||||||
//resultBody, _ := ioutil.ReadAll(response.Body)
|
|
||||||
//fmt.Println(string(resultBody))
|
|
||||||
if response.StatusCode == 200 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type Node struct {
|
|
||||||
Name string
|
|
||||||
Content string
|
|
||||||
Attr map[string]string
|
|
||||||
Child []Node
|
|
||||||
}
|
|
||||||
|
|
||||||
func addRequest(localPort, remotePort int, protocol string, gatewayHost, ctlUrl,localHost string) *http.Request {
|
|
||||||
//请求头
|
|
||||||
header := http.Header{}
|
|
||||||
header.Set("Accept", "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2")
|
|
||||||
header.Set("SOAPAction", `"urn:schemas-upnp-org:service:WANIPConnection:1#AddPortMapping"`)
|
|
||||||
header.Set("Content-Type", "text/xml")
|
|
||||||
header.Set("Connection", "Close")
|
|
||||||
header.Set("Content-Length", "")
|
|
||||||
//请求体
|
|
||||||
body := Node{Name: "SOAP-ENV:Envelope",
|
|
||||||
Attr: map[string]string{"xmlns:SOAP-ENV": `"http://schemas.xmlsoap.org/soap/envelope/"`,
|
|
||||||
"SOAP-ENV:encodingStyle": `"http://schemas.xmlsoap.org/soap/encoding/"`}}
|
|
||||||
childOne := Node{Name: `SOAP-ENV:Body`}
|
|
||||||
childTwo := Node{Name: `m:AddPortMapping`,
|
|
||||||
Attr: map[string]string{"xmlns:m": `"urn:schemas-upnp-org:service:WANIPConnection:1"`}}
|
|
||||||
|
|
||||||
childList1 := Node{Name: "NewExternalPort", Content: strconv.Itoa(remotePort)}
|
|
||||||
childList2 := Node{Name: "NewInternalPort", Content: strconv.Itoa(localPort)}
|
|
||||||
childList3 := Node{Name: "NewProtocol", Content: protocol}
|
|
||||||
childList4 := Node{Name: "NewEnabled", Content: "1"}
|
|
||||||
childList5 := Node{Name: "NewInternalClient", Content: localHost}
|
|
||||||
childList6 := Node{Name: "NewLeaseDuration", Content: "0"}
|
|
||||||
childList7 := Node{Name: "NewPortMappingDescription", Content: "Oasis"}
|
|
||||||
childList8 := Node{Name: "NewRemoteHost"}
|
|
||||||
childTwo.AddChild(childList1)
|
|
||||||
childTwo.AddChild(childList2)
|
|
||||||
childTwo.AddChild(childList3)
|
|
||||||
childTwo.AddChild(childList4)
|
|
||||||
childTwo.AddChild(childList5)
|
|
||||||
childTwo.AddChild(childList6)
|
|
||||||
childTwo.AddChild(childList7)
|
|
||||||
childTwo.AddChild(childList8)
|
|
||||||
|
|
||||||
childOne.AddChild(childTwo)
|
|
||||||
body.AddChild(childOne)
|
|
||||||
bodyStr := body.BuildXML()
|
|
||||||
//请求
|
|
||||||
request, _ := http.NewRequest("POST", "http://"+gatewayHost+ctlUrl,
|
|
||||||
strings.NewReader(bodyStr))
|
|
||||||
request.Header = header
|
|
||||||
request.Header.Set("Content-Length", strconv.Itoa(len([]byte(bodyStr))))
|
|
||||||
return request
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *Node) AddChild(node Node) {
|
|
||||||
n.Child = append(n.Child, node)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *Node) BuildXML() string {
|
|
||||||
buf := bytes.NewBufferString("<")
|
|
||||||
buf.WriteString(n.Name)
|
|
||||||
for key, value := range n.Attr {
|
|
||||||
buf.WriteString(" ")
|
|
||||||
buf.WriteString(key + "=" + value)
|
|
||||||
}
|
|
||||||
buf.WriteString(">" + n.Content)
|
|
||||||
|
|
||||||
for _, node := range n.Child {
|
|
||||||
buf.WriteString(node.BuildXML())
|
|
||||||
}
|
|
||||||
buf.WriteString("</" + n.Name + ">")
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *Upnp)DelPortMapping(remotePort int, protocol string) bool {
|
|
||||||
issuccess := delSendSend(remotePort, protocol,n.GatewayHost,n.CtrlUrl)
|
|
||||||
if issuccess {
|
|
||||||
//this.MappingPort.delMapping(remotePort, protocol)
|
|
||||||
//fmt.Println("删除了一个端口映射: remote:", remotePort)
|
|
||||||
}
|
|
||||||
return issuccess
|
|
||||||
}
|
|
||||||
|
|
||||||
func delSendSend(remotePort int, protocol,host,ctlUrl string) bool {
|
|
||||||
delrequest := delbuildRequest(remotePort, protocol,host,ctlUrl)
|
|
||||||
response, _ := http.DefaultClient.Do(delrequest)
|
|
||||||
//resultBody, _ := ioutil.ReadAll(response.Body)
|
|
||||||
defer response.Body.Close()
|
|
||||||
if response.StatusCode == 200 {
|
|
||||||
// log.Println(string(resultBody))
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
func delbuildRequest(remotePort int, protocol,host,ctlUrl string) *http.Request {
|
|
||||||
//请求头
|
|
||||||
header := http.Header{}
|
|
||||||
header.Set("Accept", "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2")
|
|
||||||
header.Set("SOAPAction", `"urn:schemas-upnp-org:service:WANIPConnection:1#DeletePortMapping"`)
|
|
||||||
header.Set("Content-Type", "text/xml")
|
|
||||||
header.Set("Connection", "Close")
|
|
||||||
header.Set("Content-Length", "")
|
|
||||||
//请求体
|
|
||||||
body := Node{Name: "SOAP-ENV:Envelope",
|
|
||||||
Attr: map[string]string{"xmlns:SOAP-ENV": `"http://schemas.xmlsoap.org/soap/envelope/"`,
|
|
||||||
"SOAP-ENV:encodingStyle": `"http://schemas.xmlsoap.org/soap/encoding/"`}}
|
|
||||||
childOne := Node{Name: `SOAP-ENV:Body`}
|
|
||||||
childTwo := Node{Name: `m:DeletePortMapping`,
|
|
||||||
Attr: map[string]string{"xmlns:m": `"urn:schemas-upnp-org:service:WANIPConnection:1"`}}
|
|
||||||
childList1 := Node{Name: "NewExternalPort", Content: strconv.Itoa(remotePort)}
|
|
||||||
childList2 := Node{Name: "NewProtocol", Content: protocol}
|
|
||||||
childList3 := Node{Name: "NewRemoteHost"}
|
|
||||||
childTwo.AddChild(childList1)
|
|
||||||
childTwo.AddChild(childList2)
|
|
||||||
childTwo.AddChild(childList3)
|
|
||||||
childOne.AddChild(childTwo)
|
|
||||||
body.AddChild(childOne)
|
|
||||||
bodyStr := body.BuildXML()
|
|
||||||
|
|
||||||
//请求
|
|
||||||
request, _ := http.NewRequest("POST", "http://"+host+ctlUrl,
|
|
||||||
strings.NewReader(bodyStr))
|
|
||||||
request.Header = header
|
|
||||||
request.Header.Set("Content-Length", strconv.Itoa(len([]byte(bodyStr))))
|
|
||||||
return request
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
package upnp
|
|
||||||
|
|
||||||
import "testing"
|
|
||||||
|
|
||||||
func TestAddPortMapping(t *testing.T) {
|
|
||||||
//AddPortMapping(6666,6666,"TCP","192.168.2.1:5000",)
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
package upnp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/prestonTao/upnp"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Upnp struct {
|
|
||||||
LocalHost string `json:"local_host"`
|
|
||||||
GatewayName string `json:"gateway_name"` //网关名称
|
|
||||||
GatewayHost string `json:"gateway_host"` //网关ip和端口
|
|
||||||
DeviceDescUrl string `json:"device_desc_url"` //设备描述url
|
|
||||||
CtrlUrl string `json:"ctrl_url"` //控制请求url
|
|
||||||
}
|
|
||||||
|
|
||||||
func Testaaa() {
|
|
||||||
upnpMan := new(upnp.Upnp)
|
|
||||||
err := upnpMan.SearchGateway()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
} else {
|
|
||||||
fmt.Println("local ip address: ", upnpMan.LocalHost)
|
|
||||||
fmt.Println("gateway ip address: ", upnpMan.Gateway.Host)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
package upnp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestTestaaa(t *testing.T) {
|
|
||||||
(Testaaa())
|
|
||||||
}
|
|
||||||
@@ -2,9 +2,14 @@ package command
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func OnlyExec(cmdStr string) {
|
func OnlyExec(cmdStr string) {
|
||||||
@@ -33,8 +38,8 @@ func ExecResultStrArray(cmdStr string) []string {
|
|||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
//str, err := ioutil.ReadAll(stdout)
|
// str, err := ioutil.ReadAll(stdout)
|
||||||
var networklist = []string{}
|
networklist := []string{}
|
||||||
outputBuf := bufio.NewReader(stdout)
|
outputBuf := bufio.NewReader(stdout)
|
||||||
for {
|
for {
|
||||||
output, _, err := outputBuf.ReadLine()
|
output, _, err := outputBuf.ReadLine()
|
||||||
@@ -52,6 +57,8 @@ func ExecResultStrArray(cmdStr string) []string {
|
|||||||
|
|
||||||
func ExecResultStr(cmdStr string) string {
|
func ExecResultStr(cmdStr string) string {
|
||||||
cmd := exec.Command("/bin/bash", "-c", cmdStr)
|
cmd := exec.Command("/bin/bash", "-c", cmdStr)
|
||||||
|
println(cmd.String())
|
||||||
|
|
||||||
stdout, err := cmd.StdoutPipe()
|
stdout, err := cmd.StdoutPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
@@ -71,20 +78,89 @@ func ExecResultStr(cmdStr string) string {
|
|||||||
return string(str)
|
return string(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
//执行 lsblk 命令
|
// 执行 lsblk 命令
|
||||||
func ExecLSBLK() []byte {
|
func ExecLSBLK() []byte {
|
||||||
output, err := exec.Command("lsblk", "-O", "-J", "-b").Output()
|
output, err := exec.Command("lsblk", "-O", "-J", "-b").Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Println("lsblk", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
//执行 lsblk 命令
|
// 执行 lsblk 命令
|
||||||
func ExecLSBLKByPath(path string) []byte {
|
func ExecLSBLKByPath(path string) []byte {
|
||||||
output, err := exec.Command("lsblk", path, "-O", "-J", "-b").Output()
|
output, err := exec.Command("lsblk", path, "-O", "-J", "-b").Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Println("lsblk", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// exec smart
|
||||||
|
func ExecSmartCTLByPath(path string) []byte {
|
||||||
|
timeout := 3
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
output, err := exec.CommandContext(ctx, "smartctl", "-a", path, "-j").Output()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("smartctl", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExecEnabledSMART(path string) {
|
||||||
|
exec.Command("smartctl", "-s on", path).Output()
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExecuteScripts(scriptDirectory string) {
|
||||||
|
if _, err := os.Stat(scriptDirectory); os.IsNotExist(err) {
|
||||||
|
fmt.Printf("No post-start scripts at %s\n", scriptDirectory)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
files, err := os.ReadDir(scriptDirectory)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Failed to read from script directory %s: %s\n", scriptDirectory, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, file := range files {
|
||||||
|
if file.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
scriptFilepath := filepath.Join(scriptDirectory, file.Name())
|
||||||
|
|
||||||
|
f, err := os.Open(scriptFilepath)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Failed to open script file %s: %s\n", scriptFilepath, err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(f)
|
||||||
|
scanner.Scan()
|
||||||
|
shebang := scanner.Text()
|
||||||
|
|
||||||
|
interpreter := "/bin/sh"
|
||||||
|
if strings.HasPrefix(shebang, "#!") {
|
||||||
|
interpreter = shebang[2:]
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := exec.Command(interpreter, scriptFilepath)
|
||||||
|
|
||||||
|
fmt.Printf("Executing post-start script %s using %s\n", scriptFilepath, interpreter)
|
||||||
|
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
|
||||||
|
err = cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Failed to execute post-start script %s: %s\n", scriptFilepath, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println("Finished executing post-start scripts.")
|
||||||
|
}
|
||||||
|
|||||||
29
pkg/utils/command/command_helper_test.go
Normal file
29
pkg/utils/command/command_helper_test.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"gotest.tools/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestExecuteScripts(t *testing.T) {
|
||||||
|
// make a temp directory
|
||||||
|
tmpDir, err := os.MkdirTemp("", "casaos-test-*")
|
||||||
|
assert.NilError(t, err)
|
||||||
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
|
ExecuteScripts(tmpDir)
|
||||||
|
|
||||||
|
// create a sample script under tmpDir
|
||||||
|
script := tmpDir + "/test.sh"
|
||||||
|
f, err := os.Create(script)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
// write a sample script
|
||||||
|
_, err = f.WriteString("#!/bin/bash\necho 123")
|
||||||
|
assert.NilError(t, err)
|
||||||
|
|
||||||
|
ExecuteScripts(tmpDir)
|
||||||
|
}
|
||||||
125
pkg/utils/common_err/e.go
Normal file
125
pkg/utils/common_err/e.go
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
package common_err
|
||||||
|
|
||||||
|
const (
|
||||||
|
SUCCESS = 200
|
||||||
|
SERVICE_ERROR = 500
|
||||||
|
CLIENT_ERROR = 400
|
||||||
|
ERROR_AUTH_TOKEN = 401
|
||||||
|
|
||||||
|
INVALID_PARAMS = 4000
|
||||||
|
//user
|
||||||
|
PWD_INVALID = 10001
|
||||||
|
PWD_IS_EMPTY = 10002
|
||||||
|
PWD_INVALID_OLD = 10003
|
||||||
|
ACCOUNT_LOCK = 10004
|
||||||
|
PWD_IS_TOO_SIMPLE = 10005
|
||||||
|
USER_NOT_EXIST = 10006
|
||||||
|
USER_EXIST = 10007
|
||||||
|
KEY_NOT_EXIST = 10008
|
||||||
|
NOT_IMAGE = 10009
|
||||||
|
IMAGE_TOO_LARGE = 10010
|
||||||
|
INSUFFICIENT_PERMISSIONS = 10011
|
||||||
|
|
||||||
|
//system
|
||||||
|
DIR_ALREADY_EXISTS = 20001
|
||||||
|
FILE_ALREADY_EXISTS = 20002
|
||||||
|
FILE_OR_DIR_EXISTS = 20003
|
||||||
|
PORT_IS_OCCUPIED = 20004
|
||||||
|
COMMAND_ERROR_INVALID_OPERATION = 20005
|
||||||
|
VERIFICATION_FAILURE = 20006
|
||||||
|
Record_NOT_EXIST = 20007
|
||||||
|
Record_ALREADY_EXIST = 20008
|
||||||
|
SERVICE_NOT_RUNNING = 20009
|
||||||
|
CHARACTER_LIMIT = 20010
|
||||||
|
|
||||||
|
//disk
|
||||||
|
NAME_NOT_AVAILABLE = 40001
|
||||||
|
DISK_NEEDS_FORMAT = 40002
|
||||||
|
DISK_BUSYING = 40003
|
||||||
|
REMOVE_MOUNT_POINT_ERROR = 40004
|
||||||
|
FORMAT_ERROR = 40005
|
||||||
|
|
||||||
|
//app
|
||||||
|
UNINSTALL_APP_ERROR = 50001
|
||||||
|
PULL_IMAGE_ERROR = 50002
|
||||||
|
DEVICE_NOT_EXIST = 50003
|
||||||
|
ERROR_APP_NAME_EXIST = 50004
|
||||||
|
|
||||||
|
//file
|
||||||
|
FILE_DOES_NOT_EXIST = 60001
|
||||||
|
FILE_READ_ERROR = 60002
|
||||||
|
FILE_DELETE_ERROR = 60003
|
||||||
|
DIR_NOT_EXISTS = 60004
|
||||||
|
SOURCE_DES_SAME = 60005
|
||||||
|
|
||||||
|
//share
|
||||||
|
SHARE_ALREADY_EXISTS = 70001
|
||||||
|
SHARE_NAME_ALREADY_EXISTS = 70002
|
||||||
|
)
|
||||||
|
|
||||||
|
var MsgFlags = map[int]string{
|
||||||
|
SUCCESS: "ok",
|
||||||
|
SERVICE_ERROR: "Fail",
|
||||||
|
CLIENT_ERROR: "Fail",
|
||||||
|
INVALID_PARAMS: "Parameters Error",
|
||||||
|
ERROR_AUTH_TOKEN: "Error auth token",
|
||||||
|
|
||||||
|
//user
|
||||||
|
PWD_INVALID: "Invalid password",
|
||||||
|
PWD_IS_EMPTY: "Password is empty",
|
||||||
|
PWD_INVALID_OLD: "Invalid old password",
|
||||||
|
ACCOUNT_LOCK: "Account is locked",
|
||||||
|
PWD_IS_TOO_SIMPLE: "Password is too simple",
|
||||||
|
USER_NOT_EXIST: "User does not exist",
|
||||||
|
USER_EXIST: "User already exists",
|
||||||
|
KEY_NOT_EXIST: "Key does not exist",
|
||||||
|
IMAGE_TOO_LARGE: "Image is too large",
|
||||||
|
NOT_IMAGE: "Not an image",
|
||||||
|
INSUFFICIENT_PERMISSIONS: "Insufficient permissions",
|
||||||
|
|
||||||
|
//system
|
||||||
|
DIR_ALREADY_EXISTS: "Folder already exists",
|
||||||
|
FILE_ALREADY_EXISTS: "File already exists",
|
||||||
|
FILE_OR_DIR_EXISTS: "File or folder already exists",
|
||||||
|
PORT_IS_OCCUPIED: "Port is occupied",
|
||||||
|
VERIFICATION_FAILURE: "Verification failure",
|
||||||
|
Record_ALREADY_EXIST: "Record already exists",
|
||||||
|
Record_NOT_EXIST: "Record does not exist",
|
||||||
|
SERVICE_NOT_RUNNING: "Service is not running",
|
||||||
|
CHARACTER_LIMIT: "Only uppercase letters, lowercase letters and numbers are allowed for username and password.",
|
||||||
|
|
||||||
|
//app
|
||||||
|
UNINSTALL_APP_ERROR: "Error uninstalling app",
|
||||||
|
PULL_IMAGE_ERROR: "Error pulling image",
|
||||||
|
DEVICE_NOT_EXIST: "Device does not exist",
|
||||||
|
ERROR_APP_NAME_EXIST: "App name already exists",
|
||||||
|
|
||||||
|
//disk
|
||||||
|
NAME_NOT_AVAILABLE: "Name not available",
|
||||||
|
DISK_NEEDS_FORMAT: "Drive needs to be formatted",
|
||||||
|
REMOVE_MOUNT_POINT_ERROR: "Failed to remove mount point",
|
||||||
|
DISK_BUSYING: "Drive is busy",
|
||||||
|
FORMAT_ERROR: "Formatting failed, please check if the directory is occupied",
|
||||||
|
//share
|
||||||
|
SHARE_ALREADY_EXISTS: "Share already exists",
|
||||||
|
SHARE_NAME_ALREADY_EXISTS: "Share name already exists",
|
||||||
|
//
|
||||||
|
SOURCE_DES_SAME: "Source and destination cannot be the same.",
|
||||||
|
FILE_DOES_NOT_EXIST: "File does not exist",
|
||||||
|
|
||||||
|
DIR_NOT_EXISTS: "Directory does not exist",
|
||||||
|
|
||||||
|
FILE_READ_ERROR: "File read error",
|
||||||
|
FILE_DELETE_ERROR: "Delete error",
|
||||||
|
|
||||||
|
COMMAND_ERROR_INVALID_OPERATION: "invalid operation",
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取错误信息
|
||||||
|
func GetMsg(code int) string {
|
||||||
|
msg, ok := MsgFlags[code]
|
||||||
|
if ok {
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
return MsgFlags[SERVICE_ERROR]
|
||||||
|
}
|
||||||
22
pkg/utils/encryption/md5_helper.go
Normal file
22
pkg/utils/encryption/md5_helper.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.com
|
||||||
|
* @Date: 2022-06-14 14:33:25
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-06-14 14:33:49
|
||||||
|
* @FilePath: /CasaOS/pkg/utils/encryption/md5_helper.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package encryption
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
"encoding/hex"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetMD5ByStr(str string) string {
|
||||||
|
h := md5.New()
|
||||||
|
h.Write([]byte(str))
|
||||||
|
return hex.EncodeToString(h.Sum(nil))
|
||||||
|
}
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
package env_helper
|
|
||||||
|
|
||||||
import "strings"
|
|
||||||
|
|
||||||
func ReplaceDefaultENV(key string) string {
|
|
||||||
temp := ""
|
|
||||||
switch key {
|
|
||||||
case "$DefaultPassword":
|
|
||||||
temp = "casaos"
|
|
||||||
case "$DefaultUserName":
|
|
||||||
temp = "admin"
|
|
||||||
}
|
|
||||||
return temp
|
|
||||||
}
|
|
||||||
|
|
||||||
//replace env default setting
|
|
||||||
func ReplaceStringDefaultENV(str string) string {
|
|
||||||
return strings.ReplaceAll(strings.ReplaceAll(str, "$DefaultPassword", ReplaceDefaultENV("$DefaultPassword")), "$DefaultUserName", ReplaceDefaultENV("$DefaultUserName"))
|
|
||||||
}
|
|
||||||
81
pkg/utils/file/block.go
Normal file
81
pkg/utils/file/block.go
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
package file
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
"encoding/hex"
|
||||||
|
"io"
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Get info of block
|
||||||
|
func GetBlockInfo(fileSize int64) (blockSize int, length int) {
|
||||||
|
switch {
|
||||||
|
case fileSize <= 1<<28: //256M
|
||||||
|
blockSize = 1 << 17 //128kb
|
||||||
|
case fileSize <= 1<<29: //512M
|
||||||
|
blockSize = 1 << 18 //256kb
|
||||||
|
case fileSize <= 1<<30: //1G
|
||||||
|
blockSize = 1 << 19 //512kb
|
||||||
|
case fileSize <= 1<<31: //2G
|
||||||
|
blockSize = 1 << 20 //(mb)
|
||||||
|
case fileSize <= 1<<32: //4G
|
||||||
|
blockSize = 1 << 21 //2mb
|
||||||
|
case fileSize <= 1<<33: //8G
|
||||||
|
blockSize = 1 << 22 //4mb
|
||||||
|
case fileSize <= 1<<34: //16g
|
||||||
|
blockSize = 1 << 23 //8mb
|
||||||
|
default:
|
||||||
|
blockSize = 1 << 24 //16mb
|
||||||
|
}
|
||||||
|
temp := float64(fileSize) / float64(blockSize)
|
||||||
|
length = int(math.Ceil(temp))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the hash of the data
|
||||||
|
func GetHashByContent(data []byte) string {
|
||||||
|
sum := md5.Sum(data)
|
||||||
|
return hex.EncodeToString(sum[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the hash of the data
|
||||||
|
func GetHashByPath(path string) string {
|
||||||
|
pFile, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
defer pFile.Close()
|
||||||
|
md5h := md5.New()
|
||||||
|
io.Copy(md5h, pFile)
|
||||||
|
return hex.EncodeToString(md5h.Sum(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
//Comparison data hash
|
||||||
|
func ComparisonHash(data []byte, hash string) bool {
|
||||||
|
sum := md5.Sum(data)
|
||||||
|
return hex.EncodeToString(sum[:]) == hash
|
||||||
|
}
|
||||||
|
|
||||||
|
//get prefix byte length
|
||||||
|
func PrefixLength(byteLength int) []byte {
|
||||||
|
lengthByte := []byte{'0', '0', '0', '0', '0', '0'}
|
||||||
|
bSize := strconv.Itoa(byteLength)
|
||||||
|
cha := 6 - len(bSize)
|
||||||
|
for i := len(bSize); i > 0; i-- {
|
||||||
|
lengthByte[cha+i-1] = bSize[i-1]
|
||||||
|
}
|
||||||
|
return lengthByte
|
||||||
|
}
|
||||||
|
|
||||||
|
//get data byte length
|
||||||
|
func DataLength(length int) []byte {
|
||||||
|
lengthByte := []byte{'0', '0', '0', '0', '0', '0', '0', '0'}
|
||||||
|
bSize := strconv.Itoa(length)
|
||||||
|
cha := 8 - len(bSize)
|
||||||
|
for i := len(bSize); i > 0; i-- {
|
||||||
|
lengthByte[cha+i-1] = bSize[i-1]
|
||||||
|
}
|
||||||
|
return lengthByte
|
||||||
|
}
|
||||||
@@ -1,11 +1,22 @@
|
|||||||
package file
|
package file
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/fs"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
path2 "path"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/mholt/archiver/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetSize get the file size
|
// GetSize get the file size
|
||||||
@@ -35,7 +46,7 @@ func CheckPermission(src string) bool {
|
|||||||
|
|
||||||
// IsNotExistMkDir create a directory if it does not exist
|
// IsNotExistMkDir create a directory if it does not exist
|
||||||
func IsNotExistMkDir(src string) error {
|
func IsNotExistMkDir(src string) error {
|
||||||
if notExist := CheckNotExist(src); notExist == true {
|
if notExist := CheckNotExist(src); notExist {
|
||||||
if err := MkDir(src); err != nil {
|
if err := MkDir(src); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -50,7 +61,7 @@ func MkDir(src string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
os.Chmod(src, 0777)
|
os.Chmod(src, 0o777)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -93,7 +104,7 @@ func MustOpen(fileName, filePath string) (*os.File, error) {
|
|||||||
return nil, fmt.Errorf("file.IsNotExistMkDir src: %s, err: %v", src, err)
|
return nil, fmt.Errorf("file.IsNotExistMkDir src: %s, err: %v", src, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := Open(src+fileName, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644)
|
f, err := Open(src+fileName, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0o644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Fail to OpenFile :%v", err)
|
return nil, fmt.Errorf("Fail to OpenFile :%v", err)
|
||||||
}
|
}
|
||||||
@@ -103,7 +114,7 @@ func MustOpen(fileName, filePath string) (*os.File, error) {
|
|||||||
|
|
||||||
// 判断所给路径文件/文件夹是否存在
|
// 判断所给路径文件/文件夹是否存在
|
||||||
func Exists(path string) bool {
|
func Exists(path string) bool {
|
||||||
_, err := os.Stat(path) //os.Stat获取文件信息
|
_, err := os.Stat(path) // os.Stat获取文件信息
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsExist(err) {
|
if os.IsExist(err) {
|
||||||
return true
|
return true
|
||||||
@@ -136,9 +147,24 @@ func CreateFile(path string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CreateFileAndWriteContent(path string, content string) error {
|
||||||
|
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0o666)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer file.Close()
|
||||||
|
write := bufio.NewWriter(file)
|
||||||
|
|
||||||
|
write.WriteString(content)
|
||||||
|
|
||||||
|
write.Flush()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// IsNotExistMkDir create a directory if it does not exist
|
// IsNotExistMkDir create a directory if it does not exist
|
||||||
func IsNotExistCreateFile(src string) error {
|
func IsNotExistCreateFile(src string) error {
|
||||||
if notExist := CheckNotExist(src); notExist == true {
|
if notExist := CheckNotExist(src); notExist {
|
||||||
if err := CreateFile(src); err != nil {
|
if err := CreateFile(src); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -159,3 +185,395 @@ func ReadFullFile(path string) []byte {
|
|||||||
}
|
}
|
||||||
return content
|
return content
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// File copies a single file from src to dst
|
||||||
|
func CopyFile(src, dst, style string) error {
|
||||||
|
var err error
|
||||||
|
var srcfd *os.File
|
||||||
|
var dstfd *os.File
|
||||||
|
var srcinfo os.FileInfo
|
||||||
|
|
||||||
|
lastPath := src[strings.LastIndex(src, "/")+1:]
|
||||||
|
|
||||||
|
if !strings.HasSuffix(dst, "/") {
|
||||||
|
dst += "/"
|
||||||
|
}
|
||||||
|
dst += lastPath
|
||||||
|
if Exists(dst) {
|
||||||
|
if style == "skip" {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
os.Remove(dst)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if srcfd, err = os.Open(src); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer srcfd.Close()
|
||||||
|
|
||||||
|
if dstfd, err = os.Create(dst); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer dstfd.Close()
|
||||||
|
|
||||||
|
if _, err = io.Copy(dstfd, srcfd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if srcinfo, err = os.Stat(src); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return os.Chmod(dst, srcinfo.Mode())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @param {*} src
|
||||||
|
* @param {*} dst
|
||||||
|
* @param {string} style
|
||||||
|
* @return {*}
|
||||||
|
* @method:
|
||||||
|
* @router:
|
||||||
|
*/
|
||||||
|
func CopySingleFile(src, dst, style string) error {
|
||||||
|
var err error
|
||||||
|
var srcfd *os.File
|
||||||
|
var dstfd *os.File
|
||||||
|
var srcinfo os.FileInfo
|
||||||
|
|
||||||
|
if Exists(dst) {
|
||||||
|
if style == "skip" {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
os.Remove(dst)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if srcfd, err = os.Open(src); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer srcfd.Close()
|
||||||
|
|
||||||
|
if dstfd, err = os.Create(dst); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer dstfd.Close()
|
||||||
|
|
||||||
|
if _, err = io.Copy(dstfd, srcfd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if srcinfo, err = os.Stat(src); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return os.Chmod(dst, srcinfo.Mode())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for duplicate file names
|
||||||
|
func GetNoDuplicateFileName(fullPath string) string {
|
||||||
|
path, fileName := filepath.Split(fullPath)
|
||||||
|
fileSuffix := path2.Ext(fileName)
|
||||||
|
filenameOnly := strings.TrimSuffix(fileName, fileSuffix)
|
||||||
|
for i := 0; Exists(fullPath); i++ {
|
||||||
|
fullPath = path2.Join(path, filenameOnly+"("+strconv.Itoa(i+1)+")"+fileSuffix)
|
||||||
|
}
|
||||||
|
return fullPath
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dir copies a whole directory recursively
|
||||||
|
func CopyDir(src string, dst string, style string) error {
|
||||||
|
var err error
|
||||||
|
var fds []os.FileInfo
|
||||||
|
var srcinfo os.FileInfo
|
||||||
|
|
||||||
|
if srcinfo, err = os.Stat(src); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !srcinfo.IsDir() {
|
||||||
|
if err = CopyFile(src, dst, style); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// dstPath := dst
|
||||||
|
lastPath := src[strings.LastIndex(src, "/")+1:]
|
||||||
|
dst += "/" + lastPath
|
||||||
|
// for i := 0; Exists(dst); i++ {
|
||||||
|
// dst = dstPath + "/" + lastPath + strconv.Itoa(i+1)
|
||||||
|
// }
|
||||||
|
if Exists(dst) {
|
||||||
|
if style == "skip" {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
os.Remove(dst)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = os.MkdirAll(dst, srcinfo.Mode()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if fds, err = ioutil.ReadDir(src); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, fd := range fds {
|
||||||
|
srcfp := path.Join(src, fd.Name())
|
||||||
|
dstfp := dst // path.Join(dst, fd.Name())
|
||||||
|
|
||||||
|
if fd.IsDir() {
|
||||||
|
if err = CopyDir(srcfp, dstfp, style); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err = CopyFile(srcfp, dstfp, style); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteToPath(data []byte, path, name string) error {
|
||||||
|
fullPath := path
|
||||||
|
if strings.HasSuffix(path, "/") {
|
||||||
|
fullPath += name
|
||||||
|
} else {
|
||||||
|
fullPath += "/" + name
|
||||||
|
}
|
||||||
|
return WriteToFullPath(data, fullPath, 0o666)
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteToFullPath(data []byte, fullPath string, perm fs.FileMode) error {
|
||||||
|
if err := IsNotExistCreateFile(fullPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
file, err := os.OpenFile(fullPath,
|
||||||
|
os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
|
||||||
|
perm,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
_, err = file.Write(data)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 最终拼接
|
||||||
|
func SpliceFiles(dir, path string, length int, startPoint int) error {
|
||||||
|
fullPath := path
|
||||||
|
|
||||||
|
if err := IsNotExistCreateFile(fullPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
file, _ := os.OpenFile(fullPath,
|
||||||
|
os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
|
||||||
|
0o666,
|
||||||
|
)
|
||||||
|
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
bufferedWriter := bufio.NewWriter(file)
|
||||||
|
|
||||||
|
// todo: here should have a goroutine to remove each partial file after it is read, to save disk space
|
||||||
|
|
||||||
|
for i := 0; i < length+startPoint-1; i++ {
|
||||||
|
data, err := ioutil.ReadFile(dir + "/" + strconv.Itoa(i+startPoint))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := bufferedWriter.Write(data); err != nil { // recommend to use https://github.com/iceber/iouring-go for faster write
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bufferedWriter.Flush()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetCompressionAlgorithm(t string) (string, archiver.Writer, error) {
|
||||||
|
switch t {
|
||||||
|
case "zip", "":
|
||||||
|
return ".zip", archiver.NewZip(), nil
|
||||||
|
case "tar":
|
||||||
|
return ".tar", archiver.NewTar(), nil
|
||||||
|
case "targz":
|
||||||
|
return ".tar.gz", archiver.NewTarGz(), nil
|
||||||
|
case "tarbz2":
|
||||||
|
return ".tar.bz2", archiver.NewTarBz2(), nil
|
||||||
|
case "tarxz":
|
||||||
|
return ".tar.xz", archiver.NewTarXz(), nil
|
||||||
|
case "tarlz4":
|
||||||
|
return ".tar.lz4", archiver.NewTarLz4(), nil
|
||||||
|
case "tarsz":
|
||||||
|
return ".tar.sz", archiver.NewTarSz(), nil
|
||||||
|
default:
|
||||||
|
return "", nil, errors.New("format not implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddFile(ar archiver.Writer, path, commonPath string) error {
|
||||||
|
info, err := os.Stat(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !info.IsDir() && !info.Mode().IsRegular() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
file, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
if path != commonPath {
|
||||||
|
filename := info.Name()
|
||||||
|
err = ar.Write(archiver.File{
|
||||||
|
FileInfo: archiver.FileInfo{
|
||||||
|
FileInfo: info,
|
||||||
|
CustomName: filename,
|
||||||
|
},
|
||||||
|
ReadCloser: file,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.IsDir() {
|
||||||
|
names, err := file.Readdirnames(0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, name := range names {
|
||||||
|
err = AddFile(ar, filepath.Join(path, name), commonPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed to archive %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CommonPrefix(sep byte, paths ...string) string {
|
||||||
|
// Handle special cases.
|
||||||
|
switch len(paths) {
|
||||||
|
case 0:
|
||||||
|
return ""
|
||||||
|
case 1:
|
||||||
|
return path.Clean(paths[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note, we treat string as []byte, not []rune as is often
|
||||||
|
// done in Go. (And sep as byte, not rune). This is because
|
||||||
|
// most/all supported OS' treat paths as string of non-zero
|
||||||
|
// bytes. A filename may be displayed as a sequence of Unicode
|
||||||
|
// runes (typically encoded as UTF-8) but paths are
|
||||||
|
// not required to be valid UTF-8 or in any normalized form
|
||||||
|
// (e.g. "é" (U+00C9) and "é" (U+0065,U+0301) are different
|
||||||
|
// file names.
|
||||||
|
c := []byte(path.Clean(paths[0]))
|
||||||
|
|
||||||
|
// We add a trailing sep to handle the case where the
|
||||||
|
// common prefix directory is included in the path list
|
||||||
|
// (e.g. /home/user1, /home/user1/foo, /home/user1/bar).
|
||||||
|
// path.Clean will have cleaned off trailing / separators with
|
||||||
|
// the exception of the root directory, "/" (in which case we
|
||||||
|
// make it "//", but this will get fixed up to "/" bellow).
|
||||||
|
c = append(c, sep)
|
||||||
|
|
||||||
|
// Ignore the first path since it's already in c
|
||||||
|
for _, v := range paths[1:] {
|
||||||
|
// Clean up each path before testing it
|
||||||
|
v = path.Clean(v) + string(sep)
|
||||||
|
|
||||||
|
// Find the first non-common byte and truncate c
|
||||||
|
if len(v) < len(c) {
|
||||||
|
c = c[:len(v)]
|
||||||
|
}
|
||||||
|
for i := 0; i < len(c); i++ {
|
||||||
|
if v[i] != c[i] {
|
||||||
|
c = c[:i]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove trailing non-separator characters and the final separator
|
||||||
|
for i := len(c) - 1; i >= 0; i-- {
|
||||||
|
if c[i] == sep {
|
||||||
|
c = c[:i]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetFileOrDirSize(path string) (int64, error) {
|
||||||
|
fileInfo, err := os.Stat(path)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if fileInfo.IsDir() {
|
||||||
|
return DirSizeB(path + "/")
|
||||||
|
}
|
||||||
|
return fileInfo.Size(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getFileSize get file size by path(B)
|
||||||
|
func DirSizeB(path string) (int64, error) {
|
||||||
|
var size int64
|
||||||
|
err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
|
||||||
|
if !info.IsDir() {
|
||||||
|
size += info.Size()
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
return size, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func MoveFile(sourcePath, destPath string) error {
|
||||||
|
inputFile, err := os.Open(sourcePath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Couldn't open source file: %s", err)
|
||||||
|
}
|
||||||
|
outputFile, err := os.Create(destPath)
|
||||||
|
if err != nil {
|
||||||
|
inputFile.Close()
|
||||||
|
return fmt.Errorf("Couldn't open dest file: %s", err)
|
||||||
|
}
|
||||||
|
defer outputFile.Close()
|
||||||
|
_, err = io.Copy(outputFile, inputFile)
|
||||||
|
inputFile.Close()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Writing to output file failed: %s", err)
|
||||||
|
}
|
||||||
|
err = os.Remove(sourcePath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed removing original file: %s", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadLine(lineNumber int, path string) string {
|
||||||
|
file, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
fileScanner := bufio.NewScanner(file)
|
||||||
|
lineCount := 1
|
||||||
|
for fileScanner.Scan() {
|
||||||
|
if lineCount == lineNumber {
|
||||||
|
return fileScanner.Text()
|
||||||
|
}
|
||||||
|
lineCount++
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|||||||
261
pkg/utils/file/image.go
Normal file
261
pkg/utils/file/image.go
Normal file
@@ -0,0 +1,261 @@
|
|||||||
|
package file
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/disintegration/imaging"
|
||||||
|
"github.com/dsoprea/go-exif/v3"
|
||||||
|
exifcommon "github.com/dsoprea/go-exif/v3/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetImage(path string, width, height int) ([]byte, error) {
|
||||||
|
if thumbnail, err := GetThumbnailByOwnerPhotos(path); err == nil {
|
||||||
|
return thumbnail, nil
|
||||||
|
} else {
|
||||||
|
return GetThumbnailByWebPhoto(path, width, height)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func GetThumbnailByOwnerPhotos(path string) ([]byte, error) {
|
||||||
|
file, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
buff := &bytes.Buffer{}
|
||||||
|
|
||||||
|
defer file.Close()
|
||||||
|
offset := 0
|
||||||
|
offsets := []int{12, 30}
|
||||||
|
|
||||||
|
head := make([]byte, 0xffff)
|
||||||
|
|
||||||
|
r := io.TeeReader(file, buff)
|
||||||
|
_, err = r.Read(head)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, offset = range offsets {
|
||||||
|
if _, err = exif.ParseExifHeader(head[offset:]); err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
im, err := exifcommon.NewIfdMappingWithStandard()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, index, err := exif.Collect(im, exif.NewTagIndex(), head[offset:])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ifd := index.RootIfd.NextIfd()
|
||||||
|
if ifd == nil {
|
||||||
|
return nil, exif.ErrNoThumbnail
|
||||||
|
}
|
||||||
|
thumbnail, err := ifd.Thumbnail()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return thumbnail, nil
|
||||||
|
}
|
||||||
|
func GetThumbnailByWebPhoto(path string, width, height int) ([]byte, error) {
|
||||||
|
src, err := imaging.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
img := imaging.Resize(src, width, 0, imaging.Lanczos)
|
||||||
|
|
||||||
|
f, err := imaging.FormatFromFilename(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
buf := bytes.Buffer{}
|
||||||
|
imaging.Encode(&buf, img, f)
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ImageExtArray() []string {
|
||||||
|
|
||||||
|
ext := []string{
|
||||||
|
"ase",
|
||||||
|
"art",
|
||||||
|
"bmp",
|
||||||
|
"blp",
|
||||||
|
"cd5",
|
||||||
|
"cit",
|
||||||
|
"cpt",
|
||||||
|
"cr2",
|
||||||
|
"cut",
|
||||||
|
"dds",
|
||||||
|
"dib",
|
||||||
|
"djvu",
|
||||||
|
"egt",
|
||||||
|
"exif",
|
||||||
|
"gif",
|
||||||
|
"gpl",
|
||||||
|
"grf",
|
||||||
|
"icns",
|
||||||
|
"ico",
|
||||||
|
"iff",
|
||||||
|
"jng",
|
||||||
|
"jpeg",
|
||||||
|
"jpg",
|
||||||
|
"jfif",
|
||||||
|
"jp2",
|
||||||
|
"jps",
|
||||||
|
"lbm",
|
||||||
|
"max",
|
||||||
|
"miff",
|
||||||
|
"mng",
|
||||||
|
"msp",
|
||||||
|
"nitf",
|
||||||
|
"ota",
|
||||||
|
"pbm",
|
||||||
|
"pc1",
|
||||||
|
"pc2",
|
||||||
|
"pc3",
|
||||||
|
"pcf",
|
||||||
|
"pcx",
|
||||||
|
"pdn",
|
||||||
|
"pgm",
|
||||||
|
"PI1",
|
||||||
|
"PI2",
|
||||||
|
"PI3",
|
||||||
|
"pict",
|
||||||
|
"pct",
|
||||||
|
"pnm",
|
||||||
|
"pns",
|
||||||
|
"ppm",
|
||||||
|
"psb",
|
||||||
|
"psd",
|
||||||
|
"pdd",
|
||||||
|
"psp",
|
||||||
|
"px",
|
||||||
|
"pxm",
|
||||||
|
"pxr",
|
||||||
|
"qfx",
|
||||||
|
"raw",
|
||||||
|
"rle",
|
||||||
|
"sct",
|
||||||
|
"sgi",
|
||||||
|
"rgb",
|
||||||
|
"int",
|
||||||
|
"bw",
|
||||||
|
"tga",
|
||||||
|
"tiff",
|
||||||
|
"tif",
|
||||||
|
"vtf",
|
||||||
|
"xbm",
|
||||||
|
"xcf",
|
||||||
|
"xpm",
|
||||||
|
"3dv",
|
||||||
|
"amf",
|
||||||
|
"ai",
|
||||||
|
"awg",
|
||||||
|
"cgm",
|
||||||
|
"cdr",
|
||||||
|
"cmx",
|
||||||
|
"dxf",
|
||||||
|
"e2d",
|
||||||
|
"egt",
|
||||||
|
"eps",
|
||||||
|
"fs",
|
||||||
|
"gbr",
|
||||||
|
"odg",
|
||||||
|
"svg",
|
||||||
|
"stl",
|
||||||
|
"vrml",
|
||||||
|
"x3d",
|
||||||
|
"sxd",
|
||||||
|
"v2d",
|
||||||
|
"vnd",
|
||||||
|
"wmf",
|
||||||
|
"emf",
|
||||||
|
"art",
|
||||||
|
"xar",
|
||||||
|
"png",
|
||||||
|
"webp",
|
||||||
|
"jxr",
|
||||||
|
"hdp",
|
||||||
|
"wdp",
|
||||||
|
"cur",
|
||||||
|
"ecw",
|
||||||
|
"iff",
|
||||||
|
"lbm",
|
||||||
|
"liff",
|
||||||
|
"nrrd",
|
||||||
|
"pam",
|
||||||
|
"pcx",
|
||||||
|
"pgf",
|
||||||
|
"sgi",
|
||||||
|
"rgb",
|
||||||
|
"rgba",
|
||||||
|
"bw",
|
||||||
|
"int",
|
||||||
|
"inta",
|
||||||
|
"sid",
|
||||||
|
"ras",
|
||||||
|
"sun",
|
||||||
|
"tga",
|
||||||
|
}
|
||||||
|
|
||||||
|
return ext
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:get a image's ext
|
||||||
|
* @param {string} path "file path"
|
||||||
|
* @return {string} ext "file ext"
|
||||||
|
* @return {error} err "error info"
|
||||||
|
*/
|
||||||
|
func GetImageExt(p string) (string, error) {
|
||||||
|
file, err := os.Open(p)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
buff := make([]byte, 512)
|
||||||
|
|
||||||
|
_, err = file.Read(buff)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
filetype := http.DetectContentType(buff)
|
||||||
|
|
||||||
|
ext := ImageExtArray()
|
||||||
|
|
||||||
|
for i := 0; i < len(ext); i++ {
|
||||||
|
if strings.Contains(ext[i], filetype[6:]) {
|
||||||
|
return ext[i], nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", errors.New("invalid image type")
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetImageExtByName(p string) (string, error) {
|
||||||
|
|
||||||
|
extArr := ImageExtArray()
|
||||||
|
ext := filepath.Ext(p)
|
||||||
|
for i := 0; i < len(extArr); i++ {
|
||||||
|
if strings.Contains(ext, extArr[i]) {
|
||||||
|
return extArr[i], nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", errors.New("invalid image type")
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@ package httper
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -12,13 +12,13 @@ import (
|
|||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
//发送GET请求
|
// 发送GET请求
|
||||||
//url:请求地址
|
// url:请求地址
|
||||||
//response:请求返回的内容
|
// response:请求返回的内容
|
||||||
func Get(url string, head map[string]string) (response string) {
|
func Get(url string, head map[string]string) (response string) {
|
||||||
client := http.Client{Timeout: 30 * time.Second}
|
client := &http.Client{Timeout: 30 * time.Second}
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
req.BasicAuth()
|
|
||||||
for k, v := range head {
|
for k, v := range head {
|
||||||
req.Header.Add(k, v)
|
req.Header.Add(k, v)
|
||||||
}
|
}
|
||||||
@@ -27,10 +27,11 @@ func Get(url string, head map[string]string) (response string) {
|
|||||||
}
|
}
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//需要错误日志的处理
|
fmt.Println(err)
|
||||||
//loger.Error(error)
|
// 需要错误日志的处理
|
||||||
|
// logger.Error(error)
|
||||||
return ""
|
return ""
|
||||||
//panic(error)
|
// panic(error)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
var buffer [512]byte
|
var buffer [512]byte
|
||||||
@@ -41,7 +42,7 @@ func Get(url string, head map[string]string) (response string) {
|
|||||||
if err != nil && err == io.EOF {
|
if err != nil && err == io.EOF {
|
||||||
break
|
break
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
//loger.Error(err)
|
// logger.Error(err)
|
||||||
return ""
|
return ""
|
||||||
// panic(err)
|
// panic(err)
|
||||||
}
|
}
|
||||||
@@ -50,11 +51,44 @@ func Get(url string, head map[string]string) (response string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//发送POST请求
|
// 发送GET请求
|
||||||
//url:请求地址,data:POST请求提交的数据,contentType:请求体格式,如:application/json
|
// url:请求地址
|
||||||
//content:请求放回的内容
|
// response:请求返回的内容
|
||||||
func Post(url string, data []byte, contentType string, head map[string]string) (content string) {
|
func PersonGet(url string) (response string) {
|
||||||
|
client := &http.Client{Timeout: 5 * time.Second}
|
||||||
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
// 需要错误日志的处理
|
||||||
|
// logger.Error(error)
|
||||||
|
return ""
|
||||||
|
// panic(error)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
var buffer [512]byte
|
||||||
|
result := bytes.NewBuffer(nil)
|
||||||
|
for {
|
||||||
|
n, err := resp.Body.Read(buffer[0:])
|
||||||
|
result.Write(buffer[0:n])
|
||||||
|
if err != nil && err == io.EOF {
|
||||||
|
break
|
||||||
|
} else if err != nil {
|
||||||
|
// logger.Error(err)
|
||||||
|
return ""
|
||||||
|
// panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
response = result.String()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送POST请求
|
||||||
|
// url:请求地址,data:POST请求提交的数据,contentType:请求体格式,如:application/json
|
||||||
|
// content:请求放回的内容
|
||||||
|
func Post(url string, data []byte, contentType string, head map[string]string) (content string) {
|
||||||
req, err := http.NewRequest("POST", url, bytes.NewBuffer(data))
|
req, err := http.NewRequest("POST", url, bytes.NewBuffer(data))
|
||||||
req.Header.Add("content-type", contentType)
|
req.Header.Add("content-type", contentType)
|
||||||
for k, v := range head {
|
for k, v := range head {
|
||||||
@@ -67,7 +101,8 @@ func Post(url string, data []byte, contentType string, head map[string]string) (
|
|||||||
client := &http.Client{Timeout: 5 * time.Second}
|
client := &http.Client{Timeout: 5 * time.Second}
|
||||||
resp, error := client.Do(req)
|
resp, error := client.Do(req)
|
||||||
if error != nil {
|
if error != nil {
|
||||||
panic(error)
|
fmt.Println(error)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
@@ -76,91 +111,9 @@ func Post(url string, data []byte, contentType string, head map[string]string) (
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//发送POST请求
|
// 发送POST请求
|
||||||
//url:请求地址,data:POST请求提交的数据,contentType:请求体格式,如:application/json
|
// url:请求地址,data:POST请求提交的数据,contentType:请求体格式,如:application/json
|
||||||
//content:请求放回的内容
|
// content:请求放回的内容
|
||||||
func ZeroTierPost(url string, data map[string]string, head map[string]string, cookies []*http.Cookie) (content string, code int) {
|
|
||||||
b, _ := json.Marshal(data)
|
|
||||||
req, err := http.NewRequest("POST", url, bytes.NewReader(b))
|
|
||||||
for _, cookie := range cookies {
|
|
||||||
req.AddCookie(cookie)
|
|
||||||
}
|
|
||||||
for k, v := range head {
|
|
||||||
req.Header.Add(k, v)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
client := &http.Client{Timeout: 20 * time.Second}
|
|
||||||
resp, error := client.Do(req)
|
|
||||||
|
|
||||||
if error != nil {
|
|
||||||
panic(error)
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
code = resp.StatusCode
|
|
||||||
result, _ := ioutil.ReadAll(resp.Body)
|
|
||||||
content = string(result)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//发送POST请求
|
|
||||||
//url:请求地址,data:POST请求提交的数据,contentType:请求体格式,如:application/json
|
|
||||||
//content:请求放回的内容
|
|
||||||
func ZeroTierPostJson(url string, data string, head map[string]string) (content string, code int) {
|
|
||||||
var postData *bytes.Buffer
|
|
||||||
|
|
||||||
jsonStr := []byte(data)
|
|
||||||
postData = bytes.NewBuffer(jsonStr)
|
|
||||||
|
|
||||||
req, err := http.NewRequest("POST", url, postData)
|
|
||||||
for k, v := range head {
|
|
||||||
req.Header.Add(k, v)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
client := &http.Client{Timeout: 20 * time.Second}
|
|
||||||
resp, error := client.Do(req)
|
|
||||||
|
|
||||||
if error != nil {
|
|
||||||
panic(error)
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
result, _ := ioutil.ReadAll(resp.Body)
|
|
||||||
content = string(result)
|
|
||||||
code = resp.StatusCode
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func ZeroTierDelete(url string, head map[string]string) (content string, code int) {
|
|
||||||
|
|
||||||
req, err := http.NewRequest("DELETE", url, nil)
|
|
||||||
for k, v := range head {
|
|
||||||
req.Header.Add(k, v)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
client := &http.Client{Timeout: 20 * time.Second}
|
|
||||||
resp, error := client.Do(req)
|
|
||||||
|
|
||||||
if error != nil {
|
|
||||||
panic(error)
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
result, _ := ioutil.ReadAll(resp.Body)
|
|
||||||
content = string(result)
|
|
||||||
code = resp.StatusCode
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//发送POST请求
|
|
||||||
//url:请求地址,data:POST请求提交的数据,contentType:请求体格式,如:application/json
|
|
||||||
//content:请求放回的内容
|
|
||||||
func ZeroTierGet(url string, head map[string]string) (content string, code int) {
|
func ZeroTierGet(url string, head map[string]string) (content string, code int) {
|
||||||
req, err := http.NewRequest(http.MethodGet, url, nil)
|
req, err := http.NewRequest(http.MethodGet, url, nil)
|
||||||
for k, v := range head {
|
for k, v := range head {
|
||||||
@@ -183,11 +136,10 @@ func ZeroTierGet(url string, head map[string]string) (content string, code int)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//发送GET请求
|
// 发送GET请求
|
||||||
//url:请求地址
|
// url:请求地址
|
||||||
//response:请求返回的内容
|
// response:请求返回的内容
|
||||||
func OasisGet(url string) (response string) {
|
func OasisGet(url string) (response string) {
|
||||||
|
|
||||||
head := make(map[string]string)
|
head := make(map[string]string)
|
||||||
|
|
||||||
t := make(chan string)
|
t := make(chan string)
|
||||||
@@ -200,5 +152,4 @@ func OasisGet(url string) (response string) {
|
|||||||
head["Authorization"] = <-t
|
head["Authorization"] = <-t
|
||||||
|
|
||||||
return Get(url, head)
|
return Get(url, head)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
package utils
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user