mirror of
https://github.com/IceWhaleTech/CasaOS.git
synced 2025-12-23 21:14:41 +00:00
Compare commits
176 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
cc46a96a75 | ||
|
|
049090444e | ||
|
|
796c25b7a5 | ||
|
|
9057290188 | ||
|
|
fcc57bb734 | ||
|
|
a98f5e087c | ||
|
|
403d563869 | ||
|
|
88c15104b4 | ||
|
|
6176289b88 | ||
|
|
5cfd44da79 | ||
|
|
2437da33a6 | ||
|
|
49ca0af746 | ||
|
|
9440b89fab | ||
|
|
f020c1162d | ||
|
|
120fb2cea2 | ||
|
|
37130966cf | ||
|
|
795b82c42c | ||
|
|
57ad33d53a | ||
|
|
a6ceee7bc0 | ||
|
|
44bb05fad0 | ||
|
|
a5fee0ee97 | ||
|
|
da99b2d01a | ||
|
|
1433e3297b | ||
|
|
cad7af13af | ||
|
|
39cb8904a3 | ||
|
|
595e0f28af | ||
|
|
d2962a8e70 | ||
|
|
d2ff1b0506 | ||
|
|
21f3fd85d9 | ||
|
|
0d6e7ca339 | ||
|
|
4f06be0e45 | ||
|
|
6ba845eec5 | ||
|
|
4fa72289ed | ||
|
|
cc5504c0a9 | ||
|
|
32e00b17b1 | ||
|
|
16108f03ac | ||
|
|
e7f990b224 | ||
|
|
c5d824c4ba | ||
|
|
e69d2e587b | ||
|
|
8fe0e4aa73 | ||
|
|
30a23a93a2 | ||
|
|
53157fbb1f |
32
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
32
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**Desktop (please complete the following information):**
|
||||||
|
- OS: [e.g. iOS]
|
||||||
|
- Browser [e.g. chrome, safari]
|
||||||
|
- Version [e.g. 22]
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
||||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
||||||
15
.github/ISSUE_TEMPLATE/submit-application.md
vendored
Normal file
15
.github/ISSUE_TEMPLATE/submit-application.md
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
name: Submit application
|
||||||
|
about: Add an app to this project
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: LinkLeong
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Tested platform
|
||||||
|
e.g. linux/amd64,linux/arm-v7,linux-arm64
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Please export and upload the configuration file of this application
|
||||||
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-Demo-Snapshot-[0-9]' | 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 large_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 }}
|
||||||
|
|
||||||
|
|
||||||
201
LICENSE
Normal file
201
LICENSE
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
91
README.md
91
README.md
@@ -1,4 +1,4 @@
|
|||||||
# CasaOS - A simple, easy-to-use, elegant open-source home server system.
|
# CasaOS - A simple, easy-to-use, elegant open-source Home Cloud system.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -6,18 +6,58 @@
|
|||||||
[](https://github.com/IceWhaleTech/CasaOS/pulls)
|
[](https://github.com/IceWhaleTech/CasaOS/pulls)
|
||||||
[](https://github.com/IceWhaleTech/CasaOS/issues)
|
[](https://github.com/IceWhaleTech/CasaOS/issues)
|
||||||
[](https://github.com/IceWhaleTech/CasaOS/stargazers)
|
[](https://github.com/IceWhaleTech/CasaOS/stargazers)
|
||||||
[](https://discord.gg/Gx4BCEtHjx)
|
[](https://discord.gg/knqAbbBbeX)
|
||||||
|
|
||||||
CasaOS is an open-source home server 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 server system.
|
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.
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
> ⚠️ Note:
|
||||||
|
>
|
||||||
|
> 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/knqAbbBbeX)!
|
||||||
|
|
||||||
|
### Quick Setup CasaOS
|
||||||
|
|
||||||
|
Fresh install a system from the list below and run the this command:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
wget -qO- https://get.icewhale.io/casaos.sh | bash
|
||||||
|
```
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
```sh
|
||||||
|
curl -fsSL https://get.icewhale.io/casaos.sh | bash
|
||||||
|
```
|
||||||
|
|
||||||
|
### Uninstall CasaOS
|
||||||
|
|
||||||
|
```sh
|
||||||
|
curl -fsSL https://get.icewhale.io/casaos-uninstall.sh | bash
|
||||||
|
```
|
||||||
|
|
||||||
|
### System Compatibility
|
||||||
|
|
||||||
|
- Ubuntu Server 20.04 amd64 (✅ Recommend, Tested)
|
||||||
|
- Armbian 22.02 armhf/arm64/amd64 (✅ Recommend, Tested)
|
||||||
|
- Elementary OS 6.1 Jólnir amd64 (✅ Recommend, Tested)
|
||||||
|
- Deepin 20.4 amd64 (⚠️ Not Fully Tested Yet)
|
||||||
|
- 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
|
## Key Features
|
||||||
|
|
||||||
- UI designed for home scenarios - simple, elegant, and easy-to-use
|
- UI designed for home scenarios - simple, elegant, and easy-to-use
|
||||||
- Quick Docker app installation with only three steps, plus automatic management
|
- Quick Docker app installation with only three steps, plus automatic management
|
||||||
- App Store for private cloud 🚧
|
- App Store for Home Cloud 🚧
|
||||||
- Home data/digital asset management 🚧
|
- Home data/digital asset management 🚧
|
||||||
- Smart home manager 🚧
|
- Smart home manager 🚧
|
||||||
|
|
||||||
@@ -34,48 +74,11 @@ 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)!
|
> A warm welcome for you to share and discuss your great ideas in the [Discord server](https://discord.gg/knqAbbBbeX)!
|
||||||
|
|
||||||
[](https://discord.gg/Gx4BCEtHjx)
|
[](https://discord.gg/knqAbbBbeX)
|
||||||
|
|
||||||
|
|
||||||
## Getting Started
|
|
||||||
|
|
||||||
> ⚠️ Note:
|
|
||||||
>
|
|
||||||
> 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)!
|
|
||||||
|
|
||||||
### System Compatibility
|
|
||||||
|
|
||||||
- Ubuntu Server 20.04 amd64 (✅ Recommend, Tested)
|
|
||||||
- Debian 11 amd64 (⚠️ Not Fully Tested Yet)
|
|
||||||
- OpenWrt 21.02 amd64 (⚠️ Not Fully Tested Yet)
|
|
||||||
- Raspberry Pi OS aarch64/arm64 (🚧 Under Planning)
|
|
||||||
- OpenWrt 21.02 aarch64/arm64 (🚧 Under Planning)
|
|
||||||
|
|
||||||
### Quick Setup CasaOS
|
|
||||||
|
|
||||||
Fresh install a system from the above list and run the below command:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
curl -fsSL https://get.icewhale.io/casaos.sh | bash
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## To Do
|
|
||||||
|
|
||||||
**v 0.1.x**
|
|
||||||
|
|
||||||
- [x] An elegant UI for home scenarios
|
|
||||||
- [x] Custom installation of Docker Apps
|
|
||||||
- [x] Update, stop, uninstall, restart, etc. of Docker apps
|
|
||||||
- [x] Docker CLI parser
|
|
||||||
- [x] System Update
|
|
||||||
- [ ] Getting Started tutorial
|
|
||||||
- [ ] Docker Compose parser
|
|
||||||
- [ ] App config file import and export
|
|
||||||
- [ ] macvlan network mode
|
|
||||||
|
|
||||||
|
|
||||||
## Maintainers
|
## Maintainers
|
||||||
- Jerry Liu
|
- Jerry Liu
|
||||||
@@ -83,4 +86,4 @@ curl -fsSL https://get.icewhale.io/casaos.sh | bash
|
|||||||
- Ober Zhang
|
- Ober Zhang
|
||||||
- Zyaire Ann
|
- Zyaire Ann
|
||||||
- John Guan
|
- John Guan
|
||||||
- Right here, waiting for YOU!
|
- Right here, waiting for YOU!
|
||||||
|
|||||||
2
UI
2
UI
Submodule UI updated: 66ab6d9470...74fa1f8920
@@ -9,12 +9,18 @@ DateTimeFormat = 2006-01-02 15:04:05
|
|||||||
TimeFormat = 15:04:05
|
TimeFormat = 15:04:05
|
||||||
DateFormat = 2006-01-02
|
DateFormat = 2006-01-02
|
||||||
ProjectPath = /casaOS/server
|
ProjectPath = /casaOS/server
|
||||||
|
RootPath = /casaOS
|
||||||
|
|
||||||
|
|
||||||
[server]
|
[server]
|
||||||
HttpPort = 8089
|
HttpPort = 8089
|
||||||
|
UDPPort =
|
||||||
RunMode = release
|
RunMode = release
|
||||||
ServerApi = https://api.casaos.zimaboard.com
|
ServerApi = https://api.casaos.zimaboard.com
|
||||||
|
Handshake = socket.casaos.io
|
||||||
|
Token =
|
||||||
|
USBAutoMount = true
|
||||||
|
|
||||||
|
|
||||||
[user]
|
[user]
|
||||||
UserName = admin
|
UserName = admin
|
||||||
@@ -22,12 +28,8 @@ PWD = zimaboard
|
|||||||
Email = user@gmail.com
|
Email = user@gmail.com
|
||||||
Description = description
|
Description = description
|
||||||
Initialized = false
|
Initialized = false
|
||||||
Token = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImVyZXJlIiwicGFzc3dvcmQiOiJhZHNmZGYiLCJleHAiOjE2MjQwMDU0ODEsImlzcyI6Imdpbi1ibG9nIn0.JNsCccZuFCwlSMLJg62iOIB2xymk_k7xGa11xhZ07bc
|
Avatar =
|
||||||
|
NickName =
|
||||||
[zerotier]
|
|
||||||
UserName = user
|
|
||||||
PWD = pwd
|
|
||||||
Token = yBKYyavr2RdFAIVN7iTpzlsB1o6CqTgm
|
|
||||||
|
|
||||||
[redis]
|
[redis]
|
||||||
Host = 127.0.0.1:6379
|
Host = 127.0.0.1:6379
|
||||||
@@ -39,4 +41,8 @@ IdleTimeout = 200
|
|||||||
[system]
|
[system]
|
||||||
ConfigStr =
|
ConfigStr =
|
||||||
WidgetList =
|
WidgetList =
|
||||||
|
Analyse =
|
||||||
|
|
||||||
|
[file]
|
||||||
|
ShareDir =
|
||||||
|
DownloadDir =
|
||||||
14
go.mod
14
go.mod
@@ -10,10 +10,11 @@ require (
|
|||||||
github.com/bits-and-blooms/bitset v1.2.1 // indirect
|
github.com/bits-and-blooms/bitset v1.2.1 // indirect
|
||||||
github.com/containerd/containerd v1.5.7
|
github.com/containerd/containerd v1.5.7
|
||||||
github.com/containerd/continuity v0.2.0 // indirect
|
github.com/containerd/continuity v0.2.0 // indirect
|
||||||
|
github.com/docker/distribution v2.8.0+incompatible // indirect
|
||||||
github.com/docker/docker v20.10.7+incompatible
|
github.com/docker/docker v20.10.7+incompatible
|
||||||
github.com/docker/go-connections v0.4.0
|
github.com/docker/go-connections v0.4.0
|
||||||
github.com/forease/gotld v0.0.0-20190808124948-c50ff635576b
|
github.com/forease/gotld v0.0.0-20190808124948-c50ff635576b
|
||||||
github.com/gin-contrib/gzip v0.0.2 // indirect
|
github.com/gin-contrib/gzip v0.0.2
|
||||||
github.com/gin-gonic/gin v1.7.2
|
github.com/gin-gonic/gin v1.7.2
|
||||||
github.com/go-ini/ini v1.62.0
|
github.com/go-ini/ini v1.62.0
|
||||||
github.com/go-ole/go-ole v1.2.5 // indirect
|
github.com/go-ole/go-ole v1.2.5 // indirect
|
||||||
@@ -31,10 +32,13 @@ require (
|
|||||||
github.com/json-iterator/go v1.1.11 // indirect
|
github.com/json-iterator/go v1.1.11 // indirect
|
||||||
github.com/klauspost/compress v1.13.6 // indirect
|
github.com/klauspost/compress v1.13.6 // indirect
|
||||||
github.com/leodido/go-urn v1.2.1 // indirect
|
github.com/leodido/go-urn v1.2.1 // indirect
|
||||||
|
github.com/lucas-clemente/quic-go v0.25.0
|
||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.11 // indirect
|
||||||
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
||||||
github.com/morikuni/aec v1.0.0 // indirect
|
github.com/morikuni/aec v1.0.0 // indirect
|
||||||
|
github.com/opencontainers/image-spec v1.0.2 // indirect
|
||||||
github.com/opencontainers/selinux v1.8.5 // 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/pkg/errors v0.9.1
|
||||||
@@ -46,10 +50,10 @@ require (
|
|||||||
github.com/sirupsen/logrus v1.8.1
|
github.com/sirupsen/logrus v1.8.1
|
||||||
github.com/smartystreets/assertions v1.2.0 // indirect
|
github.com/smartystreets/assertions v1.2.0 // indirect
|
||||||
github.com/smartystreets/goconvey v1.6.4 // indirect
|
github.com/smartystreets/goconvey v1.6.4 // indirect
|
||||||
|
github.com/spf13/afero v1.2.2
|
||||||
github.com/swaggo/gin-swagger v1.3.0
|
github.com/swaggo/gin-swagger v1.3.0
|
||||||
github.com/swaggo/swag v1.7.3
|
github.com/swaggo/swag v1.7.3
|
||||||
github.com/tidwall/gjson v1.8.0
|
github.com/tidwall/gjson v1.10.2
|
||||||
github.com/tidwall/pretty v1.2.0 // indirect
|
|
||||||
github.com/tklauser/go-sysconf v0.3.6 // indirect
|
github.com/tklauser/go-sysconf v0.3.6 // indirect
|
||||||
github.com/ugorji/go v1.2.6 // indirect
|
github.com/ugorji/go v1.2.6 // indirect
|
||||||
go.opencensus.io v0.23.0 // indirect
|
go.opencensus.io v0.23.0 // indirect
|
||||||
@@ -67,6 +71,6 @@ require (
|
|||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
gopkg.in/ini.v1 v1.62.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||||
gorm.io/driver/sqlite v1.1.5
|
gorm.io/driver/sqlite v1.2.6
|
||||||
gorm.io/gorm v1.21.15
|
gorm.io/gorm v1.22.5
|
||||||
)
|
)
|
||||||
|
|||||||
161
go.sum
161
go.sum
@@ -1,7 +1,9 @@
|
|||||||
bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
|
bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
|
||||||
bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM=
|
bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM=
|
||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo=
|
||||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||||
@@ -32,7 +34,12 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
|
|||||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||||
|
dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
|
dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
|
||||||
|
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
|
||||||
|
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
|
||||||
|
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||||
github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
||||||
@@ -94,6 +101,7 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF
|
|||||||
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
|
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
|
||||||
github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
|
github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
|
||||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||||
|
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||||
@@ -110,8 +118,10 @@ github.com/bits-and-blooms/bitset v1.2.1/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edY
|
|||||||
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||||
|
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
|
||||||
github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
|
github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
|
||||||
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
||||||
|
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
||||||
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
|
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
|
||||||
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
|
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
|
||||||
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
|
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
|
||||||
@@ -120,6 +130,8 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf
|
|||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
|
github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
|
||||||
github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
|
github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
|
||||||
|
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
|
||||||
|
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
@@ -233,6 +245,7 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
|
|||||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
|
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
|
github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
|
||||||
github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
|
github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
|
||||||
@@ -259,8 +272,9 @@ github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8
|
|||||||
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||||
github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
|
github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
|
||||||
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
|
||||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
|
github.com/docker/distribution v2.8.0+incompatible h1:l9EaZDICImO1ngI+uTifW+ZYvvz7fKISBAKpg+MbWbY=
|
||||||
|
github.com/docker/distribution v2.8.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/docker/docker v20.10.7+incompatible h1:Z6O9Nhsjv+ayUEeI1IojKbYcsGdgYSNqxe1s2MYzUhQ=
|
github.com/docker/docker v20.10.7+incompatible h1:Z6O9Nhsjv+ayUEeI1IojKbYcsGdgYSNqxe1s2MYzUhQ=
|
||||||
github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||||
@@ -289,11 +303,14 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.
|
|||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
|
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||||
github.com/forease/gotld v0.0.0-20190808124948-c50ff635576b h1:r13MvtFTtnvxtuKK7z0ZSQ2EfMmTzWDHwfDvGCoqUQE=
|
github.com/forease/gotld v0.0.0-20190808124948-c50ff635576b h1:r13MvtFTtnvxtuKK7z0ZSQ2EfMmTzWDHwfDvGCoqUQE=
|
||||||
github.com/forease/gotld v0.0.0-20190808124948-c50ff635576b/go.mod h1:EfR6AU78zUiZ36oVS5YrmTzc2um3zDXWPx4L4st++jo=
|
github.com/forease/gotld v0.0.0-20190808124948-c50ff635576b/go.mod h1:EfR6AU78zUiZ36oVS5YrmTzc2um3zDXWPx4L4st++jo=
|
||||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||||
|
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
|
||||||
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
|
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
|
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
|
||||||
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
|
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
|
||||||
@@ -311,6 +328,8 @@ github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/
|
|||||||
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||||
github.com/gin-gonic/gin v1.7.2 h1:Tg03T9yM2xa8j6I3Z3oqLaQRSmKvxPd6g/2HJ6zICFA=
|
github.com/gin-gonic/gin v1.7.2 h1:Tg03T9yM2xa8j6I3Z3oqLaQRSmKvxPd6g/2HJ6zICFA=
|
||||||
github.com/gin-gonic/gin v1.7.2/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
|
github.com/gin-gonic/gin v1.7.2/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
|
||||||
|
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||||
|
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
@@ -360,6 +379,8 @@ github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn
|
|||||||
github.com/go-playground/validator/v10 v10.6.1 h1:W6TRDXt4WcWp4c4nf/G+6BkGdhiIo0k417gfr+V6u4I=
|
github.com/go-playground/validator/v10 v10.6.1 h1:W6TRDXt4WcWp4c4nf/G+6BkGdhiIo0k417gfr+V6u4I=
|
||||||
github.com/go-playground/validator/v10 v10.6.1/go.mod h1:xm76BBt941f7yWdGnI2DVPFFg1UK3YY04qifoXU3lOk=
|
github.com/go-playground/validator/v10 v10.6.1/go.mod h1:xm76BBt941f7yWdGnI2DVPFFg1UK3YY04qifoXU3lOk=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
||||||
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||||
github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||||
github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||||
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
|
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
|
||||||
@@ -387,6 +408,7 @@ github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4er
|
|||||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||||
@@ -394,6 +416,8 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
|
|||||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||||
|
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||||
|
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
@@ -428,6 +452,8 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
|
||||||
|
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||||
github.com/google/go-github/v36 v36.0.0 h1:ndCzM616/oijwufI7nBRa+5eZHLldT+4yIB68ib5ogs=
|
github.com/google/go-github/v36 v36.0.0 h1:ndCzM616/oijwufI7nBRa+5eZHLldT+4yIB68ib5ogs=
|
||||||
github.com/google/go-github/v36 v36.0.0/go.mod h1:LFlKC047IOqiglRGNqNb9s/iAPTnnjtlshm+bxp+kwk=
|
github.com/google/go-github/v36 v36.0.0/go.mod h1:LFlKC047IOqiglRGNqNb9s/iAPTnnjtlshm+bxp+kwk=
|
||||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||||
@@ -450,6 +476,8 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
|
|||||||
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||||
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
|
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
|
||||||
@@ -467,6 +495,7 @@ github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:Fecb
|
|||||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||||
@@ -486,12 +515,14 @@ github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH
|
|||||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
|
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
|
||||||
|
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
|
||||||
github.com/jinzhu/copier v0.3.2 h1:QdBOCbaouLDYaIPFfi1bKv5F5tPpeTwXe4sD0jqtz5w=
|
github.com/jinzhu/copier v0.3.2 h1:QdBOCbaouLDYaIPFfi1bKv5F5tPpeTwXe4sD0jqtz5w=
|
||||||
github.com/jinzhu/copier v0.3.2/go.mod h1:24xnZezI2Yqac9J61UC6/dG/k76ttpq0DdJI3QmUvro=
|
github.com/jinzhu/copier v0.3.2/go.mod h1:24xnZezI2Yqac9J61UC6/dG/k76ttpq0DdJI3QmUvro=
|
||||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||||
github.com/jinzhu/now v1.1.2 h1:eVKgfIdy9b6zbWBMgFpfDPoAMifwSZagU9HmEU6zgiI=
|
|
||||||
github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
|
github.com/jinzhu/now v1.1.4 h1:tHnRBy1i5F2Dh8BAFxqFzxKqqvezXrL2OW1TnX+Mlas=
|
||||||
|
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||||
github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
@@ -526,6 +557,7 @@ github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn
|
|||||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
|
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
@@ -533,8 +565,12 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
|||||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||||
|
github.com/lucas-clemente/quic-go v0.25.0 h1:K+X9Gvd7JXsOHtU0N2icZ2Nw3rx82uBej3mP4CLgibc=
|
||||||
|
github.com/lucas-clemente/quic-go v0.25.0/go.mod h1:YtzP8bxRVCBlO77yRanE264+fY/T2U9ZlW1AaHOsMOg=
|
||||||
|
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
|
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
|
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
|
||||||
@@ -542,6 +578,14 @@ github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ
|
|||||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||||
github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
|
github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
|
||||||
|
github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc=
|
||||||
|
github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I=
|
||||||
|
github.com/marten-seemann/qtls-go1-16 v0.1.4 h1:xbHbOGGhrenVtII6Co8akhLEdrawwB2iHl5yhJRpnco=
|
||||||
|
github.com/marten-seemann/qtls-go1-16 v0.1.4/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk=
|
||||||
|
github.com/marten-seemann/qtls-go1-17 v0.1.0 h1:P9ggrs5xtwiqXv/FHNwntmuLMNq3KaSIG93AtAZ48xk=
|
||||||
|
github.com/marten-seemann/qtls-go1-17 v0.1.0/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8=
|
||||||
|
github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 h1:EnzzN9fPUkUck/1CuY1FlzBaIYMoiBsdwTNmNGkwUUM=
|
||||||
|
github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1/go.mod h1:PUhIQk19LoFt2174H4+an8TYvWOGjb/hHwphBeaDHwI=
|
||||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
@@ -551,10 +595,12 @@ github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9
|
|||||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||||
github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
|
github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
|
||||||
github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxzIU=
|
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||||
github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
github.com/mattn/go-sqlite3 v1.14.11 h1:gt+cp9c0XGqe9S/wAHTL3n/7MqY+siPWgWJgqdsFrzQ=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.11/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||||
|
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
||||||
github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
||||||
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
|
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
@@ -583,8 +629,12 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m
|
|||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||||
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
|
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
|
||||||
|
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
||||||
|
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||||
|
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||||
|
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||||
github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
@@ -594,11 +644,18 @@ github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+
|
|||||||
github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||||
|
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||||
|
github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
|
||||||
|
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
|
||||||
|
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||||
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
|
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||||
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
|
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
|
||||||
|
github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
|
||||||
|
github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
|
||||||
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||||
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||||
@@ -606,8 +663,9 @@ github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.
|
|||||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
|
|
||||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
|
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
|
||||||
|
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
@@ -628,6 +686,7 @@ github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3
|
|||||||
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
||||||
github.com/opencontainers/selinux v1.8.5 h1:OkT6bMHOQ1JQQO4ihjQ49sj0+wciDcjziSVTRn8VeTA=
|
github.com/opencontainers/selinux v1.8.5 h1:OkT6bMHOQ1JQQO4ihjQ49sj0+wciDcjziSVTRn8VeTA=
|
||||||
github.com/opencontainers/selinux v1.8.5/go.mod h1:HTvjPFoGMbpQsG886e3lQwnsRWtE4TC1OF3OUvG9FAo=
|
github.com/opencontainers/selinux v1.8.5/go.mod h1:HTvjPFoGMbpQsG886e3lQwnsRWtE4TC1OF3OUvG9FAo=
|
||||||
|
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
@@ -644,6 +703,7 @@ github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prY
|
|||||||
github.com/prestonTao/upnp v0.0.0-20150206124352-f4370df5e109 h1:h9WYaTCQJ7hap8C5vQniEum2YZbc+iRad/ROafTjy10=
|
github.com/prestonTao/upnp v0.0.0-20150206124352-f4370df5e109 h1:h9WYaTCQJ7hap8C5vQniEum2YZbc+iRad/ROafTjy10=
|
||||||
github.com/prestonTao/upnp v0.0.0-20150206124352-f4370df5e109/go.mod h1:U7VCLF6LMHzOFD/6Kww2MTQuwaNeEA1U1dOxFyZBoBE=
|
github.com/prestonTao/upnp v0.0.0-20150206124352-f4370df5e109/go.mod h1:U7VCLF6LMHzOFD/6Kww2MTQuwaNeEA1U1dOxFyZBoBE=
|
||||||
github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
|
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||||
@@ -655,12 +715,14 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:
|
|||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||||
|
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
|
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
|
||||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||||
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
|
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
@@ -679,15 +741,39 @@ github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfm
|
|||||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
|
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
|
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
|
||||||
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
||||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||||
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
|
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
|
||||||
|
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||||
github.com/shirou/gopsutil/v3 v3.21.5 h1:YUBf0w/KPLk7w1803AYBnH7BmA+1Z/Q5MEZxpREUaB4=
|
github.com/shirou/gopsutil/v3 v3.21.5 h1:YUBf0w/KPLk7w1803AYBnH7BmA+1Z/Q5MEZxpREUaB4=
|
||||||
github.com/shirou/gopsutil/v3 v3.21.5/go.mod h1:ghfMypLDrFSWN2c9cDYFLHyynQ+QUht0cv/18ZqVczw=
|
github.com/shirou/gopsutil/v3 v3.21.5/go.mod h1:ghfMypLDrFSWN2c9cDYFLHyynQ+QUht0cv/18ZqVczw=
|
||||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||||
|
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
|
||||||
|
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
|
||||||
|
github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
|
||||||
|
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
|
||||||
|
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
|
||||||
|
github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw=
|
||||||
|
github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI=
|
||||||
|
github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU=
|
||||||
|
github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag=
|
||||||
|
github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg=
|
||||||
|
github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw=
|
||||||
|
github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y=
|
||||||
|
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
||||||
|
github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q=
|
||||||
|
github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ=
|
||||||
|
github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I=
|
||||||
|
github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0=
|
||||||
|
github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ=
|
||||||
|
github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk=
|
||||||
|
github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
|
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
|
||||||
|
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
|
||||||
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||||
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
@@ -704,8 +790,11 @@ github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:s
|
|||||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||||
|
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
|
||||||
|
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
|
||||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||||
|
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
|
||||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||||
@@ -740,12 +829,12 @@ github.com/swaggo/swag v1.7.3/go.mod h1:zD8h6h4SPv7t3l+4BKdRquqW1ASWjKZgT6Qv9z3k
|
|||||||
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||||
|
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
||||||
github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
|
github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
|
||||||
github.com/tidwall/gjson v1.8.0 h1:Qt+orfosKn0rbNTZqHYDqBrmm3UDA4KRkv70fDzG+PQ=
|
github.com/tidwall/gjson v1.10.2 h1:APbLGOM0rrEkd8WBw9C24nllro4ajFuJu0Sc9hRz8Bo=
|
||||||
github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
|
github.com/tidwall/gjson v1.10.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||||
github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE=
|
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||||
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||||
github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
|
||||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
github.com/tklauser/go-sysconf v0.3.4/go.mod h1:Cl2c8ZRWfHD5IrfHo9VN+FX9kCFjIOyVklgXycLB6ek=
|
github.com/tklauser/go-sysconf v0.3.4/go.mod h1:Cl2c8ZRWfHD5IrfHo9VN+FX9kCFjIOyVklgXycLB6ek=
|
||||||
@@ -772,6 +861,8 @@ github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijb
|
|||||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||||
|
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
|
||||||
|
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
|
||||||
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
|
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
|
||||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||||
github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
|
github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
|
||||||
@@ -789,6 +880,7 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
|||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
|
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
|
||||||
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
|
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
|
||||||
@@ -798,6 +890,7 @@ go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
|||||||
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||||
go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg=
|
go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg=
|
||||||
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
|
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
|
||||||
|
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
@@ -810,15 +903,20 @@ go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
|||||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||||
|
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
||||||
|
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
|
||||||
golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
@@ -837,6 +935,7 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH
|
|||||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
|
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
@@ -864,11 +963,14 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r
|
|||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
@@ -893,6 +995,7 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/
|
|||||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
@@ -905,16 +1008,20 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
||||||
|
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211020060615-d418f374d309 h1:A0lJIi+hcTR6aajJH4YqKWwohY4aW9RO7oRMcdv+HKI=
|
golang.org/x/net v0.0.0-20211020060615-d418f374d309 h1:A0lJIi+hcTR6aajJH4YqKWwohY4aW9RO7oRMcdv+HKI=
|
||||||
golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f h1:Qmd2pbz05z7z6lm0DrgQVVPuBm92jqujBKMHMOlOQEw=
|
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f h1:Qmd2pbz05z7z6lm0DrgQVVPuBm92jqujBKMHMOlOQEw=
|
||||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@@ -930,12 +1037,14 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -979,6 +1088,7 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -994,6 +1104,7 @@ golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210217105451-b926d437f341/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210217105451-b926d437f341/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -1031,7 +1142,9 @@ golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxb
|
|||||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs=
|
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs=
|
||||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
@@ -1078,8 +1191,10 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
|
|||||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
|
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||||
|
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ=
|
golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ=
|
||||||
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@@ -1088,6 +1203,9 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
|
|||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||||
|
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||||
|
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||||
|
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
|
||||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||||
@@ -1105,6 +1223,8 @@ google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M
|
|||||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
|
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||||
@@ -1114,6 +1234,10 @@ google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6
|
|||||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk=
|
google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
|
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
|
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
|
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
|
||||||
|
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
@@ -1149,6 +1273,9 @@ google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6D
|
|||||||
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0 h1:5Tbluzus3QxoAJx4IefGt1W0HQZW4nuMrVk684jI74Q=
|
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0 h1:5Tbluzus3QxoAJx4IefGt1W0HQZW4nuMrVk684jI74Q=
|
||||||
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
|
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
|
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||||
|
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
@@ -1207,6 +1334,7 @@ gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
|||||||
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||||
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||||
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
@@ -1222,15 +1350,18 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
|||||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gorm.io/driver/sqlite v1.1.5 h1:JU8G59VyKu1x1RMQgjefQnkZjDe9wHc1kARDZPu5dZs=
|
gorm.io/driver/sqlite v1.2.6 h1:SStaH/b+280M7C8vXeZLz/zo9cLQmIGwwj3cSj7p6l4=
|
||||||
gorm.io/driver/sqlite v1.1.5/go.mod h1:NpaYMcVKEh6vLJ47VP6T7Weieu4H1Drs3dGD/K6GrGc=
|
gorm.io/driver/sqlite v1.2.6/go.mod h1:gyoX0vHiiwi0g49tv+x2E7l8ksauLK0U/gShcdUsjWY=
|
||||||
gorm.io/gorm v1.21.15 h1:gAyaDoPw0lCyrSFWhBlahbUA1U4P5RViC1uIqoB+1Rk=
|
gorm.io/gorm v1.22.3/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
|
||||||
gorm.io/gorm v1.21.15/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
|
gorm.io/gorm v1.22.5 h1:lYREBgc02Be/5lSCTuysZZDb6ffL2qrat6fg9CFbvXU=
|
||||||
|
gorm.io/gorm v1.22.5/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
|
||||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||||
gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
|
gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
|
||||||
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
||||||
|
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
||||||
|
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
@@ -1272,3 +1403,5 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK
|
|||||||
sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||||
|
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
|
||||||
|
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
|
||||||
|
|||||||
53
main.go
53
main.go
@@ -4,6 +4,7 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/cache"
|
"github.com/IceWhaleTech/CasaOS/pkg/cache"
|
||||||
@@ -28,10 +29,40 @@ func init() {
|
|||||||
config.InitSetup(*configFlag)
|
config.InitSetup(*configFlag)
|
||||||
config.UpdateSetup()
|
config.UpdateSetup()
|
||||||
loger2.LogSetup()
|
loger2.LogSetup()
|
||||||
|
sysType := runtime.GOOS
|
||||||
|
if sysType == "windows" {
|
||||||
|
config.AppInfo.ProjectPath = "C:\\CasaOS\\service"
|
||||||
|
config.Cfg.Section("app").Key("ProjectPath").SetValue("C:\\CasaOS\\service")
|
||||||
|
|
||||||
|
config.AppInfo.RootPath = "C:\\CasaOS"
|
||||||
|
config.Cfg.Section("app").Key("RootPath").SetValue("C:\\CasaOS")
|
||||||
|
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||||
|
}
|
||||||
|
if sysType == "darwin" {
|
||||||
|
config.AppInfo.ProjectPath = "./CasaOS/service"
|
||||||
|
config.Cfg.Section("app").Key("ProjectPath").SetValue("./CasaOS/service")
|
||||||
|
|
||||||
|
config.AppInfo.RootPath = "./CasaOS"
|
||||||
|
config.Cfg.Section("app").Key("RootPath").SetValue("./CasaOS")
|
||||||
|
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||||
|
}
|
||||||
|
|
||||||
sqliteDB = sqlite.GetDb(config.AppInfo.ProjectPath)
|
sqliteDB = sqlite.GetDb(config.AppInfo.ProjectPath)
|
||||||
//gredis.GetRedisConn(config.RedisInfo),
|
//gredis.GetRedisConn(config.RedisInfo),
|
||||||
service.MyService = service.NewService(sqliteDB, loger2.NewOLoger())
|
service.MyService = service.NewService(sqliteDB, loger2.NewOLoger())
|
||||||
service.Cache = cache.Init()
|
service.Cache = cache.Init()
|
||||||
|
|
||||||
|
go service.UDPService()
|
||||||
|
|
||||||
|
fmt.Println("token", service.GetToken())
|
||||||
|
service.UDPAddressMap = make(map[string]string)
|
||||||
|
//go service.SocketConnect()
|
||||||
|
service.CancelList = make(map[string]string)
|
||||||
|
route.InitFunction()
|
||||||
|
|
||||||
|
go service.SendIPToServer()
|
||||||
|
go service.LoopFriend()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @title casaOS API
|
// @title casaOS API
|
||||||
@@ -56,17 +87,30 @@ func main() {
|
|||||||
//gredis.Setup()
|
//gredis.Setup()
|
||||||
r := route.InitRouter()
|
r := route.InitRouter()
|
||||||
//service.SyncTask(sqliteDB)
|
//service.SyncTask(sqliteDB)
|
||||||
cron2 := cron.New() //创建一个cron实例
|
cron2 := cron.New()
|
||||||
//执行定时任务(每5秒执行一次)
|
//every day execution
|
||||||
err := cron2.AddFunc("0 0 0 1/1 * *", func() {
|
err := cron2.AddFunc("0 0/5 * * * *", func() {
|
||||||
|
//service.PushIpInfo(*&config.ServerInfo.Token)
|
||||||
//service.UpdataDDNSList(mysqldb)
|
//service.UpdataDDNSList(mysqldb)
|
||||||
//service.SyncTask(sqliteDB)
|
//service.SyncTask(sqliteDB)
|
||||||
|
|
||||||
|
service.SendIPToServer()
|
||||||
|
|
||||||
|
service.LoopFriend()
|
||||||
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
|
// err = cron2.AddFunc("0/1 * * * * *", func() {
|
||||||
|
|
||||||
//启动/关闭
|
// //service.SendIPToServer()
|
||||||
|
// //service.LoopNet()
|
||||||
|
|
||||||
|
// })
|
||||||
|
// if err != nil {
|
||||||
|
// fmt.Println(err)
|
||||||
|
// }
|
||||||
cron2.Start()
|
cron2.Start()
|
||||||
defer cron2.Stop()
|
defer cron2.Stop()
|
||||||
s := &http.Server{
|
s := &http.Server{
|
||||||
@@ -76,6 +120,7 @@ func main() {
|
|||||||
WriteTimeout: 60 * time.Second,
|
WriteTimeout: 60 * time.Second,
|
||||||
MaxHeaderBytes: 1 << 20,
|
MaxHeaderBytes: 1 << 20,
|
||||||
}
|
}
|
||||||
|
|
||||||
s.ListenAndServe()
|
s.ListenAndServe()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ package middleware
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Cors() gin.HandlerFunc {
|
func Cors() gin.HandlerFunc {
|
||||||
@@ -17,7 +18,7 @@ func Cors() gin.HandlerFunc {
|
|||||||
//服务器支持的所有跨域请求的方法
|
//服务器支持的所有跨域请求的方法
|
||||||
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE")
|
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-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,Language")
|
||||||
// 允许浏览器(客户端)可以解析的头部 (重要)
|
// 允许浏览器(客户端)可以解析的头部 (重要)
|
||||||
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers")
|
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers")
|
||||||
//设置缓存时间
|
//设置缓存时间
|
||||||
|
|||||||
16
model/app-analyse.go
Normal file
16
model/app-analyse.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type AppAnalyse struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
UUId string `json:"uuid"`
|
||||||
|
Language string `json:"language"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConnectionStatus struct {
|
||||||
|
From string `json:"from"`
|
||||||
|
To string `json:"to"`
|
||||||
|
Error string `json:"error"`
|
||||||
|
UUId string `json:"uuid"`
|
||||||
|
Event string `json:"event"`
|
||||||
|
}
|
||||||
62
model/app.go
62
model/app.go
@@ -7,32 +7,42 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ServerAppList struct {
|
type ServerAppList struct {
|
||||||
Id uint `gorm:"column:id;primary_key" json:"id"`
|
Id uint `gorm:"column:id;primary_key" json:"id"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
Tagline string `json:"tagline"`
|
Tagline string `json:"tagline"`
|
||||||
Tags Strings `gorm:"type:json" json:"tags"`
|
Tags Strings `gorm:"type:json" json:"tags"`
|
||||||
Icon string `json:"icon"`
|
Icon string `json:"icon"`
|
||||||
ScreenshotLink Strings `gorm:"type:json" json:"screenshot_link"`
|
ScreenshotLink Strings `gorm:"type:json" json:"screenshot_link"`
|
||||||
Category string `json:"category"`
|
Category string `json:"category"`
|
||||||
TcpPort uint `json:"tcp_port"`
|
CategoryFont string `json:"category_font"`
|
||||||
PortMap uint `json:"port_map"`
|
PortMap string `json:"port_map"`
|
||||||
ImageVersion string `json:"image_version"`
|
ImageVersion string `json:"image_version"`
|
||||||
Tip string `json:"tip"`
|
Tip string `json:"tip"`
|
||||||
Configures configures `gorm:"type:json" json:"configures"`
|
Envs EnvArray `json:"envs"`
|
||||||
NetworkModel string `json:"network_mode"`
|
Ports PortArray `json:"ports"`
|
||||||
Image string `json:"image"`
|
Volumes PathArray `json:"volumes"`
|
||||||
Index string `json:"index"`
|
Devices PathArray `json:"devices"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
NetworkModel string `json:"network_model"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
Image string `json:"image"`
|
||||||
State string `json:"state"`
|
Index string `json:"index"`
|
||||||
Author string `json:"author"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
MinMemory int `json:"min_memory"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
MinDisk int `json:"min_disk"`
|
State string `json:"state"`
|
||||||
MaxMemory uint64 `json:"max_memory"`
|
Author string `json:"author"`
|
||||||
Thumbnail string `json:"thumbnail"`
|
MinMemory int `json:"min_memory"`
|
||||||
Healthy string `json:"healthy"`
|
MinDisk int `json:"min_disk"`
|
||||||
Plugins Strings `json:"plugins"`
|
MaxMemory uint64 `json:"max_memory"`
|
||||||
|
Thumbnail string `json:"thumbnail"`
|
||||||
|
Healthy string `json:"healthy"`
|
||||||
|
Plugins Strings `json:"plugins"`
|
||||||
|
Origin string `json:"origin"`
|
||||||
|
Type int `json:"type"`
|
||||||
|
Developer string `json:"developer"`
|
||||||
|
HostName string `json:"host_name"`
|
||||||
|
Privileged bool `json:"privileged"`
|
||||||
|
CapAdd Strings `json:"cap_add"`
|
||||||
|
Cmd Strings `json:"cmd"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Ports struct {
|
type Ports struct {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ type ServerCategoryList struct {
|
|||||||
//CreatedAt time.Time `json:"created_at"`
|
//CreatedAt time.Time `json:"created_at"`
|
||||||
//
|
//
|
||||||
//UpdatedAt time.Time `json:"updated_at"`
|
//UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
Font string `json:"font"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Count uint `json:"count"`
|
Count uint `json:"count"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,12 +20,57 @@ type LSBLKModel struct {
|
|||||||
Format string `json:"format"`
|
Format string `json:"format"`
|
||||||
Health string `json:"health"`
|
Health string `json:"health"`
|
||||||
HotPlug bool `json:"hotplug"`
|
HotPlug bool `json:"hotplug"`
|
||||||
|
UUID string `json:"uuid"`
|
||||||
FSUsed string `json:"fsused"`
|
FSUsed string `json:"fsused"`
|
||||||
|
Temperature int `json:"temperature"`
|
||||||
Tran string `json:"tran"`
|
Tran string `json:"tran"`
|
||||||
MinIO uint64 `json:"min-io"`
|
MinIO uint64 `json:"min-io"`
|
||||||
UsedPercent float64 `json:"used_percent"`
|
UsedPercent float64 `json:"used_percent"`
|
||||||
|
Serial string `json:"serial"`
|
||||||
Children []LSBLKModel `json:"children"`
|
Children []LSBLKModel `json:"children"`
|
||||||
|
SubSystems string `json:"subsystems"`
|
||||||
//详情特有
|
//详情特有
|
||||||
StartSector uint64 `json:"start_sector,omitempty"`
|
StartSector uint64 `json:"start_sector,omitempty"`
|
||||||
|
Rota bool `json:"rota"` //true(hhd) false(ssd)
|
||||||
|
DiskType string `json:"disk_type"`
|
||||||
EndSector uint64 `json:"end_sector,omitempty"`
|
EndSector uint64 `json:"end_sector,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Drive struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Size uint64 `json:"size"`
|
||||||
|
Model string `json:"model"`
|
||||||
|
Health string `json:"health"`
|
||||||
|
Temperature int `json:"temperature"`
|
||||||
|
DiskType string `json:"disk_type"`
|
||||||
|
NeedFormat bool `json:"need_format"`
|
||||||
|
Serial string `json:"serial"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DriveUSB struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Size uint64 `json:"size"`
|
||||||
|
Used uint64 `json:"use"`
|
||||||
|
Model string `json:"model"`
|
||||||
|
Mount bool `json:"mount"` //是否完全挂载
|
||||||
|
Avail uint64 `json:"avail"` //可用空间
|
||||||
|
}
|
||||||
|
|
||||||
|
type Storage struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
MountPoint string `json:"mountpoint"`
|
||||||
|
Size string `json:"size"`
|
||||||
|
Avail string `json:"avail"` //可用空间
|
||||||
|
Type string `json:"type"`
|
||||||
|
CreatedAt int64 `json:"create_at"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
DriveName string `json:"drive_name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Summary struct {
|
||||||
|
Size uint64 `json:"size"`
|
||||||
|
Avail uint64 `json:"avail"` //可用空间
|
||||||
|
Health bool `json:"health"`
|
||||||
|
Used uint64 `json:"used"`
|
||||||
|
}
|
||||||
|
|||||||
8
model/docker.go
Normal file
8
model/docker.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type DockerStatsModel struct {
|
||||||
|
Icon string `json:"icon"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Data interface{} `json:"data"`
|
||||||
|
Pre interface{} `json:"pre"`
|
||||||
|
}
|
||||||
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"`
|
||||||
|
}
|
||||||
@@ -17,20 +17,22 @@ type UdpPorts struct {
|
|||||||
/*******************使用gorm支持json************************************/
|
/*******************使用gorm支持json************************************/
|
||||||
|
|
||||||
type PortMap struct {
|
type PortMap struct {
|
||||||
ContainerPort string `json:"container,omitempty"`
|
ContainerPort string `json:"container"`
|
||||||
CommendPort string `json:"host,omitempty"`
|
CommendPort string `json:"host"`
|
||||||
Protocol string `json:"protocol"`
|
Protocol string `json:"protocol"`
|
||||||
|
Desc string `json:"desc"`
|
||||||
|
Type int `json:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PortArrey []PortMap
|
type PortArray []PortMap
|
||||||
|
|
||||||
// Value 实现方法
|
// Value 实现方法
|
||||||
func (p PortArrey) Value() (driver.Value, error) {
|
func (p PortArray) Value() (driver.Value, error) {
|
||||||
return json.Marshal(p)
|
return json.Marshal(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan 实现方法
|
// Scan 实现方法
|
||||||
func (p *PortArrey) Scan(input interface{}) error {
|
func (p *PortArray) Scan(input interface{}) error {
|
||||||
return json.Unmarshal(input.([]byte), p)
|
return json.Unmarshal(input.([]byte), p)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,20 +43,22 @@ func (p *PortArrey) Scan(input interface{}) error {
|
|||||||
type Env struct {
|
type Env struct {
|
||||||
Name string `json:"container"`
|
Name string `json:"container"`
|
||||||
Value string `json:"host"`
|
Value string `json:"host"`
|
||||||
|
Desc string `json:"desc"`
|
||||||
|
Type int `json:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type JSON json.RawMessage
|
type JSON json.RawMessage
|
||||||
|
|
||||||
type EnvArrey []Env
|
type EnvArray []Env
|
||||||
|
|
||||||
// Value 实现方法
|
// Value 实现方法
|
||||||
func (p EnvArrey) Value() (driver.Value, error) {
|
func (p EnvArray) Value() (driver.Value, error) {
|
||||||
return json.Marshal(p)
|
return json.Marshal(p)
|
||||||
//return .MarshalJSON()
|
//return .MarshalJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan 实现方法
|
// Scan 实现方法
|
||||||
func (p *EnvArrey) Scan(input interface{}) error {
|
func (p *EnvArray) Scan(input interface{}) error {
|
||||||
return json.Unmarshal(input.([]byte), p)
|
return json.Unmarshal(input.([]byte), p)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,17 +69,19 @@ func (p *EnvArrey) Scan(input interface{}) error {
|
|||||||
type PathMap struct {
|
type PathMap struct {
|
||||||
ContainerPath string `json:"container"`
|
ContainerPath string `json:"container"`
|
||||||
Path string `json:"host"`
|
Path string `json:"host"`
|
||||||
|
Type int `json:"type"`
|
||||||
|
Desc string `json:"desc"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PathArrey []PathMap
|
type PathArray []PathMap
|
||||||
|
|
||||||
// Value 实现方法
|
// Value 实现方法
|
||||||
func (p PathArrey) Value() (driver.Value, error) {
|
func (p PathArray) Value() (driver.Value, error) {
|
||||||
return json.Marshal(p)
|
return json.Marshal(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan 实现方法
|
// Scan 实现方法
|
||||||
func (p *PathArrey) Scan(input interface{}) error {
|
func (p *PathArray) Scan(input interface{}) error {
|
||||||
return json.Unmarshal(input.([]byte), p)
|
return json.Unmarshal(input.([]byte), p)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,17 +109,21 @@ type CustomizationPostData struct {
|
|||||||
Index string `json:"index"`
|
Index string `json:"index"`
|
||||||
Icon string `json:"icon"`
|
Icon string `json:"icon"`
|
||||||
Image string `json:"image"`
|
Image string `json:"image"`
|
||||||
Envs EnvArrey `json:"envs"`
|
Envs EnvArray `json:"envs"`
|
||||||
Ports PortArrey `json:"ports"`
|
Ports PortArray `json:"ports"`
|
||||||
Volumes PathArrey `json:"volumes"`
|
Volumes PathArray `json:"volumes"`
|
||||||
Devices PathArrey `json:"devices"`
|
Devices PathArray `json:"devices"`
|
||||||
//Port string `json:"port,omitempty"`
|
//Port string `json:"port,omitempty"`
|
||||||
PortMap string `json:"port_map"`
|
PortMap string `json:"port_map"`
|
||||||
CpuShares int64 `json:"cpu_shares"`
|
CpuShares int64 `json:"cpu_shares"`
|
||||||
Memory int64 `json:"memory"`
|
Memory int64 `json:"memory"`
|
||||||
Restart string `json:"restart"`
|
Restart string `json:"restart"`
|
||||||
EnableUPNP bool `json:"enable_upnp"`
|
EnableUPNP bool `json:"enable_upnp"`
|
||||||
Label string `json:"label"`
|
Label string `json:"label"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
Position bool `json:"position"`
|
Position bool `json:"position"`
|
||||||
|
HostName string `json:"host_name"`
|
||||||
|
Privileged bool `json:"privileged"`
|
||||||
|
CapAdd []string `json:"cap_add"`
|
||||||
|
Cmd []string `json:"cmd"`
|
||||||
}
|
}
|
||||||
|
|||||||
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"`
|
||||||
|
}
|
||||||
54
model/person.go
Normal file
54
model/person.go
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type PersionModel struct {
|
||||||
|
Token string `json:"token"`
|
||||||
|
Ips []string `json:"ips"`
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//记录链接状态
|
||||||
|
type ConnectState struct {
|
||||||
|
From string `json:"from"`
|
||||||
|
To string `json:"to"`
|
||||||
|
Type string `json:"type"` //current state 1:ready 2:ok
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
UUId string `json:"uuid"` //对接标识
|
||||||
|
}
|
||||||
|
type MessageModel struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Data interface{} `json:"data"`
|
||||||
|
UUId string `json:"uuid"`
|
||||||
|
From string `json:"from"`
|
||||||
|
To string `json:"to"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TranFileModel struct {
|
||||||
|
Hash string `json:"hash"` //Verify current fragment integrity
|
||||||
|
Length int `json:"length"`
|
||||||
|
Index int `json:"index"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//需要获取文件详情
|
||||||
|
type FileDetailModel struct {
|
||||||
|
Path string `json:"path"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回文件详情
|
||||||
|
type FileSummaryModel struct {
|
||||||
|
Hash string `json:"hash"` //Verify file
|
||||||
|
Name string `json:"name"`
|
||||||
|
BlockSize int `json:"block_size"`
|
||||||
|
Length int `json:"length"`
|
||||||
|
Size int64 `json:"size"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FriendsModel struct {
|
||||||
|
Id uint `gorm:"column:id;primary_key" json:"id"`
|
||||||
|
NickName string `json:"nick_name"`
|
||||||
|
Desc string `json:"desc"`
|
||||||
|
ShareId string `json:"share_id"`
|
||||||
|
}
|
||||||
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"`
|
||||||
|
}
|
||||||
@@ -16,13 +16,20 @@ type UserModel struct {
|
|||||||
Email string
|
Email string
|
||||||
Description string
|
Description string
|
||||||
Initialized bool
|
Initialized bool
|
||||||
|
Avatar string
|
||||||
|
NickName string
|
||||||
}
|
}
|
||||||
|
|
||||||
//服务配置
|
//服务配置
|
||||||
type ServerModel struct {
|
type ServerModel struct {
|
||||||
HttpPort string
|
HttpPort string
|
||||||
RunMode string
|
RunMode string
|
||||||
ServerApi string
|
ServerApi string
|
||||||
|
LockAccount bool
|
||||||
|
Handshake string
|
||||||
|
Token string
|
||||||
|
UDPPort string
|
||||||
|
USBAutoMount string
|
||||||
}
|
}
|
||||||
|
|
||||||
//服务配置
|
//服务配置
|
||||||
@@ -35,6 +42,7 @@ type APPModel struct {
|
|||||||
TimeFormat string
|
TimeFormat string
|
||||||
DateFormat string
|
DateFormat string
|
||||||
ProjectPath string
|
ProjectPath string
|
||||||
|
RootPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
//公共返回模型
|
//公共返回模型
|
||||||
@@ -44,13 +52,6 @@ type Result struct {
|
|||||||
Data interface{} `json:"data" example:"返回结果"`
|
Data interface{} `json:"data" example:"返回结果"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//zeritier相关
|
|
||||||
type ZeroTierModel struct {
|
|
||||||
UserName string
|
|
||||||
PWD string
|
|
||||||
Token string
|
|
||||||
}
|
|
||||||
|
|
||||||
//redis配置文件
|
//redis配置文件
|
||||||
type RedisModel struct {
|
type RedisModel struct {
|
||||||
Host string
|
Host string
|
||||||
@@ -64,4 +65,16 @@ type SystemConfig struct {
|
|||||||
ConfigStr string `json:"config_str"`
|
ConfigStr string `json:"config_str"`
|
||||||
WidgetList string `json:"widget_list"`
|
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"`
|
||||||
|
Analyse string `json:"analyse"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CasaOSGlobalVariables struct {
|
||||||
|
AppChange bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileSetting struct {
|
||||||
|
ShareDir []string `json:"share_dir" delim:"|"`
|
||||||
|
DownloadDir string `json:"download_dir"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
8
model/system_app/sync.go
Normal file
8
model/system_app/sync.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package system_app
|
||||||
|
|
||||||
|
import "encoding/xml"
|
||||||
|
|
||||||
|
type SyncConfig struct {
|
||||||
|
XMLName xml.Name `xml:"configuration"`
|
||||||
|
Key string `xml:"gui>apikey"`
|
||||||
|
}
|
||||||
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"`
|
||||||
|
}
|
||||||
@@ -1,7 +1,13 @@
|
|||||||
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"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,14 +25,15 @@ var AppInfo = &model.APPModel{}
|
|||||||
//redis相关配置
|
//redis相关配置
|
||||||
var RedisInfo = &model.RedisModel{}
|
var RedisInfo = &model.RedisModel{}
|
||||||
|
|
||||||
//zerotier相关
|
|
||||||
var ZeroTierInfo = &model.ZeroTierModel{}
|
|
||||||
|
|
||||||
//server相关
|
//server相关
|
||||||
var ServerInfo = &model.ServerModel{}
|
var ServerInfo = &model.ServerModel{}
|
||||||
|
|
||||||
var SystemConfigInfo = &model.SystemConfig{}
|
var SystemConfigInfo = &model.SystemConfig{}
|
||||||
|
|
||||||
|
var CasaOSGlobalVariables = &model.CasaOSGlobalVariables{}
|
||||||
|
|
||||||
|
var FileSettingInfo = &model.FileSetting{}
|
||||||
|
|
||||||
var Cfg *ini.File
|
var Cfg *ini.File
|
||||||
|
|
||||||
//初始化设置,获取系统的部分信息。
|
//初始化设置,获取系统的部分信息。
|
||||||
@@ -52,10 +53,10 @@ func InitSetup(config string) {
|
|||||||
|
|
||||||
mapTo("user", UserInfo)
|
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)
|
||||||
SystemConfigInfo.ConfigPath = configDir
|
SystemConfigInfo.ConfigPath = configDir
|
||||||
// AppInfo.ProjectPath = getCurrentDirectory() //os.Getwd()
|
// AppInfo.ProjectPath = getCurrentDirectory() //os.Getwd()
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,30 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
import (
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
|
)
|
||||||
|
|
||||||
//检查目录是否存在
|
//检查目录是否存在
|
||||||
func mkdirDATAAll() {
|
func mkdirDATAAll() {
|
||||||
dirArray := [7]string{"/DATA/AppData", "/DATA/Documents", "/DATA/Downloads", "/DATA/Gallery", "/DATA/Media/Movies", "/DATA/Media/TV Shows", "/DATA/Media/Music"}
|
sysType := runtime.GOOS
|
||||||
|
var dirArray []string
|
||||||
|
if sysType == "linux" {
|
||||||
|
dirArray = []string{"/DATA/AppData", "/DATA/Documents", "/DATA/Downloads", "/DATA/Gallery", "/DATA/Media/Movies", "/DATA/Media/TV Shows", "/DATA/Media/Music"}
|
||||||
|
}
|
||||||
|
|
||||||
|
if sysType == "windows" {
|
||||||
|
dirArray = []string{"C:\\CasaOS\\DATA\\AppData", "C:\\CasaOS\\DATA\\Documents", "C:\\CasaOS\\DATA\\Downloads", "C:\\CasaOS\\DATA\\Gallery", "C:\\CasaOS\\DATA\\Media/Movies", "C:\\CasaOS\\DATA\\Media\\TV Shows", "C:\\CasaOS\\DATA\\Media\\Music"}
|
||||||
|
}
|
||||||
|
if sysType == "darwin" {
|
||||||
|
dirArray = []string{"./CasaOS/DATA/AppData", "./CasaOS/DATA/Documents", "./CasaOS/DATA/Downloads", "./CasaOS/DATA/Gallery", "./CasaOS/DATA/Media/Movies", "./CasaOS/DATA/Media/TV Shows", "./CasaOS/DATA/Media/Music"}
|
||||||
|
}
|
||||||
|
|
||||||
for _, v := range dirArray {
|
for _, v := range dirArray {
|
||||||
file.IsNotExistMkDir(v)
|
file.IsNotExistMkDir(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateSetup() {
|
func UpdateSetup() {
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
package docker
|
package docker
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
func GetDir(id, envName string) string {
|
func GetDir(id, envName string) string {
|
||||||
var path string
|
|
||||||
switch envName {
|
if strings.Contains(envName, "$AppID") && len(id) > 0 {
|
||||||
case "/config":
|
return strings.ReplaceAll(envName, "$AppID", id)
|
||||||
path = "/oasis/app_data/" + id + "/"
|
|
||||||
default:
|
|
||||||
//path = "/media"
|
|
||||||
}
|
}
|
||||||
return path
|
return envName
|
||||||
}
|
}
|
||||||
|
|||||||
10
pkg/docker/volumes_test.go
Normal file
10
pkg/docker/volumes_test.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package docker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetDir(t *testing.T) {
|
||||||
|
fmt.Println(GetDir("", "config"))
|
||||||
|
}
|
||||||
@@ -6,7 +6,6 @@ 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(
|
||||||
|
|||||||
51
pkg/quic_helper/config.go
Normal file
51
pkg/quic_helper/config.go
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package quic_helper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/pem"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/lucas-clemente/quic-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Setup a bare-bones TLS config for the server
|
||||||
|
func GetGenerateTLSConfig(token string) *tls.Config {
|
||||||
|
key, err := rsa.GenerateKey(rand.Reader, 1024)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
template := x509.Certificate{SerialNumber: big.NewInt(1)}
|
||||||
|
certDER, err := x509.CreateCertificate(rand.Reader, &template, &template, &key.PublicKey, key)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)})
|
||||||
|
certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER})
|
||||||
|
|
||||||
|
tlsCert, err := tls.X509KeyPair(certPEM, keyPEM)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return &tls.Config{
|
||||||
|
Certificates: []tls.Certificate{tlsCert},
|
||||||
|
NextProtos: []string{token},
|
||||||
|
SessionTicketsDisabled: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func GetClientTlsConfig(otherToken string) *tls.Config {
|
||||||
|
return &tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
NextProtos: []string{otherToken},
|
||||||
|
SessionTicketsDisabled: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetQUICConfig() *quic.Config {
|
||||||
|
return &quic.Config{
|
||||||
|
ConnectionIDLength: 4,
|
||||||
|
KeepAlive: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,11 +2,12 @@ package sqlite
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"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"
|
"gorm.io/driver/sqlite"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var gdb *gorm.DB
|
var gdb *gorm.DB
|
||||||
@@ -30,7 +31,7 @@ func GetDb(projectPath string) *gorm.DB {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
gdb = db
|
gdb = db
|
||||||
err = db.AutoMigrate(&model2.TaskDBModel{}, &model2.AppNotify{}, &model2.AppListDBModel{})
|
err = db.AutoMigrate(&model2.TaskDBModel{}, &model2.AppNotify{}, &model2.AppListDBModel{}, &model2.SerialDisk{}, model2.PersonDownloadDBModel{}, model2.FriendModel{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("检查和创建数据库出错", err)
|
fmt.Println("检查和创建数据库出错", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetCtrlUrl(host,device string) string {
|
func GetCtrlUrl(host, device string) string {
|
||||||
request := ctrlUrlRequest(host, device)
|
request := ctrlUrlRequest(host, device)
|
||||||
response, _ := http.DefaultClient.Do(request)
|
response, _ := http.DefaultClient.Do(request)
|
||||||
resultBody, _ := ioutil.ReadAll(response.Body)
|
resultBody, _ := ioutil.ReadAll(response.Body)
|
||||||
@@ -86,4 +86,4 @@ func resolve(resultStr string) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return controlURL
|
return controlURL
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,21 +22,21 @@ func send() (string, error) {
|
|||||||
"ST: urn:schemas-upnp-org:service:WANIPConnection:1\r\n" +
|
"ST: urn:schemas-upnp-org:service:WANIPConnection:1\r\n" +
|
||||||
"MAN: \"ssdp:discover\"\r\n" + "MX: 3\r\n\r\n"
|
"MAN: \"ssdp:discover\"\r\n" + "MX: 3\r\n\r\n"
|
||||||
var conn *net.UDPConn
|
var conn *net.UDPConn
|
||||||
remotAddr, err := net.ResolveUDPAddr("udp", "239.255.255.250:1900")
|
remoteAddr, err := net.ResolveUDPAddr("udp", "239.255.255.250:1900")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.New("组播地址格式不正确")
|
return "", errors.New("组播地址格式不正确")
|
||||||
}
|
}
|
||||||
locaAddr, err := net.ResolveUDPAddr("udp", ip_helper2.GetLoclIp()+":")
|
localAddr, err := net.ResolveUDPAddr("udp", ip_helper2.GetLoclIp()+":")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.New("本地ip地址格式不正确")
|
return "", errors.New("本地ip地址格式不正确")
|
||||||
}
|
}
|
||||||
conn, err = net.ListenUDP("udp", locaAddr)
|
conn, err = net.ListenUDP("udp", localAddr)
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.New("监听udp出错")
|
return "", errors.New("监听udp出错")
|
||||||
}
|
}
|
||||||
_, err = conn.WriteToUDP([]byte(str), remotAddr)
|
_, err = conn.WriteToUDP([]byte(str), remoteAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.New("发送msg到组播地址出错")
|
return "", errors.New("发送msg到组播地址出错")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,4 +5,4 @@ import "testing"
|
|||||||
func TestGateway(t *testing.T) {
|
func TestGateway(t *testing.T) {
|
||||||
|
|
||||||
Gateway()
|
Gateway()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,40 +2,37 @@ package upnp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
//
|
//
|
||||||
////添加一个端口映射
|
////添加一个端口映射
|
||||||
func (n *Upnp)AddPortMapping(localPort, remotePort int, protocol string) (err error) {
|
func (n *Upnp) AddPortMapping(localPort, remotePort int, protocol string) (err error) {
|
||||||
defer func(err error) {
|
defer func() {
|
||||||
if errTemp := recover(); errTemp != nil {
|
if errTemp := recover(); errTemp != nil {
|
||||||
//log.Println("upnp模块报错了", errTemp)
|
loger2.NewOLoger().Error("upnp模块报错了", errTemp)
|
||||||
err = errTemp.(error)
|
|
||||||
}
|
}
|
||||||
}(err)
|
}()
|
||||||
if issuccess := addSend(localPort, remotePort, protocol,n.GatewayHost, n.CtrlUrl,n.LocalHost); issuccess {
|
|
||||||
|
if isSuccess := addSend(localPort, remotePort, protocol, n.GatewayHost, n.CtrlUrl, n.LocalHost); isSuccess {
|
||||||
return nil
|
return nil
|
||||||
} else {
|
} else {
|
||||||
return errors.New("添加一个端口映射失败")
|
return errors.New("添加一个端口映射失败")
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func addSend(localPort, remotePort int, protocol, host, ctrUrl,localHost string) bool {
|
func addSend(localPort, remotePort int, protocol, host, ctrUrl, localHost string) bool {
|
||||||
request := addRequest(localPort, remotePort, protocol, host, ctrUrl,localHost)
|
request := addRequest(localPort, remotePort, protocol, host, ctrUrl, localHost)
|
||||||
response, _ := http.DefaultClient.Do(request)
|
response, _ := http.DefaultClient.Do(request)
|
||||||
defer response.Body.Close()
|
defer response.Body.Close()
|
||||||
//resultBody, _ := ioutil.ReadAll(response.Body)
|
//resultBody, _ := ioutil.ReadAll(response.Body)
|
||||||
//fmt.Println(string(resultBody))
|
//fmt.Println(string(resultBody))
|
||||||
if response.StatusCode == 200 {
|
return response.StatusCode == 200
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Node struct {
|
type Node struct {
|
||||||
@@ -45,7 +42,7 @@ type Node struct {
|
|||||||
Child []Node
|
Child []Node
|
||||||
}
|
}
|
||||||
|
|
||||||
func addRequest(localPort, remotePort int, protocol string, gatewayHost, ctlUrl,localHost string) *http.Request {
|
func addRequest(localPort, remotePort int, protocol string, gatewayHost, ctlUrl, localHost string) *http.Request {
|
||||||
//请求头
|
//请求头
|
||||||
header := http.Header{}
|
header := http.Header{}
|
||||||
header.Set("Accept", "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2")
|
header.Set("Accept", "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2")
|
||||||
@@ -109,27 +106,25 @@ func (n *Node) BuildXML() string {
|
|||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Upnp)DelPortMapping(remotePort int, protocol string) bool {
|
func (n *Upnp) DelPortMapping(remotePort int, protocol string) bool {
|
||||||
issuccess := delSendSend(remotePort, protocol,n.GatewayHost,n.CtrlUrl)
|
isSuccess := delSendSend(remotePort, protocol, n.GatewayHost, n.CtrlUrl)
|
||||||
if issuccess {
|
if isSuccess {
|
||||||
//this.MappingPort.delMapping(remotePort, protocol)
|
//this.MappingPort.delMapping(remotePort, protocol)
|
||||||
//fmt.Println("删除了一个端口映射: remote:", remotePort)
|
//fmt.Println("删除了一个端口映射: remote:", remotePort)
|
||||||
}
|
}
|
||||||
return issuccess
|
return isSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
func delSendSend(remotePort int, protocol,host,ctlUrl string) bool {
|
func delSendSend(remotePort int, protocol, host, ctlUrl string) bool {
|
||||||
delrequest := delbuildRequest(remotePort, protocol,host,ctlUrl)
|
delrequest := delbuildRequest(remotePort, protocol, host, ctlUrl)
|
||||||
response, _ := http.DefaultClient.Do(delrequest)
|
response, _ := http.DefaultClient.Do(delrequest)
|
||||||
//resultBody, _ := ioutil.ReadAll(response.Body)
|
//resultBody, _ := ioutil.ReadAll(response.Body)
|
||||||
defer response.Body.Close()
|
defer response.Body.Close()
|
||||||
if response.StatusCode == 200 {
|
|
||||||
// log.Println(string(resultBody))
|
return response.StatusCode == 200
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
func delbuildRequest(remotePort int, protocol,host,ctlUrl string) *http.Request {
|
|
||||||
|
func delbuildRequest(remotePort int, protocol, host, ctlUrl string) *http.Request {
|
||||||
//请求头
|
//请求头
|
||||||
header := http.Header{}
|
header := http.Header{}
|
||||||
header.Set("Accept", "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2")
|
header.Set("Accept", "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2")
|
||||||
@@ -160,4 +155,4 @@ func delbuildRequest(remotePort int, protocol,host,ctlUrl string) *http.Request
|
|||||||
request.Header = header
|
request.Header = header
|
||||||
request.Header.Set("Content-Length", strconv.Itoa(len([]byte(bodyStr))))
|
request.Header.Set("Content-Length", strconv.Itoa(len([]byte(bodyStr))))
|
||||||
return request
|
return request
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import (
|
|||||||
|
|
||||||
type Upnp struct {
|
type Upnp struct {
|
||||||
LocalHost string `json:"local_host"`
|
LocalHost string `json:"local_host"`
|
||||||
GatewayName string `json:"gateway_name"` //网关名称
|
GatewayName string `json:"gateway_name"` //网关名称
|
||||||
GatewayHost string `json:"gateway_host"` //网关ip和端口
|
GatewayHost string `json:"gateway_host"` //网关ip和端口
|
||||||
DeviceDescUrl string `json:"device_desc_url"` //设备描述url
|
DeviceDescUrl string `json:"device_desc_url"` //设备描述url
|
||||||
CtrlUrl string `json:"ctrl_url"` //控制请求url
|
CtrlUrl string `json:"ctrl_url"` //控制请求url
|
||||||
}
|
}
|
||||||
|
|
||||||
func Testaaa() {
|
func Testaaa() {
|
||||||
@@ -23,4 +23,3 @@ func Testaaa() {
|
|||||||
fmt.Println("gateway ip address: ", upnpMan.Gateway.Host)
|
fmt.Println("gateway ip address: ", upnpMan.Gateway.Host)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,4 +6,4 @@ import (
|
|||||||
|
|
||||||
func TestTestaaa(t *testing.T) {
|
func TestTestaaa(t *testing.T) {
|
||||||
(Testaaa())
|
(Testaaa())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,11 @@ package command
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func OnlyExec(cmdStr string) {
|
func OnlyExec(cmdStr string) {
|
||||||
@@ -75,6 +77,7 @@ func ExecResultStr(cmdStr string) string {
|
|||||||
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
|
||||||
@@ -84,7 +87,26 @@ func ExecLSBLK() []byte {
|
|||||||
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()
|
||||||
|
}
|
||||||
|
|||||||
26
pkg/utils/env_helper/env.go
Normal file
26
pkg/utils/env_helper/env.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package env_helper
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
func ReplaceDefaultENV(key, tz string) string {
|
||||||
|
temp := ""
|
||||||
|
switch key {
|
||||||
|
case "$DefaultPassword":
|
||||||
|
temp = "casaos"
|
||||||
|
case "$DefaultUserName":
|
||||||
|
temp = "admin"
|
||||||
|
|
||||||
|
case "$PUID":
|
||||||
|
temp = "1000"
|
||||||
|
case "$PGID":
|
||||||
|
temp = "1000"
|
||||||
|
case "$TZ":
|
||||||
|
temp = tz
|
||||||
|
}
|
||||||
|
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,17 @@
|
|||||||
package file
|
package file
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
path2 "path"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetSize get the file size
|
// GetSize get the file size
|
||||||
@@ -35,7 +41,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
|
||||||
}
|
}
|
||||||
@@ -136,6 +142,21 @@ 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, 0666)
|
||||||
|
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 == true {
|
||||||
@@ -146,3 +167,169 @@ func IsNotExistCreateFile(src string) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ReadFullFile(path string) []byte {
|
||||||
|
file, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return []byte("")
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
content, err := ioutil.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
return []byte("")
|
||||||
|
}
|
||||||
|
return content
|
||||||
|
}
|
||||||
|
|
||||||
|
// File copies a single file from src to dst
|
||||||
|
func CopyFile(src, dst 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 += "/"
|
||||||
|
}
|
||||||
|
dstPath := dst
|
||||||
|
dst += lastPath
|
||||||
|
for i := 0; Exists(dst); i++ {
|
||||||
|
name := strings.Split(lastPath, ".")
|
||||||
|
nameIndex := 0
|
||||||
|
if len(name) > 2 {
|
||||||
|
nameIndex = len(name) - 2
|
||||||
|
}
|
||||||
|
name[nameIndex] = name[nameIndex] + "(Copy)"
|
||||||
|
dst = dstPath
|
||||||
|
for _, v := range name {
|
||||||
|
dst += v + "."
|
||||||
|
}
|
||||||
|
dst = strings.TrimSuffix(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) 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); 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 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); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err = CopyFile(srcfp, dstfp); 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
|
||||||
|
}
|
||||||
|
IsNotExistCreateFile(fullPath)
|
||||||
|
file, err := os.OpenFile(fullPath,
|
||||||
|
os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
|
||||||
|
0666,
|
||||||
|
)
|
||||||
|
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
|
||||||
|
|
||||||
|
IsNotExistCreateFile(fullPath)
|
||||||
|
|
||||||
|
file, _ := os.OpenFile(fullPath,
|
||||||
|
os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
|
||||||
|
0666,
|
||||||
|
)
|
||||||
|
defer file.Close()
|
||||||
|
bufferedWriter := bufio.NewWriter(file)
|
||||||
|
for i := 0; i < length+startPoint; i++ {
|
||||||
|
data, err := ioutil.ReadFile(dir + "/" + strconv.Itoa(i+startPoint))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = bufferedWriter.Write(data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bufferedWriter.Flush()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package httper
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -16,9 +17,9 @@ import (
|
|||||||
//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)
|
||||||
}
|
}
|
||||||
@@ -53,10 +54,13 @@ func Get(url string, head map[string]string) (response string) {
|
|||||||
//发送POST请求
|
//发送POST请求
|
||||||
//url:请求地址,data:POST请求提交的数据,contentType:请求体格式,如:application/json
|
//url:请求地址,data:POST请求提交的数据,contentType:请求体格式,如:application/json
|
||||||
//content:请求放回的内容
|
//content:请求放回的内容
|
||||||
func Post(url string, data interface{}, contentType string) (content string) {
|
func Post(url string, data []byte, contentType string, head map[string]string) (content string) {
|
||||||
jsonStr, _ := json.Marshal(data)
|
|
||||||
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
|
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 {
|
||||||
|
req.Header.Add(k, v)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@@ -64,7 +68,8 @@ func Post(url string, data interface{}, contentType string) (content 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()
|
||||||
|
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
package utils
|
|
||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
file2 "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
file2 "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -11,14 +11,23 @@ const (
|
|||||||
PWD_IS_EMPTY = 10002
|
PWD_IS_EMPTY = 10002
|
||||||
|
|
||||||
PWD_INVALID_OLD = 10003
|
PWD_INVALID_OLD = 10003
|
||||||
|
ACCOUNT_LOCK = 10004
|
||||||
//system
|
//system
|
||||||
DIR_ALREADY_EXISTS = 20001
|
DIR_ALREADY_EXISTS = 20001
|
||||||
FILE_ALREADY_EXISTS = 20002
|
FILE_ALREADY_EXISTS = 20002
|
||||||
FILE_OR_DIR_EXISTS = 20003
|
FILE_OR_DIR_EXISTS = 20003
|
||||||
|
PORT_IS_OCCUPIED = 20004
|
||||||
|
|
||||||
//zerotier
|
//zerotier
|
||||||
GET_TOKEN_ERROR = 30001
|
GET_TOKEN_ERROR = 30001
|
||||||
|
|
||||||
|
//disk
|
||||||
|
NAME_NOT_AVAILABLE = 40001
|
||||||
|
DISK_NEEDS_FORMAT = 40002
|
||||||
|
DISK_BUSYING = 40003
|
||||||
|
REMOVE_MOUNT_POINT_ERROR = 40004
|
||||||
|
FORMAT_ERROR = 40005
|
||||||
|
|
||||||
//app
|
//app
|
||||||
UNINSTALL_APP_ERROR = 50001
|
UNINSTALL_APP_ERROR = 50001
|
||||||
PULL_IMAGE_ERROR = 50002
|
PULL_IMAGE_ERROR = 50002
|
||||||
@@ -27,40 +36,69 @@ const (
|
|||||||
//file
|
//file
|
||||||
FILE_DOES_NOT_EXIST = 60001
|
FILE_DOES_NOT_EXIST = 60001
|
||||||
FILE_READ_ERROR = 60002
|
FILE_READ_ERROR = 60002
|
||||||
|
FILE_DELETE_ERROR = 60003
|
||||||
|
DIR_NOT_EXISTS = 60004
|
||||||
|
|
||||||
//shortcuts
|
//shortcuts
|
||||||
SHORTCUTS_URL_ERROR = 70001
|
SHORTCUTS_URL_ERROR = 70001
|
||||||
|
|
||||||
|
//person
|
||||||
|
PERSON_REMOTE_ERROR = 80001
|
||||||
|
PERSON_DOWN_NOT_EXIST = 80002
|
||||||
|
PERSON_EXIST_DOWNLOAD = 80003
|
||||||
|
PERSON_NOT_EXIST_USER = 80004
|
||||||
|
PERSON_EXIST_FRIEND = 80005
|
||||||
|
PERSON_MYSELF = 80006
|
||||||
)
|
)
|
||||||
|
|
||||||
var MsgFlags = map[int]string{
|
var MsgFlags = map[int]string{
|
||||||
SUCCESS: "ok",
|
SUCCESS: "ok",
|
||||||
ERROR: "fail",
|
ERROR: "fail",
|
||||||
INVALID_PARAMS: "Invalid params",
|
INVALID_PARAMS: "Parameters Error",
|
||||||
ERROR_AUTH_TOKEN: "error auth token",
|
ERROR_AUTH_TOKEN: "Error auth token",
|
||||||
|
|
||||||
//user
|
//user
|
||||||
PWD_INVALID: "Password invalid",
|
PWD_INVALID: "Invalid password",
|
||||||
PWD_IS_EMPTY: "Password is empty",
|
PWD_IS_EMPTY: "Password is empty",
|
||||||
PWD_INVALID_OLD: "Old Password invalid",
|
PWD_INVALID_OLD: "Invalid old password",
|
||||||
|
ACCOUNT_LOCK: "Account is locked",
|
||||||
|
|
||||||
//system
|
//system
|
||||||
DIR_ALREADY_EXISTS: "Directory already exists",
|
DIR_ALREADY_EXISTS: "Folder already exists",
|
||||||
FILE_ALREADY_EXISTS: "File already exists",
|
FILE_ALREADY_EXISTS: "File already exists",
|
||||||
FILE_OR_DIR_EXISTS: "File or directory already exists",
|
FILE_OR_DIR_EXISTS: "File or folder already exists",
|
||||||
|
PORT_IS_OCCUPIED: "Port is occupied",
|
||||||
|
|
||||||
//zerotier
|
//zerotier
|
||||||
GET_TOKEN_ERROR: "Get token error,Please log in to zerotier's official website to confirm whether the account is available",
|
GET_TOKEN_ERROR: "Get token error,Please log in to zerotier's official website to confirm whether the account is available",
|
||||||
|
|
||||||
//app
|
//app
|
||||||
UNINSTALL_APP_ERROR: "uninstall app error",
|
UNINSTALL_APP_ERROR: "Error uninstalling app",
|
||||||
PULL_IMAGE_ERROR: "pull image error",
|
PULL_IMAGE_ERROR: "Error pulling image",
|
||||||
DEVICE_NOT_EXIST: "device not exist",
|
DEVICE_NOT_EXIST: "Device does not exist",
|
||||||
|
|
||||||
|
//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",
|
||||||
|
|
||||||
//
|
//
|
||||||
FILE_DOES_NOT_EXIST: "file does not exist",
|
FILE_DOES_NOT_EXIST: "File does not exist",
|
||||||
|
|
||||||
FILE_READ_ERROR: "file read error",
|
DIR_NOT_EXISTS: "Directory does not exist",
|
||||||
SHORTCUTS_URL_ERROR: "url error",
|
|
||||||
|
FILE_READ_ERROR: "File read error",
|
||||||
|
FILE_DELETE_ERROR: "Delete error",
|
||||||
|
SHORTCUTS_URL_ERROR: "URL error",
|
||||||
|
|
||||||
|
PERSON_REMOTE_ERROR: "Remote connection error",
|
||||||
|
PERSON_DOWN_NOT_EXIST: "Download record does not exist",
|
||||||
|
PERSON_EXIST_DOWNLOAD: "The same download task exists",
|
||||||
|
PERSON_EXIST_FRIEND: "Friend already exist",
|
||||||
|
PERSON_NOT_EXIST_USER: "User does not exist",
|
||||||
|
PERSON_MYSELF: "You can not add yourself",
|
||||||
}
|
}
|
||||||
|
|
||||||
//获取错误信息
|
//获取错误信息
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ func IsPortAvailable(port int, t string) bool {
|
|||||||
uc, err := net.ListenUDP("udp", sadd)
|
uc, err := net.ListenUDP("udp", sadd)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
defer uc.Close()
|
defer uc.Close()
|
||||||
|
|||||||
@@ -6,5 +6,5 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestRandomString(t *testing.T) {
|
func TestRandomString(t *testing.T) {
|
||||||
fmt.Println(RandomString(6,true))
|
fmt.Println(RandomString(6, true))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package sort
|
package sort
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 数据集类型, 与上一篇排序文章(多字段单独排序)比较, less字段的数据类型不再是 func(p1, p2 *Change) bool
|
// 数据集类型, 与上一篇排序文章(多字段单独排序)比较, less字段的数据类型不再是 func(p1, p2 *Change) bool
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
package zerotier
|
|
||||||
|
|
||||||
import (
|
|
||||||
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
|
||||||
"github.com/tidwall/gjson"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
func PostData(url, token string, data string) interface{} {
|
|
||||||
|
|
||||||
body, code := httper2.ZeroTierPostJson(url, data, GetHead(token))
|
|
||||||
|
|
||||||
if code != http.StatusOK {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
result := gjson.Parse(body)
|
|
||||||
return result.Value()
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetData(url, token string) interface{} {
|
|
||||||
|
|
||||||
body, code := httper2.ZeroTierGet(url, GetHead(token))
|
|
||||||
|
|
||||||
if code != http.StatusOK {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
result := gjson.Parse(body)
|
|
||||||
return result.Value()
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteMember(url, token string) interface{} {
|
|
||||||
|
|
||||||
body, code := httper2.ZeroTierDelete(url, GetHead(token))
|
|
||||||
|
|
||||||
if code != http.StatusOK {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
result := gjson.Parse(body)
|
|
||||||
return result.Value()
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetHead(token string) map[string]string {
|
|
||||||
var head = make(map[string]string)
|
|
||||||
head["Authorization"] = "Bearer " + token
|
|
||||||
head["Content-Type"] = "application/json"
|
|
||||||
return head
|
|
||||||
}
|
|
||||||
293
route/init.go
Normal file
293
route/init.go
Normal file
@@ -0,0 +1,293 @@
|
|||||||
|
package route
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model/system_app"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/docker"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/env_helper"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/port"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
|
uuid "github.com/satori/go.uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
func InitFunction() {
|
||||||
|
go checkSystemApp()
|
||||||
|
Update2_3()
|
||||||
|
CheckSerialDiskMount()
|
||||||
|
|
||||||
|
CheckToken2_11()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var syncIsExistence = false
|
||||||
|
|
||||||
|
func installSyncthing(appId string) {
|
||||||
|
|
||||||
|
var appInfo model.ServerAppList
|
||||||
|
m := model.CustomizationPostData{}
|
||||||
|
var dockerImage string
|
||||||
|
var dockerImageVersion string
|
||||||
|
appInfo = service.MyService.Casa().GetServerAppInfo(appId, "system", "us_en")
|
||||||
|
dockerImage = appInfo.Image
|
||||||
|
dockerImageVersion = appInfo.ImageVersion
|
||||||
|
|
||||||
|
if len(appInfo.ImageVersion) == 0 {
|
||||||
|
dockerImageVersion = "latest"
|
||||||
|
}
|
||||||
|
|
||||||
|
if appInfo.NetworkModel != "host" {
|
||||||
|
for i := 0; i < len(appInfo.Ports); i++ {
|
||||||
|
if p, _ := strconv.Atoi(appInfo.Ports[i].ContainerPort); port.IsPortAvailable(p, appInfo.Ports[i].Protocol) {
|
||||||
|
appInfo.Ports[i].CommendPort = strconv.Itoa(p)
|
||||||
|
} else {
|
||||||
|
if appInfo.Ports[i].Protocol == "tcp" {
|
||||||
|
if p, err := port.GetAvailablePort("tcp"); err == nil {
|
||||||
|
appInfo.Ports[i].CommendPort = strconv.Itoa(p)
|
||||||
|
}
|
||||||
|
} else if appInfo.Ports[i].Protocol == "upd" {
|
||||||
|
if p, err := port.GetAvailablePort("udp"); err == nil {
|
||||||
|
appInfo.Ports[i].CommendPort = strconv.Itoa(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if appInfo.Ports[i].Type == 0 {
|
||||||
|
appInfo.PortMap = appInfo.Ports[i].CommendPort
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(appInfo.Devices); i++ {
|
||||||
|
if !file.CheckNotExist(appInfo.Devices[i].ContainerPath) {
|
||||||
|
appInfo.Devices[i].Path = appInfo.Devices[i].ContainerPath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(appInfo.Tip) > 0 {
|
||||||
|
appInfo.Tip = env_helper.ReplaceStringDefaultENV(appInfo.Tip)
|
||||||
|
}
|
||||||
|
|
||||||
|
appInfo.MaxMemory = service.MyService.ZiMa().GetMemInfo().Total >> 20
|
||||||
|
|
||||||
|
id := uuid.NewV4().String()
|
||||||
|
|
||||||
|
installLog := model2.AppNotify{}
|
||||||
|
|
||||||
|
// step:下载镜像
|
||||||
|
err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, installLog)
|
||||||
|
if err != nil {
|
||||||
|
//pull image error
|
||||||
|
fmt.Println("pull image error", err, dockerImage, dockerImageVersion)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for !service.MyService.Docker().IsExistImage(dockerImage + ":" + dockerImageVersion) {
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
m.CpuShares = 50
|
||||||
|
m.Envs = appInfo.Envs
|
||||||
|
m.Memory = int64(appInfo.MaxMemory)
|
||||||
|
m.Origin = "system"
|
||||||
|
m.PortMap = appInfo.PortMap
|
||||||
|
m.Ports = appInfo.Ports
|
||||||
|
m.Restart = "always"
|
||||||
|
m.Volumes = appInfo.Volumes
|
||||||
|
|
||||||
|
containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, id, m, appInfo.NetworkModel)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("container create error", err)
|
||||||
|
// create container error
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//step:start container
|
||||||
|
err = service.MyService.Docker().DockerContainerStart(id)
|
||||||
|
if err != nil {
|
||||||
|
//start container error
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
portsStr, _ := json.Marshal(appInfo.Ports)
|
||||||
|
envsStr, _ := json.Marshal(appInfo.Envs)
|
||||||
|
volumesStr, _ := json.Marshal(appInfo.Volumes)
|
||||||
|
devicesStr, _ := json.Marshal(appInfo.Devices)
|
||||||
|
//step: 保存数据到数据库
|
||||||
|
md := model2.AppListDBModel{
|
||||||
|
CustomId: id,
|
||||||
|
Title: appInfo.Title,
|
||||||
|
//ScreenshotLink: appInfo.ScreenshotLink,
|
||||||
|
Slogan: appInfo.Tagline,
|
||||||
|
Description: appInfo.Description,
|
||||||
|
//Tags: appInfo.Tags,
|
||||||
|
Icon: appInfo.Icon,
|
||||||
|
Version: dockerImageVersion,
|
||||||
|
ContainerId: containerId,
|
||||||
|
Image: dockerImage,
|
||||||
|
Index: appInfo.Index,
|
||||||
|
PortMap: appInfo.PortMap,
|
||||||
|
Label: appInfo.Title,
|
||||||
|
EnableUPNP: false,
|
||||||
|
Ports: string(portsStr),
|
||||||
|
Envs: string(envsStr),
|
||||||
|
Volumes: string(volumesStr),
|
||||||
|
Position: true,
|
||||||
|
NetModel: appInfo.NetworkModel,
|
||||||
|
Restart: m.Restart,
|
||||||
|
CpuShares: 50,
|
||||||
|
Memory: int64(appInfo.MaxMemory),
|
||||||
|
Devices: string(devicesStr),
|
||||||
|
Origin: m.Origin,
|
||||||
|
CreatedAt: strconv.FormatInt(time.Now().Unix(), 10),
|
||||||
|
UpdatedAt: strconv.FormatInt(time.Now().Unix(), 10),
|
||||||
|
}
|
||||||
|
service.MyService.App().SaveContainer(md)
|
||||||
|
|
||||||
|
checkSystemApp()
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the system application is installed
|
||||||
|
func checkSystemApp() {
|
||||||
|
list := service.MyService.App().GetSystemAppList()
|
||||||
|
for _, v := range *list {
|
||||||
|
if v.Image == "linuxserver/syncthing" {
|
||||||
|
if v.State != "running" {
|
||||||
|
//step:start container
|
||||||
|
service.MyService.Docker().DockerContainerStart(v.CustomId)
|
||||||
|
}
|
||||||
|
syncIsExistence = true
|
||||||
|
if config.SystemConfigInfo.SyncPort != v.Port {
|
||||||
|
config.SystemConfigInfo.SyncPort = v.Port
|
||||||
|
}
|
||||||
|
var paths []model.PathMap
|
||||||
|
json.Unmarshal([]byte(v.Volumes), &paths)
|
||||||
|
path := ""
|
||||||
|
for _, i := range paths {
|
||||||
|
if i.ContainerPath == "/config" {
|
||||||
|
path = docker.GetDir(v.CustomId, i.Path) + "/config.xml"
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
if file.CheckNotExist(path) {
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
content := file.ReadFullFile(path)
|
||||||
|
syncConfig := &system_app.SyncConfig{}
|
||||||
|
xml.Unmarshal(content, &syncConfig)
|
||||||
|
config.SystemConfigInfo.SyncKey = syncConfig.Key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !syncIsExistence {
|
||||||
|
installSyncthing("74")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func CheckSerialDiskMount() {
|
||||||
|
// check mount point
|
||||||
|
dbList := service.MyService.Disk().GetSerialAll()
|
||||||
|
|
||||||
|
list := service.MyService.Disk().LSBLK(true)
|
||||||
|
mountPoint := make(map[string]string, len(dbList))
|
||||||
|
//remount
|
||||||
|
for _, v := range dbList {
|
||||||
|
mountPoint[v.UUID] = v.MountPoint
|
||||||
|
}
|
||||||
|
for _, v := range list {
|
||||||
|
command.ExecEnabledSMART(v.Path)
|
||||||
|
if v.Children != nil {
|
||||||
|
for _, h := range v.Children {
|
||||||
|
if len(h.MountPoint) == 0 && len(v.Children) == 1 && h.FsType == "ext4" {
|
||||||
|
if m, ok := mountPoint[h.UUID]; ok {
|
||||||
|
//mount point check
|
||||||
|
volume := m
|
||||||
|
if !file.CheckNotExist(m) {
|
||||||
|
for i := 0; file.CheckNotExist(volume); i++ {
|
||||||
|
volume = m + strconv.Itoa(i+1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
service.MyService.Disk().MountDisk(h.Path, volume)
|
||||||
|
if volume != m {
|
||||||
|
ms := model2.SerialDisk{}
|
||||||
|
ms.UUID = v.UUID
|
||||||
|
ms.MountPoint = volume
|
||||||
|
service.MyService.Disk().UpdateMountPoint(ms)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
service.MyService.Disk().RemoveLSBLKCache()
|
||||||
|
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;AutoRemoveUnuseDir")
|
||||||
|
}
|
||||||
|
func Update2_3() {
|
||||||
|
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/assist.sh")
|
||||||
|
|
||||||
|
}
|
||||||
|
func CheckToken2_11() {
|
||||||
|
if len(config.ServerInfo.Token) == 0 {
|
||||||
|
token := uuid.NewV4().String
|
||||||
|
config.ServerInfo.Token = token()
|
||||||
|
config.Cfg.Section("server").Key("Token").SetValue(token())
|
||||||
|
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||||
|
}
|
||||||
|
if len(config.AppInfo.RootPath) == 0 {
|
||||||
|
config.Cfg.Section("app").Key("RootPath").SetValue("/casaOS")
|
||||||
|
config.AppInfo.RootPath = "/casaOS"
|
||||||
|
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||||
|
}
|
||||||
|
// if len(config.ServerInfo.Handshake) == 0 {
|
||||||
|
// config.Cfg.Section("app").Key("RootPath").SetValue("/casaOS")
|
||||||
|
// config.AppInfo.RootPath = "/casaOS"
|
||||||
|
// config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||||
|
// }
|
||||||
|
sysType := runtime.GOOS
|
||||||
|
if len(config.FileSettingInfo.DownloadDir) == 0 {
|
||||||
|
downloadPath := "/DATA/Downloads"
|
||||||
|
if sysType == "windows" {
|
||||||
|
downloadPath = "C:\\CasaOS\\DATA\\Downloads"
|
||||||
|
}
|
||||||
|
if sysType == "darwin" {
|
||||||
|
downloadPath = "~/CasaOS/DATA/Downloads"
|
||||||
|
}
|
||||||
|
config.Cfg.Section("file").Key("DownloadDir").SetValue(downloadPath)
|
||||||
|
config.FileSettingInfo.DownloadDir = downloadPath
|
||||||
|
file.IsNotExistMkDir(config.FileSettingInfo.DownloadDir)
|
||||||
|
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(config.UserInfo.Description) == 0 {
|
||||||
|
config.Cfg.Section("user").Key("Description").SetValue("nothing")
|
||||||
|
config.UserInfo.Description = "nothing"
|
||||||
|
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||||
|
}
|
||||||
|
if len(config.ServerInfo.Handshake) == 0 {
|
||||||
|
config.Cfg.Section("server").Key("Handshake").SetValue("socket.casaos.io")
|
||||||
|
config.ServerInfo.Handshake = "socket.casaos.io"
|
||||||
|
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
service.MyService.System().ExecUSBAutoMountShell(config.ServerInfo.USBAutoMount)
|
||||||
|
|
||||||
|
// str := []string{}
|
||||||
|
// str = append(str, "ddd")
|
||||||
|
// str = append(str, "aaa")
|
||||||
|
// ddd := strings.Join(str, "|")
|
||||||
|
// config.Cfg.Section("file").Key("ShareDir").SetValue(ddd)
|
||||||
|
|
||||||
|
// config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||||
|
|
||||||
|
}
|
||||||
137
route/route.go
137
route/route.go
@@ -8,15 +8,19 @@ import (
|
|||||||
jwt2 "github.com/IceWhaleTech/CasaOS/pkg/utils/jwt"
|
jwt2 "github.com/IceWhaleTech/CasaOS/pkg/utils/jwt"
|
||||||
v1 "github.com/IceWhaleTech/CasaOS/route/v1"
|
v1 "github.com/IceWhaleTech/CasaOS/route/v1"
|
||||||
"github.com/IceWhaleTech/CasaOS/web"
|
"github.com/IceWhaleTech/CasaOS/web"
|
||||||
|
"github.com/gin-contrib/gzip"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
var swagHandler gin.HandlerFunc
|
var swagHandler gin.HandlerFunc
|
||||||
|
var OnlineDemo bool = false
|
||||||
|
|
||||||
func InitRouter() *gin.Engine {
|
func InitRouter() *gin.Engine {
|
||||||
|
|
||||||
r := gin.Default()
|
r := gin.Default()
|
||||||
|
|
||||||
r.Use(middleware.Cors())
|
r.Use(middleware.Cors())
|
||||||
|
r.Use(gzip.Gzip(gzip.DefaultCompression))
|
||||||
gin.SetMode(config.ServerInfo.RunMode)
|
gin.SetMode(config.ServerInfo.RunMode)
|
||||||
|
|
||||||
r.StaticFS("/ui", http.FS(web.Static))
|
r.StaticFS("/ui", http.FS(web.Static))
|
||||||
@@ -32,11 +36,12 @@ func InitRouter() *gin.Engine {
|
|||||||
|
|
||||||
r.GET("/v1/guide/check", v1.GetGuideCheck)
|
r.GET("/v1/guide/check", v1.GetGuideCheck)
|
||||||
|
|
||||||
r.GET("/debug", v1.GetSystemConfigDebug)
|
r.GET("/v1/debug", v1.GetSystemConfigDebug)
|
||||||
//set user
|
//set user
|
||||||
r.POST("/v1/user/setusernamepwd", v1.Set_Name_Pwd)
|
r.POST("/v1/user/setusernamepwd", v1.Set_Name_Pwd)
|
||||||
//get user info
|
//get user info
|
||||||
r.GET("/v1/user/info", v1.UserInfo)
|
r.GET("/v1/user/info", v1.GetUserInfo)
|
||||||
|
|
||||||
v1Group := r.Group("/v1")
|
v1Group := r.Group("/v1")
|
||||||
|
|
||||||
v1Group.Use(jwt2.JWT(swagHandler))
|
v1Group.Use(jwt2.JWT(swagHandler))
|
||||||
@@ -46,13 +51,18 @@ func InitRouter() *gin.Engine {
|
|||||||
{
|
{
|
||||||
|
|
||||||
//chang head
|
//chang head
|
||||||
v1UserGroup.POST("/changhead", v1.Up_Load_Head)
|
v1UserGroup.POST("/head", v1.PostUserHead)
|
||||||
//chang user name
|
//chang user name
|
||||||
v1UserGroup.PUT("/changusername", v1.Chang_User_Name)
|
v1UserGroup.PUT("/username", v1.PutUserName)
|
||||||
//chang pwd
|
//chang pwd
|
||||||
v1UserGroup.PUT("/changuserpwd", v1.Chang_User_Pwd)
|
v1UserGroup.PUT("/password", v1.PutUserPwd)
|
||||||
//edit user info
|
//edit user info
|
||||||
v1UserGroup.POST("/changuserinfo", v1.Chang_User_Info)
|
v1UserGroup.POST("/info", v1.PostUserChangeInfo)
|
||||||
|
v1UserGroup.PUT("/nick", v1.PutUserChangeNick)
|
||||||
|
v1UserGroup.PUT("/desc", v1.PutUserChangeDesc)
|
||||||
|
v1UserGroup.POST("/person/info", v1.PostUserPersonInfo)
|
||||||
|
|
||||||
|
v1UserGroup.GET("/shareid", v1.GetUserShareID)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,56 +78,10 @@ func InitRouter() *gin.Engine {
|
|||||||
|
|
||||||
//获取网络信息
|
//获取网络信息
|
||||||
v1ZiMaGroup.GET("/getnetinfo", v1.NetInfo)
|
v1ZiMaGroup.GET("/getnetinfo", v1.NetInfo)
|
||||||
//获取网络信息
|
|
||||||
v1ZiMaGroup.GET("/getinfo", v1.Info)
|
|
||||||
//获取系统信息
|
//获取系统信息
|
||||||
v1ZiMaGroup.GET("/sysinfo", v1.SysInfo)
|
v1ZiMaGroup.GET("/sysinfo", v1.SysInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
v1ZeroTierGroup := v1Group.Group("/zerotier")
|
|
||||||
v1ZeroTierGroup.Use()
|
|
||||||
{
|
|
||||||
//获取zerotier token
|
|
||||||
v1ZeroTierGroup.POST("/login", v1.ZeroTierGetToken)
|
|
||||||
//注册zerotier
|
|
||||||
v1ZeroTierGroup.POST("/register", v1.ZeroTierRegister)
|
|
||||||
//是否需要登录
|
|
||||||
v1ZeroTierGroup.GET("/islogin", v1.ZeroTierIsNeedLogin)
|
|
||||||
//获取网络列表
|
|
||||||
v1ZeroTierGroup.GET("/list", v1.ZeroTierGetNetworkList)
|
|
||||||
//加入网络
|
|
||||||
v1ZeroTierGroup.POST("/join/:id", v1.ZeroTierJoinNetwork)
|
|
||||||
//离开网络
|
|
||||||
v1ZeroTierGroup.POST("/leave/:id", v1.ZeroTierLeaveNetwork)
|
|
||||||
//详情
|
|
||||||
v1ZeroTierGroup.GET("/info/:id", v1.ZeroTierGetNetworkGetInfo)
|
|
||||||
////网络状态
|
|
||||||
//v1ZeroTierGroup.GET("/status", v1.ZeroTierGetNetworkGetStatus)
|
|
||||||
//修改网络类型
|
|
||||||
//v1ZeroTierGroup.PUT("/type/:id", v1.ZeroTierEditType)
|
|
||||||
//修改网络类型
|
|
||||||
//v1ZeroTierGroup.PUT("/name/:id", v1.ZeroTierEditName)
|
|
||||||
//修改v6 assign
|
|
||||||
//v1ZeroTierGroup.PUT("/v6assign/:id", v1.ZeroTierEditV6Assign)
|
|
||||||
//修改 broadcast
|
|
||||||
//v1ZeroTierGroup.PUT("/broadcast/:id", v1.ZeroTierEditBroadcast)
|
|
||||||
//create new network
|
|
||||||
v1ZeroTierGroup.POST("/create", v1.ZeroTierCreateNetwork)
|
|
||||||
//获取用户列表
|
|
||||||
v1ZeroTierGroup.GET("/member/:id", v1.ZeroTierMemberList)
|
|
||||||
//修改用户信息
|
|
||||||
//v1ZeroTierGroup.PUT("/members/:id/auth/:mId", v1.ZeroTierMemberAuth)
|
|
||||||
//修改网络用户name
|
|
||||||
//v1ZeroTierGroup.PUT("/members/:id/name/:mId", v1.ZeroTierMemberName)
|
|
||||||
v1ZeroTierGroup.DELETE("/members/:id/del/:mId", v1.ZeroTierMemberDelete)
|
|
||||||
v1ZeroTierGroup.DELETE("/network/:id/del", v1.ZeroTierDeleteNetwork)
|
|
||||||
//修改网络用户bridge功能
|
|
||||||
//v1ZeroTierGroup.PUT("/members/:id/bridge/:mId", v1.ZeroTierMemberBridge)
|
|
||||||
v1ZeroTierGroup.PUT("/edit/:id", v1.ZeroTierEdit)
|
|
||||||
v1ZeroTierGroup.GET("/joined/list", v1.ZeroTierJoinedList)
|
|
||||||
v1ZeroTierGroup.PUT("/member/:id/edit/:mId", v1.ZeroTierMemberEdit)
|
|
||||||
|
|
||||||
}
|
|
||||||
v1DDNSGroup := v1Group.Group("/ddns")
|
v1DDNSGroup := v1Group.Group("/ddns")
|
||||||
v1DDNSGroup.Use()
|
v1DDNSGroup.Use()
|
||||||
{
|
{
|
||||||
@@ -139,6 +103,8 @@ func InitRouter() *gin.Engine {
|
|||||||
{
|
{
|
||||||
//获取我的已安装的列表
|
//获取我的已安装的列表
|
||||||
v1AppGroup.GET("/mylist", v1.MyAppList)
|
v1AppGroup.GET("/mylist", v1.MyAppList)
|
||||||
|
//
|
||||||
|
v1AppGroup.GET("/usage", v1.AppUsageList)
|
||||||
//app详情
|
//app详情
|
||||||
v1AppGroup.GET("/appinfo/:id", v1.AppInfo)
|
v1AppGroup.GET("/appinfo/:id", v1.AppInfo)
|
||||||
//获取未安装的列表
|
//获取未安装的列表
|
||||||
@@ -174,7 +140,7 @@ func InitRouter() *gin.Engine {
|
|||||||
v1AppGroup.GET("/rely/:id/info", v1.ContainerRelyInfo)
|
v1AppGroup.GET("/rely/:id/info", v1.ContainerRelyInfo)
|
||||||
v1AppGroup.GET("/install/config", v1.GetDockerInstallConfig)
|
v1AppGroup.GET("/install/config", v1.GetDockerInstallConfig)
|
||||||
//v1AppGroup.POST("/custom/install", v1.CustomInstallApp)
|
//v1AppGroup.POST("/custom/install", v1.CustomInstallApp)
|
||||||
|
v1AppGroup.POST("/share", v1.ShareAppFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
v1SysGroup := v1Group.Group("/sys")
|
v1SysGroup := v1Group.Group("/sys")
|
||||||
@@ -190,6 +156,13 @@ func InitRouter() *gin.Engine {
|
|||||||
v1SysGroup.POST("/config", v1.PostSetSystemConfig)
|
v1SysGroup.POST("/config", v1.PostSetSystemConfig)
|
||||||
v1SysGroup.GET("/widget/config", v1.GetWidgetConfig)
|
v1SysGroup.GET("/widget/config", v1.GetWidgetConfig)
|
||||||
v1SysGroup.POST("/widget/config", v1.PostSetWidgetConfig)
|
v1SysGroup.POST("/widget/config", v1.PostSetWidgetConfig)
|
||||||
|
v1SysGroup.GET("/port", v1.GetCasaOSPort)
|
||||||
|
v1SysGroup.PUT("/port", v1.PutCasaOSPort)
|
||||||
|
v1SysGroup.POST("/kill", v1.PostKillCasaOS)
|
||||||
|
v1SysGroup.GET("/info", v1.Info)
|
||||||
|
v1SysGroup.PUT("/usb/off", v1.PutSystemOffUSBAutoMount)
|
||||||
|
v1SysGroup.GET("/usb/on", v1.PutSystemOnUSBAutoMount)
|
||||||
|
v1SysGroup.GET("/usb", v1.GetSystemUSBAutoMount)
|
||||||
}
|
}
|
||||||
v1FileGroup := v1Group.Group("/file")
|
v1FileGroup := v1Group.Group("/file")
|
||||||
v1FileGroup.Use()
|
v1FileGroup.Use()
|
||||||
@@ -198,34 +171,48 @@ func InitRouter() *gin.Engine {
|
|||||||
v1FileGroup.PUT("/rename", v1.RenamePath)
|
v1FileGroup.PUT("/rename", v1.RenamePath)
|
||||||
v1FileGroup.GET("/read", v1.GetFilerContent)
|
v1FileGroup.GET("/read", v1.GetFilerContent)
|
||||||
v1FileGroup.POST("/upload", v1.PostFileUpload)
|
v1FileGroup.POST("/upload", v1.PostFileUpload)
|
||||||
|
v1FileGroup.GET("/upload", v1.GetFileUpload)
|
||||||
v1FileGroup.GET("/dirpath", v1.DirPath)
|
v1FileGroup.GET("/dirpath", v1.DirPath)
|
||||||
//创建目录
|
//create folder
|
||||||
v1FileGroup.POST("/mkdir", v1.MkdirAll)
|
v1FileGroup.POST("/mkdir", v1.MkdirAll)
|
||||||
v1FileGroup.POST("/create", v1.PostCreateFile)
|
v1FileGroup.POST("/create", v1.PostCreateFile)
|
||||||
|
|
||||||
v1FileGroup.GET("/download", v1.GetDownloadFile)
|
v1FileGroup.GET("/download", v1.GetDownloadFile)
|
||||||
|
v1FileGroup.GET("/new/download", v1.GetFileDownloadNew)
|
||||||
|
v1FileGroup.POST("/operate", v1.PostOperateFileOrDir)
|
||||||
|
v1FileGroup.DELETE("/delete", v1.DeleteFile)
|
||||||
|
v1FileGroup.PUT("/update", v1.PutFileContent)
|
||||||
|
|
||||||
//v1FileGroup.GET("/download", v1.UserFileDownloadCommonService)
|
//v1FileGroup.GET("/download", v1.UserFileDownloadCommonService)
|
||||||
}
|
}
|
||||||
v1DiskGroup := v1Group.Group("/disk")
|
v1DiskGroup := v1Group.Group("/disk")
|
||||||
v1DiskGroup.Use()
|
v1DiskGroup.Use()
|
||||||
{
|
{
|
||||||
//获取磁盘列表
|
v1DiskGroup.GET("/check", v1.GetDiskCheck)
|
||||||
v1DiskGroup.GET("/list", v1.GetPlugInDisk)
|
|
||||||
|
v1DiskGroup.GET("/list", v1.GetDiskList)
|
||||||
|
|
||||||
//获取磁盘详情
|
//获取磁盘详情
|
||||||
v1DiskGroup.GET("/info", v1.GetDiskInfo)
|
v1DiskGroup.GET("/info", v1.GetDiskInfo)
|
||||||
|
|
||||||
//格式化磁盘
|
//format storage
|
||||||
v1DiskGroup.POST("/format", v1.FormatDisk)
|
v1DiskGroup.POST("/format", v1.FormatDisk)
|
||||||
|
|
||||||
//添加分区
|
// add storage
|
||||||
v1DiskGroup.POST("/addpart", v1.AddPartition)
|
v1DiskGroup.POST("/storage", v1.AddPartition)
|
||||||
|
|
||||||
|
//mount SATA disk
|
||||||
|
v1DiskGroup.POST("/mount", v1.PostMountDisk)
|
||||||
|
|
||||||
|
//umount sata disk
|
||||||
|
v1DiskGroup.POST("/umount", v1.PostDiskUmount)
|
||||||
|
|
||||||
//获取可以格式化的内容
|
//获取可以格式化的内容
|
||||||
v1DiskGroup.GET("/type", v1.FormatDiskType)
|
v1DiskGroup.GET("/type", v1.FormatDiskType)
|
||||||
|
|
||||||
//删除分区
|
//删除分区
|
||||||
v1DiskGroup.DELETE("/delpart", v1.RemovePartition)
|
v1DiskGroup.DELETE("/delpart", v1.RemovePartition)
|
||||||
|
v1DiskGroup.GET("/usb", v1.GetUSBList)
|
||||||
|
|
||||||
}
|
}
|
||||||
v1ShareGroup := v1Group.Group("/share")
|
v1ShareGroup := v1Group.Group("/share")
|
||||||
@@ -265,6 +252,36 @@ func InitRouter() *gin.Engine {
|
|||||||
{
|
{
|
||||||
v1SearchGroup.GET("/search", v1.GetSearchList)
|
v1SearchGroup.GET("/search", v1.GetSearchList)
|
||||||
}
|
}
|
||||||
|
v1PersonGroup := v1Group.Group("/person")
|
||||||
|
v1PersonGroup.Use()
|
||||||
|
{
|
||||||
|
v1PersonGroup.GET("/test", v1.PersonTest)
|
||||||
|
v1PersonGroup.GET("/users", v1.GetPersonFriend)
|
||||||
|
v1PersonGroup.POST("/user/:shareids", v1.PostAddPersonFriend)
|
||||||
|
v1PersonGroup.DELETE("/user/:shareid", v1.DeletePersonFriend)
|
||||||
|
v1PersonGroup.GET("/directory", v1.GetPersonDirectory)
|
||||||
|
v1PersonGroup.GET("/file", v1.GetPersonFile)
|
||||||
|
v1PersonGroup.GET("/refile/:uuid", v1.GetPersonReFile)
|
||||||
|
v1PersonGroup.PUT("/remarks/:shareid", v1.PutPersonRemarks)
|
||||||
|
v1PersonGroup.GET("/list", v1.GetPersonDownloadList)
|
||||||
|
v1PersonGroup.DELETE("/file/:uuid", v1.DeletePersonDownloadFile)
|
||||||
|
|
||||||
|
v1PersonGroup.POST("/share", v1.PostPersonShare)
|
||||||
|
v1PersonGroup.GET("/share", v1.GetPersonShare)
|
||||||
|
v1PersonGroup.POST("/down/dir", v1.PostPersonDownDir)
|
||||||
|
v1PersonGroup.GET("/down/dir", v1.GetPersonDownDir)
|
||||||
|
v1PersonGroup.PUT("/block/:shareid", v1.PutPersonBlock)
|
||||||
|
v1PersonGroup.GET("/public", v1.GetPersonPublic)
|
||||||
|
|
||||||
|
}
|
||||||
|
v1AnalyseGroup := v1Group.Group("/analyse")
|
||||||
|
v1AnalyseGroup.Use()
|
||||||
|
{
|
||||||
|
v1AnalyseGroup.POST("/app", v1.PostAppAnalyse)
|
||||||
|
}
|
||||||
|
v1Group.GET("/sync/config", v1.GetSyncConfig)
|
||||||
|
v1Group.Any("/syncthing/*url", v1.SyncToSyncthing)
|
||||||
|
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|||||||
38
route/v1/analyse.go
Normal file
38
route/v1/analyse.go
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
|
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
// @Summary post app analyse
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept multipart/form-data
|
||||||
|
// @Tags analyse
|
||||||
|
// @Param name formData string true "app name"
|
||||||
|
// @Param type formData string true "action" Enums(open,delete)
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /analyse/app [post]
|
||||||
|
func PostAppAnalyse(c *gin.Context) {
|
||||||
|
if config.SystemConfigInfo.Analyse == "False" {
|
||||||
|
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
name := c.PostForm("name")
|
||||||
|
t := c.PostForm("type")
|
||||||
|
language := c.GetHeader("Language")
|
||||||
|
|
||||||
|
if len(name) == 0 || len(t) == 0 {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
service.MyService.Casa().PushAppAnalyse(config.ServerInfo.Token, t, name, language)
|
||||||
|
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
|
}
|
||||||
168
route/v1/app.go
168
route/v1/app.go
@@ -1,15 +1,17 @@
|
|||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||||
port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
|
port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/sort"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// @Summary 获取远程列表
|
// @Summary 获取远程列表
|
||||||
@@ -29,20 +31,34 @@ func AppList(c *gin.Context) {
|
|||||||
//service.MyService.Docker().DockerContainerCommit("test2")
|
//service.MyService.Docker().DockerContainerCommit("test2")
|
||||||
|
|
||||||
index := c.DefaultQuery("index", "1")
|
index := c.DefaultQuery("index", "1")
|
||||||
size := c.DefaultQuery("size", "10")
|
size := c.DefaultQuery("size", "10000")
|
||||||
t := c.DefaultQuery("type", "rank")
|
t := c.DefaultQuery("type", "rank")
|
||||||
categoryId := c.DefaultQuery("category_id", "0")
|
categoryId := c.DefaultQuery("category_id", "0")
|
||||||
key := c.DefaultQuery("key", "")
|
key := c.DefaultQuery("key", "")
|
||||||
list, count := service.MyService.OAPI().GetServerList(index, size, t, categoryId, key)
|
language := c.GetHeader("Language")
|
||||||
for i := 0; i < len(list); i++ {
|
recommend, list, community := service.MyService.Casa().GetServerList(index, size, t, categoryId, key, language)
|
||||||
ct, _ := service.MyService.Docker().DockerListByImage(list[i].Image, list[i].ImageVersion)
|
// for i := 0; i < len(recommend); i++ {
|
||||||
if ct != nil {
|
// ct, _ := service.MyService.Docker().DockerListByImage(recommend[i].Image, recommend[i].ImageVersion)
|
||||||
list[i].State = ct.State
|
// if ct != nil {
|
||||||
}
|
// recommend[i].State = ct.State
|
||||||
}
|
// }
|
||||||
data := make(map[string]interface{}, 2)
|
// }
|
||||||
data["count"] = count
|
// for i := 0; i < len(list); i++ {
|
||||||
data["items"] = list
|
// ct, _ := service.MyService.Docker().DockerListByImage(list[i].Image, list[i].ImageVersion)
|
||||||
|
// if ct != nil {
|
||||||
|
// list[i].State = ct.State
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// for i := 0; i < len(community); i++ {
|
||||||
|
// ct, _ := service.MyService.Docker().DockerListByImage(community[i].Image, community[i].ImageVersion)
|
||||||
|
// if ct != nil {
|
||||||
|
// community[i].State = ct.State
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
data := make(map[string]interface{}, 3)
|
||||||
|
data["recommend"] = recommend
|
||||||
|
data["list"] = list
|
||||||
|
data["community"] = community
|
||||||
|
|
||||||
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
|
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
|
||||||
}
|
}
|
||||||
@@ -99,6 +115,18 @@ func MyAppList(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
|
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Summary my app hardware usage list
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags app
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /app/usage [get]
|
||||||
|
func AppUsageList(c *gin.Context) {
|
||||||
|
list := service.MyService.App().GetHardwareUsage()
|
||||||
|
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
|
||||||
|
}
|
||||||
|
|
||||||
// @Summary 应用详情
|
// @Summary 应用详情
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept application/json
|
// @Accept application/json
|
||||||
@@ -110,51 +138,71 @@ func MyAppList(c *gin.Context) {
|
|||||||
func AppInfo(c *gin.Context) {
|
func AppInfo(c *gin.Context) {
|
||||||
|
|
||||||
id := c.Param("id")
|
id := c.Param("id")
|
||||||
info := service.MyService.App().GetServerAppInfo(id)
|
language := c.GetHeader("Language")
|
||||||
|
info := service.MyService.Casa().GetServerAppInfo(id, "", language)
|
||||||
if info.NetworkModel != "host" {
|
if info.NetworkModel != "host" {
|
||||||
port, _ := port2.GetAvailablePort("tcp")
|
for i := 0; i < len(info.Ports); i++ {
|
||||||
info.PortMap = uint(port)
|
if p, _ := strconv.Atoi(info.Ports[i].ContainerPort); port2.IsPortAvailable(p, info.Ports[i].Protocol) {
|
||||||
for i := 0; i < len(info.Configures.TcpPorts); i++ {
|
info.Ports[i].CommendPort = strconv.Itoa(p)
|
||||||
info.Configures.TcpPorts[i].CommendPort, _ = port2.GetAvailablePort("tcp")
|
} else {
|
||||||
}
|
if info.Ports[i].Protocol == "tcp" {
|
||||||
for i := 0; i < len(info.Configures.UdpPorts); i++ {
|
if p, err := port2.GetAvailablePort("tcp"); err == nil {
|
||||||
info.Configures.UdpPorts[i].CommendPort, _ = port2.GetAvailablePort("udp")
|
info.Ports[i].CommendPort = strconv.Itoa(p)
|
||||||
|
}
|
||||||
|
} else if info.Ports[i].Protocol == "upd" {
|
||||||
|
if p, err := port2.GetAvailablePort("udp"); err == nil {
|
||||||
|
info.Ports[i].CommendPort = strconv.Itoa(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.Ports[i].Type == 0 {
|
||||||
|
info.PortMap = info.Ports[i].CommendPort
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
info.PortMap = info.TcpPort
|
for i := 0; i < len(info.Ports); i++ {
|
||||||
}
|
if info.Ports[i].Type == 0 {
|
||||||
|
info.PortMap = info.Ports[i].ContainerPort
|
||||||
for i := 0; i < len(info.Configures.Devices); i++ {
|
break
|
||||||
if !file.CheckNotExist(info.Configures.Devices[i].ContainerPath) {
|
}
|
||||||
info.Configures.Devices[i].Path = info.Configures.Devices[i].ContainerPath
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
portOrder := func(c1, c2 *model.Ports) bool {
|
for i := 0; i < len(info.Devices); i++ {
|
||||||
return c1.Type < c2.Type
|
if !file.CheckNotExist(info.Devices[i].ContainerPath) {
|
||||||
|
info.Devices[i].Path = info.Devices[i].ContainerPath
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// if len(info.Tip) > 0 {
|
||||||
|
// info.Tip = env_helper.ReplaceStringDefaultENV(info.Tip)
|
||||||
|
// }
|
||||||
|
|
||||||
envOrder := func(c1, c2 *model.Envs) bool {
|
// portOrder := func(c1, c2 *model.Ports) bool {
|
||||||
return c1.Type < c2.Type
|
// return c1.Type < c2.Type
|
||||||
}
|
// }
|
||||||
|
|
||||||
volOrder := func(c1, c2 *model.Volume) bool {
|
// envOrder := func(c1, c2 *model.Envs) bool {
|
||||||
return c1.Type < c2.Type
|
// return c1.Type < c2.Type
|
||||||
}
|
// }
|
||||||
|
|
||||||
devOrder := func(c1, c2 *model.Devices) bool {
|
// volOrder := func(c1, c2 *model.Volume) bool {
|
||||||
return c1.Type < c2.Type
|
// return c1.Type < c2.Type
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
// devOrder := func(c1, c2 *model.Devices) bool {
|
||||||
|
// return c1.Type < c2.Type
|
||||||
|
// }
|
||||||
|
|
||||||
//sort
|
//sort
|
||||||
if info.NetworkModel != "host" {
|
// if info.NetworkModel != "host" {
|
||||||
sort.PortsSort(portOrder).Sort(info.Configures.TcpPorts)
|
// sort.PortsSort(portOrder).Sort(info.Configures.TcpPorts)
|
||||||
sort.PortsSort(portOrder).Sort(info.Configures.UdpPorts)
|
// sort.PortsSort(portOrder).Sort(info.Configures.UdpPorts)
|
||||||
}
|
// }
|
||||||
|
|
||||||
sort.EnvSort(envOrder).Sort(info.Configures.Envs)
|
// sort.EnvSort(envOrder).Sort(info.Envs)
|
||||||
sort.VolSort(volOrder).Sort(info.Configures.Volumes)
|
// sort.VolSort(volOrder).Sort(info.Volumes.([]model.PathMap))
|
||||||
sort.DevSort(devOrder).Sort(info.Configures.Devices)
|
// sort.DevSort(devOrder).Sort(info.Devices)
|
||||||
|
|
||||||
info.MaxMemory = service.MyService.ZiMa().GetMemInfo().Total >> 20
|
info.MaxMemory = service.MyService.ZiMa().GetMemInfo().Total >> 20
|
||||||
|
|
||||||
@@ -169,14 +217,38 @@ func AppInfo(c *gin.Context) {
|
|||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /app/category [get]
|
// @Router /app/category [get]
|
||||||
func CategoryList(c *gin.Context) {
|
func CategoryList(c *gin.Context) {
|
||||||
list := service.MyService.OAPI().GetServerCategoryList()
|
list := service.MyService.Casa().GetServerCategoryList()
|
||||||
var count uint = 0
|
var count uint = 0
|
||||||
for _, category := range list {
|
for _, category := range list {
|
||||||
count += category.Count
|
count += category.Count
|
||||||
}
|
}
|
||||||
|
|
||||||
rear := append([]model.ServerCategoryList{}, list[0:]...)
|
rear := append([]model.ServerCategoryList{}, list[0:]...)
|
||||||
list = append(list[:0], model.ServerCategoryList{Count: count, Name: "All"})
|
list = append(list[:0], model.ServerCategoryList{Count: count, Name: "All", Font: "apps"})
|
||||||
list = append(list, rear...)
|
list = append(list, rear...)
|
||||||
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
|
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Summary 分享该应用配置
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags app
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /app/share [post]
|
||||||
|
func ShareAppFile(c *gin.Context) {
|
||||||
|
str, _ := ioutil.ReadAll(c.Request.Body)
|
||||||
|
content := service.MyService.Casa().ShareAppFile(str)
|
||||||
|
c.JSON(http.StatusOK, json.RawMessage(content))
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Resource Usage
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags app
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /app/shares [post]
|
||||||
|
func AppListResourceUsage() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ func DDNSAddConfig(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var m model2.DDNSUpdataDBModel
|
var m model2.DDNSUpdateDBModel
|
||||||
c.Bind(&m)
|
c.Bind(&m)
|
||||||
if err := service.MyService.DDNS().SaveConfig(m); err != nil {
|
if err := service.MyService.DDNS().SaveConfig(m); err != nil {
|
||||||
c.JSON(http.StatusOK,
|
c.JSON(http.StatusOK,
|
||||||
|
|||||||
451
route/v1/disk.go
451
route/v1/disk.go
@@ -1,65 +1,163 @@
|
|||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/shirou/gopsutil/v3/disk"
|
"github.com/shirou/gopsutil/v3/disk"
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// @Summary 获取磁盘列表
|
var diskMap = make(map[string]string)
|
||||||
|
|
||||||
|
// @Summary disk list
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept application/json
|
// @Accept application/json
|
||||||
// @Tags disk
|
// @Tags disk
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /disk/list [get]
|
// @Router /disk/list [get]
|
||||||
func GetPlugInDisk(c *gin.Context) {
|
func GetDiskList(c *gin.Context) {
|
||||||
|
list := service.MyService.Disk().LSBLK(false)
|
||||||
|
dbList := service.MyService.Disk().GetSerialAll()
|
||||||
|
part := make(map[string]int64, len(dbList))
|
||||||
|
for _, v := range dbList {
|
||||||
|
part[v.MountPoint] = v.CreatedAt
|
||||||
|
}
|
||||||
|
findSystem := 0
|
||||||
|
|
||||||
//ls := service.MyService.Disk().GetPlugInDisk()
|
disks := []model.Drive{}
|
||||||
//fmt.Println(ls)
|
storage := []model.Storage{}
|
||||||
//dd, _ := disk.Partitions(true)
|
avail := []model.Drive{}
|
||||||
//fmt.Println(dd)
|
for i := 0; i < len(list); i++ {
|
||||||
//
|
disk := model.Drive{}
|
||||||
//dir, err := ioutil.ReadDir("/sys/block")
|
if list[i].Rota {
|
||||||
//if err != nil {
|
disk.DiskType = "HDD"
|
||||||
// panic(err)
|
} else {
|
||||||
//}
|
disk.DiskType = "SSD"
|
||||||
//
|
}
|
||||||
//files := make([]string, 0)
|
disk.Serial = list[i].Serial
|
||||||
//
|
disk.Name = list[i].Name
|
||||||
////fmt.Println(regexp.MatchString("sd[a-z]*[0-9]", "sda"))
|
disk.Size = list[i].Size
|
||||||
//
|
disk.Path = list[i].Path
|
||||||
//for _, f := range dir {
|
disk.Model = list[i].Model
|
||||||
// if match, _ := regexp.MatchString("sd[a-z]", f.Name()); match {
|
|
||||||
// files = append(files, f.Name())
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//fmt.Println(files)
|
|
||||||
//filess := make([]string, 0)
|
|
||||||
//for _, file := range files {
|
|
||||||
// dirs, _ := ioutil.ReadDir("/sys/block/" + file)
|
|
||||||
//
|
|
||||||
// for _, f := range dirs {
|
|
||||||
// if match, _ := regexp.MatchString("sd[a-z]*[0-9]", f.Name()); match {
|
|
||||||
// filess = append(filess, f.Name())
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//fmt.Println(filess)
|
|
||||||
//
|
|
||||||
//for _, s := range filess {
|
|
||||||
// fmt.Println(disk.Usage("/dev/" + s))
|
|
||||||
//}
|
|
||||||
|
|
||||||
lst := service.MyService.Disk().LSBLK()
|
if len(list[i].Children) > 0 && findSystem == 0 {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: lst})
|
for j := 0; j < len(list[i].Children); j++ {
|
||||||
|
if len(list[i].Children[j].Children) > 0 {
|
||||||
|
for _, v := range list[i].Children[j].Children {
|
||||||
|
if v.MountPoint == "/" {
|
||||||
|
stor := model.Storage{}
|
||||||
|
stor.Name = "System"
|
||||||
|
stor.MountPoint = v.MountPoint
|
||||||
|
stor.Size = v.FSSize
|
||||||
|
stor.Avail = v.FSAvail
|
||||||
|
stor.Path = v.Path
|
||||||
|
stor.Type = v.FsType
|
||||||
|
stor.DriveName = "System"
|
||||||
|
disk.Model = "System"
|
||||||
|
if strings.Contains(v.SubSystems, "mmc") {
|
||||||
|
disk.DiskType = "MMC"
|
||||||
|
} else if strings.Contains(v.SubSystems, "usb") {
|
||||||
|
disk.DiskType = "USB"
|
||||||
|
}
|
||||||
|
disk.Health = "true"
|
||||||
|
|
||||||
|
disks = append(disks, disk)
|
||||||
|
storage = append(storage, stor)
|
||||||
|
findSystem = 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if list[i].Children[j].MountPoint == "/" {
|
||||||
|
stor := model.Storage{}
|
||||||
|
stor.Name = "System"
|
||||||
|
stor.MountPoint = list[i].Children[j].MountPoint
|
||||||
|
stor.Size = list[i].Children[j].FSSize
|
||||||
|
stor.Avail = list[i].Children[j].FSAvail
|
||||||
|
stor.Path = list[i].Children[j].Path
|
||||||
|
stor.Type = list[i].Children[j].FsType
|
||||||
|
stor.DriveName = "System"
|
||||||
|
disk.Model = "System"
|
||||||
|
if strings.Contains(list[i].Children[j].SubSystems, "mmc") {
|
||||||
|
disk.DiskType = "MMC"
|
||||||
|
} else if strings.Contains(list[i].Children[j].SubSystems, "usb") {
|
||||||
|
disk.DiskType = "USB"
|
||||||
|
}
|
||||||
|
disk.Health = "true"
|
||||||
|
|
||||||
|
disks = append(disks, disk)
|
||||||
|
storage = append(storage, stor)
|
||||||
|
findSystem = 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if findSystem == 1 {
|
||||||
|
findSystem += 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" {
|
||||||
|
temp := service.MyService.Disk().SmartCTL(list[i].Path)
|
||||||
|
if reflect.DeepEqual(temp, model.SmartctlA{}) {
|
||||||
|
temp.SmartStatus.Passed = true
|
||||||
|
}
|
||||||
|
if len(list[i].Children) == 1 && len(list[i].Children[0].MountPoint) > 0 {
|
||||||
|
stor := model.Storage{}
|
||||||
|
stor.MountPoint = list[i].Children[0].MountPoint
|
||||||
|
stor.Size = list[i].Children[0].FSSize
|
||||||
|
stor.Avail = list[i].Children[0].FSAvail
|
||||||
|
stor.Path = list[i].Children[0].Path
|
||||||
|
stor.Type = list[i].Children[0].FsType
|
||||||
|
stor.DriveName = list[i].Name
|
||||||
|
pathArr := strings.Split(list[i].Children[0].MountPoint, "/")
|
||||||
|
if len(pathArr) == 3 {
|
||||||
|
stor.Name = pathArr[2]
|
||||||
|
}
|
||||||
|
if t, ok := part[list[i].Children[0].MountPoint]; ok {
|
||||||
|
stor.CreatedAt = t
|
||||||
|
}
|
||||||
|
storage = append(storage, stor)
|
||||||
|
} else {
|
||||||
|
//todo 长度有问题
|
||||||
|
if len(list[i].Children) == 1 && list[i].Children[0].FsType == "ext4" {
|
||||||
|
disk.NeedFormat = false
|
||||||
|
avail = append(avail, disk)
|
||||||
|
} else {
|
||||||
|
disk.NeedFormat = true
|
||||||
|
avail = append(avail, disk)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
disk.Temperature = temp.Temperature.Current
|
||||||
|
disk.Health = strconv.FormatBool(temp.SmartStatus.Passed)
|
||||||
|
|
||||||
|
disks = append(disks, disk)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data := make(map[string]interface{}, 3)
|
||||||
|
data["drive"] = disks
|
||||||
|
data["storage"] = storage
|
||||||
|
data["avail"] = avail
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: data})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary 获取磁盘列表
|
// @Summary get disk list
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept application/json
|
// @Accept application/json
|
||||||
// @Tags disk
|
// @Tags disk
|
||||||
@@ -68,7 +166,7 @@ func GetPlugInDisk(c *gin.Context) {
|
|||||||
// @Router /disk/lists [get]
|
// @Router /disk/lists [get]
|
||||||
func GetPlugInDisks(c *gin.Context) {
|
func GetPlugInDisks(c *gin.Context) {
|
||||||
|
|
||||||
list := service.MyService.Disk().LSBLK()
|
list := service.MyService.Disk().LSBLK(true)
|
||||||
var result []*disk.UsageStat
|
var result []*disk.UsageStat
|
||||||
for _, item := range list {
|
for _, item := range list {
|
||||||
result = append(result, service.MyService.Disk().GetDiskInfoByPath(item.Path))
|
result = append(result, service.MyService.Disk().GetDiskInfoByPath(item.Path))
|
||||||
@@ -76,12 +174,12 @@ func GetPlugInDisks(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: result})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: result})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary 磁盘详情
|
// @Summary disk detail
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept application/json
|
// @Accept application/json
|
||||||
// @Tags disk
|
// @Tags disk
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Param path query string true "要获取的磁盘详情 例如/dev/sda"
|
// @Param path query string true "for example /dev/sda"
|
||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /disk/info [get]
|
// @Router /disk/info [get]
|
||||||
func GetDiskInfo(c *gin.Context) {
|
func GetDiskInfo(c *gin.Context) {
|
||||||
@@ -93,31 +191,46 @@ func GetDiskInfo(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: m})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: m})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary 磁盘详情
|
// @Summary format storage
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept multipart/form-data
|
// @Accept multipart/form-data
|
||||||
// @Tags disk
|
// @Tags disk
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Param path formData string true "磁盘路径 例如/dev/sda1"
|
// @Param path formData string true "e.g. /dev/sda1"
|
||||||
|
// @Param pwd formData string true "user password"
|
||||||
|
// @Param volume formData string true "mount point"
|
||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /disk/format [post]
|
// @Router /disk/format [post]
|
||||||
func FormatDisk(c *gin.Context) {
|
func FormatDisk(c *gin.Context) {
|
||||||
path := c.PostForm("path")
|
path := c.PostForm("path")
|
||||||
|
t := "ext4"
|
||||||
|
pwd := c.PostForm("pwd")
|
||||||
|
volume := c.PostForm("volume")
|
||||||
|
|
||||||
t := c.PostForm("type")
|
if pwd != config.UserInfo.PWD {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.PWD_INVALID, Message: oasis_err.GetMsg(oasis_err.PWD_INVALID)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if len(path) == 0 || len(t) == 0 {
|
if len(path) == 0 || len(t) == 0 {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
if _, ok := diskMap[path]; ok {
|
||||||
//删除挂载点
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.DISK_BUSYING, Message: oasis_err.GetMsg(oasis_err.DISK_BUSYING)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
diskMap[path] = "busying"
|
||||||
service.MyService.Disk().UmountPointAndRemoveDir(path)
|
service.MyService.Disk().UmountPointAndRemoveDir(path)
|
||||||
|
format := service.MyService.Disk().FormatDisk(path, t)
|
||||||
//格式化磁盘
|
if len(format) == 0 {
|
||||||
service.MyService.Disk().FormatDisk(path, t)
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.FORMAT_ERROR, Message: oasis_err.GetMsg(oasis_err.FORMAT_ERROR)})
|
||||||
|
delete(diskMap, path)
|
||||||
//重新挂载
|
return
|
||||||
|
}
|
||||||
|
service.MyService.Disk().MountDisk(path, volume)
|
||||||
|
service.MyService.Disk().RemoveLSBLKCache()
|
||||||
|
delete(diskMap, path)
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,25 +267,231 @@ func RemovePartition(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary 添加分区
|
// @Summary add storage
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept multipart/form-data
|
// @Accept multipart/form-data
|
||||||
// @Tags disk
|
// @Tags disk
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Param path formData string true "磁盘路径 例如/dev/sda"
|
// @Param path formData string true "disk path e.g. /dev/sda"
|
||||||
// @Param size formData string true "需要分区容量大小(MB)"
|
// @Param serial formData string true "serial"
|
||||||
// @Param num formData string true "磁盘符号"
|
// @Param name formData string true "name"
|
||||||
|
// @Param format formData bool true "need format(true)"
|
||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /disk/addpart [post]
|
// @Router /disk/storage [post]
|
||||||
func AddPartition(c *gin.Context) {
|
func AddPartition(c *gin.Context) {
|
||||||
|
name := c.PostForm("name")
|
||||||
path := c.PostForm("path")
|
path := c.PostForm("path")
|
||||||
size, _ := strconv.Atoi(c.DefaultPostForm("size", "0"))
|
format, _ := strconv.ParseBool(c.PostForm("format"))
|
||||||
num := c.DefaultPostForm("num", "9")
|
if len(name) == 0 || len(path) == 0 {
|
||||||
if len(path) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, ok := diskMap[path]; ok {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.DISK_BUSYING, Message: oasis_err.GetMsg(oasis_err.DISK_BUSYING)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !file.CheckNotExist("/DATA/" + name) {
|
||||||
|
// /mnt/name exist
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.NAME_NOT_AVAILABLE, Message: oasis_err.GetMsg(oasis_err.NAME_NOT_AVAILABLE)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
diskMap[path] = "busying"
|
||||||
|
currentDisk := service.MyService.Disk().GetDiskInfo(path)
|
||||||
|
if !format {
|
||||||
|
if len(currentDisk.Children) != 1 || !(len(currentDisk.Children) > 0 && currentDisk.Children[0].FsType == "ext4") {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.DISK_NEEDS_FORMAT, Message: oasis_err.GetMsg(oasis_err.DISK_NEEDS_FORMAT)})
|
||||||
|
delete(diskMap, path)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
service.MyService.Disk().AddPartition(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
//size*1024*1024/512
|
formatBool := true
|
||||||
service.MyService.Disk().AddPartition(path, num, uint64(size*1024*2))
|
for formatBool {
|
||||||
|
currentDisk = service.MyService.Disk().GetDiskInfo(path)
|
||||||
|
fmt.Println(currentDisk.Children)
|
||||||
|
if len(currentDisk.Children) > 0 {
|
||||||
|
formatBool = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
currentDisk = service.MyService.Disk().GetDiskInfo(path)
|
||||||
|
if len(currentDisk.Children) != 1 {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.DISK_NEEDS_FORMAT, Message: oasis_err.GetMsg(oasis_err.DISK_NEEDS_FORMAT)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
mountPath := "/DATA/" + name
|
||||||
|
m := model2.SerialDisk{}
|
||||||
|
m.MountPoint = mountPath
|
||||||
|
m.Path = currentDisk.Children[0].Path
|
||||||
|
m.UUID = currentDisk.Children[0].UUID
|
||||||
|
m.State = 0
|
||||||
|
m.CreatedAt = time.Now().Unix()
|
||||||
|
service.MyService.Disk().SaveMountPoint(m)
|
||||||
|
|
||||||
|
//mount dir
|
||||||
|
service.MyService.Disk().MountDisk(currentDisk.Children[0].Path, mountPath)
|
||||||
|
|
||||||
|
service.MyService.Disk().RemoveLSBLKCache()
|
||||||
|
|
||||||
|
delete(diskMap, path)
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Summary add mount point
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept multipart/form-data
|
||||||
|
// @Tags disk
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Param path formData string true "for example: /dev/sda1"
|
||||||
|
// @Param serial formData string true "disk id"
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /disk/mount [post]
|
||||||
|
func PostMountDisk(c *gin.Context) {
|
||||||
|
// for example: path=/dev/sda1
|
||||||
|
path := c.PostForm("path")
|
||||||
|
serial := c.PostForm("serial")
|
||||||
|
|
||||||
|
mountPath := "/DATA/volume"
|
||||||
|
var list = service.MyService.Disk().GetSerialAll()
|
||||||
|
var pathMapList = make(map[string]string, len(list))
|
||||||
|
for _, v := range list {
|
||||||
|
pathMapList[v.MountPoint] = "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(list)+1; i++ {
|
||||||
|
if _, ok := pathMapList[mountPath+strconv.Itoa(i)]; !ok {
|
||||||
|
mountPath = mountPath + strconv.Itoa(i)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//mount dir
|
||||||
|
service.MyService.Disk().MountDisk(path, mountPath)
|
||||||
|
|
||||||
|
m := model2.SerialDisk{}
|
||||||
|
m.MountPoint = mountPath
|
||||||
|
m.Path = path
|
||||||
|
m.UUID = serial
|
||||||
|
m.State = 0
|
||||||
|
//service.MyService.Disk().SaveMountPoint(m)
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary remove mount point
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept multipart/form-data
|
||||||
|
// @Tags disk
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Param path formData string true "e.g. /dev/sda1"
|
||||||
|
// @Param mount_point formData string true "e.g. /mnt/volume1"
|
||||||
|
// @Param pwd formData string true "user password"
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /disk/umount [post]
|
||||||
|
func PostDiskUmount(c *gin.Context) {
|
||||||
|
|
||||||
|
path := c.PostForm("path")
|
||||||
|
mountPoint := c.PostForm("volume")
|
||||||
|
pwd := c.PostForm("pwd")
|
||||||
|
|
||||||
|
if len(path) == 0 || len(mountPoint) == 0 {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if pwd != config.UserInfo.PWD {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.PWD_INVALID, Message: oasis_err.GetMsg(oasis_err.PWD_INVALID)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := diskMap[path]; ok {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.DISK_BUSYING, Message: oasis_err.GetMsg(oasis_err.DISK_BUSYING)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
service.MyService.Disk().UmountPointAndRemoveDir(path)
|
||||||
|
//delete data
|
||||||
|
service.MyService.Disk().DeleteMountPoint(path, mountPoint)
|
||||||
|
service.MyService.Disk().RemoveLSBLKCache()
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary confirm delete disk
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags disk
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Param id path string true "id"
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /disk/remove/{id} [delete]
|
||||||
|
func DeleteDisk(c *gin.Context) {
|
||||||
|
id := c.Param("id")
|
||||||
|
service.MyService.Disk().DeleteMount(id)
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary check mount point
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags disk
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /disk/init [get]
|
||||||
|
func GetDiskCheck(c *gin.Context) {
|
||||||
|
|
||||||
|
dbList := service.MyService.Disk().GetSerialAll()
|
||||||
|
list := service.MyService.Disk().LSBLK(true)
|
||||||
|
|
||||||
|
mapList := make(map[string]string)
|
||||||
|
|
||||||
|
for _, v := range list {
|
||||||
|
mapList[v.Serial] = "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range dbList {
|
||||||
|
if _, ok := mapList[v.UUID]; !ok {
|
||||||
|
//disk undefind
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.ERROR, Message: oasis_err.GetMsg(oasis_err.ERROR), Data: "disk undefind"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary check mount point
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags disk
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /disk/usb [get]
|
||||||
|
func GetUSBList(c *gin.Context) {
|
||||||
|
list := service.MyService.Disk().LSBLK(false)
|
||||||
|
data := []model.DriveUSB{}
|
||||||
|
for _, v := range list {
|
||||||
|
if v.Tran == "usb" {
|
||||||
|
temp := model.DriveUSB{}
|
||||||
|
temp.Model = v.Model
|
||||||
|
temp.Name = v.Name
|
||||||
|
temp.Size = v.Size
|
||||||
|
mountTemp := true
|
||||||
|
if len(v.Children) == 0 {
|
||||||
|
mountTemp = false
|
||||||
|
}
|
||||||
|
for _, child := range v.Children {
|
||||||
|
if len(child.MountPoint) > 0 {
|
||||||
|
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
|
||||||
|
temp.Avail += avail
|
||||||
|
} else {
|
||||||
|
mountTemp = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
temp.Mount = mountTemp
|
||||||
|
data = append(data, temp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: data})
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package v1
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
json2 "encoding/json"
|
json2 "encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
"reflect"
|
"reflect"
|
||||||
@@ -10,6 +11,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/docker"
|
"github.com/IceWhaleTech/CasaOS/pkg/docker"
|
||||||
upnp2 "github.com/IceWhaleTech/CasaOS/pkg/upnp"
|
upnp2 "github.com/IceWhaleTech/CasaOS/pkg/upnp"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
@@ -25,6 +27,7 @@ import (
|
|||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/jinzhu/copier"
|
"github.com/jinzhu/copier"
|
||||||
uuid "github.com/satori/go.uuid"
|
uuid "github.com/satori/go.uuid"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -143,6 +146,7 @@ func SpeedPush(c *gin.Context) {
|
|||||||
// @Router /app/install/{id} [post]
|
// @Router /app/install/{id} [post]
|
||||||
func InstallApp(c *gin.Context) {
|
func InstallApp(c *gin.Context) {
|
||||||
appId := c.Param("id")
|
appId := c.Param("id")
|
||||||
|
language := c.GetHeader("Language")
|
||||||
var appInfo model.ServerAppList
|
var appInfo model.ServerAppList
|
||||||
m := model.CustomizationPostData{}
|
m := model.CustomizationPostData{}
|
||||||
c.BindJSON(&m)
|
c.BindJSON(&m)
|
||||||
@@ -172,7 +176,7 @@ func InstallApp(c *gin.Context) {
|
|||||||
dockerImageVersion = "latest"
|
dockerImageVersion = "latest"
|
||||||
}
|
}
|
||||||
if m.Origin != "custom" {
|
if m.Origin != "custom" {
|
||||||
appInfo = service.MyService.App().GetServerAppInfo(appId)
|
appInfo = service.MyService.Casa().GetServerAppInfo(appId, "", language)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@@ -216,14 +220,24 @@ func InstallApp(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
if m.Origin == "custom" {
|
||||||
|
for _, device := range m.Devices {
|
||||||
|
if file.CheckNotExist(device.Path) {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.DEVICE_NOT_EXIST, Message: device.Path + "," + oasis_err2.GetMsg(oasis_err2.DEVICE_NOT_EXIST)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
for _, device := range m.Devices {
|
|
||||||
if file.CheckNotExist(device.Path) {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.DEVICE_NOT_EXIST, Message: device.Path + "," + oasis_err2.GetMsg(oasis_err2.DEVICE_NOT_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
dev := []model.PathMap{}
|
||||||
|
for _, device := range dev {
|
||||||
|
if !file.CheckNotExist(device.Path) {
|
||||||
|
dev = append(dev, device)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m.Devices = dev
|
||||||
}
|
}
|
||||||
|
|
||||||
//restart := c.PostForm("restart") //always 总是重启, unless-stopped 除非用户手动停止容器,否则总是重新启动, on-failure:仅当容器退出代码非零时重新启动
|
//restart := c.PostForm("restart") //always 总是重启, unless-stopped 除非用户手动停止容器,否则总是重新启动, on-failure:仅当容器退出代码非零时重新启动
|
||||||
//if len(restart) > 0 {
|
//if len(restart) > 0 {
|
||||||
//
|
//
|
||||||
@@ -239,10 +253,13 @@ func InstallApp(c *gin.Context) {
|
|||||||
go func() {
|
go func() {
|
||||||
installLog := model2.AppNotify{}
|
installLog := model2.AppNotify{}
|
||||||
installLog.State = 0
|
installLog.State = 0
|
||||||
|
installLog.CustomId = id
|
||||||
installLog.Message = "installing rely"
|
installLog.Message = "installing rely"
|
||||||
|
installLog.Class = types.NOTIFY_APP
|
||||||
installLog.Type = types.NOTIFY_TYPE_UNIMPORTANT
|
installLog.Type = types.NOTIFY_TYPE_UNIMPORTANT
|
||||||
installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
||||||
installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
||||||
|
installLog.Id = uuid.NewV4().String()
|
||||||
service.MyService.Notify().AddLog(installLog)
|
service.MyService.Notify().AddLog(installLog)
|
||||||
if m.Origin != "custom" {
|
if m.Origin != "custom" {
|
||||||
for _, plugin := range appInfo.Plugins {
|
for _, plugin := range appInfo.Plugins {
|
||||||
@@ -265,11 +282,11 @@ func InstallApp(c *gin.Context) {
|
|||||||
rely.ContainerId = mysqlContainerId
|
rely.ContainerId = mysqlContainerId
|
||||||
rely.CustomId = mid
|
rely.CustomId = mid
|
||||||
rely.ContainerCustomId = id
|
rely.ContainerCustomId = id
|
||||||
var msqlConfig model2.MysqlConfigs
|
var mysqlConfig model2.MysqlConfigs
|
||||||
|
|
||||||
//结构体转换
|
//结构体转换
|
||||||
copier.Copy(&msqlConfig, &mc)
|
copier.Copy(&mysqlConfig, &mc)
|
||||||
rely.Config = msqlConfig
|
rely.Config = mysqlConfig
|
||||||
service.MyService.Rely().Create(rely)
|
service.MyService.Rely().Create(rely)
|
||||||
|
|
||||||
relyMap["mysql"] = mid
|
relyMap["mysql"] = mid
|
||||||
@@ -282,7 +299,6 @@ func InstallApp(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
installLog.Message = "pulling"
|
installLog.Message = "pulling"
|
||||||
@@ -333,6 +349,8 @@ func InstallApp(c *gin.Context) {
|
|||||||
service.MyService.Notify().UpdateLog(installLog)
|
service.MyService.Notify().UpdateLog(installLog)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// echo -e "hellow\nworld" >>
|
||||||
|
|
||||||
//step:启动容器
|
//step:启动容器
|
||||||
err = service.MyService.Docker().DockerContainerStart(id)
|
err = service.MyService.Docker().DockerContainerStart(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -417,10 +435,18 @@ func InstallApp(c *gin.Context) {
|
|||||||
rely := model.MapStrings{}
|
rely := model.MapStrings{}
|
||||||
|
|
||||||
copier.Copy(&rely, &relyMap)
|
copier.Copy(&rely, &relyMap)
|
||||||
|
// if m.Origin != "custom" {
|
||||||
|
// for i := 0; i < len(m.Volumes); i++ {
|
||||||
|
// m.Volumes[i].Path = docker.GetDir(id, m.Volumes[i].Path)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
portsStr, _ := json2.Marshal(m.Ports)
|
portsStr, _ := json2.Marshal(m.Ports)
|
||||||
envsStr, _ := json2.Marshal(m.Envs)
|
envsStr, _ := json2.Marshal(m.Envs)
|
||||||
volumesStr, _ := json2.Marshal(m.Volumes)
|
volumesStr, _ := json2.Marshal(m.Volumes)
|
||||||
devicesStr, _ := json2.Marshal(m.Devices)
|
devicesStr, _ := json2.Marshal(m.Devices)
|
||||||
|
cmd, _ := json2.Marshal(m.Cmd)
|
||||||
|
capAdd, _ := json.Marshal(m.CapAdd)
|
||||||
//step: 保存数据到数据库
|
//step: 保存数据到数据库
|
||||||
md := model2.AppListDBModel{
|
md := model2.AppListDBModel{
|
||||||
CustomId: id,
|
CustomId: id,
|
||||||
@@ -448,14 +474,19 @@ func InstallApp(c *gin.Context) {
|
|||||||
Memory: m.Memory,
|
Memory: m.Memory,
|
||||||
Devices: string(devicesStr),
|
Devices: string(devicesStr),
|
||||||
//Rely: rely,
|
//Rely: rely,
|
||||||
Origin: m.Origin,
|
Origin: m.Origin,
|
||||||
CreatedAt: strconv.FormatInt(time.Now().Unix(), 10),
|
CreatedAt: strconv.FormatInt(time.Now().Unix(), 10),
|
||||||
UpdatedAt: strconv.FormatInt(time.Now().Unix(), 10),
|
UpdatedAt: strconv.FormatInt(time.Now().Unix(), 10),
|
||||||
|
Cmd: string(cmd),
|
||||||
|
CapAdd: string(capAdd),
|
||||||
|
HostName: m.HostName,
|
||||||
|
Privileged: m.Privileged,
|
||||||
}
|
}
|
||||||
//if appInfo.NetworkModel == "host" {
|
//if appInfo.NetworkModel == "host" {
|
||||||
// m.PortMap = m.Port
|
// m.PortMap = m.Port
|
||||||
//}
|
//}
|
||||||
service.MyService.App().SaveContainer(md)
|
service.MyService.App().SaveContainer(md)
|
||||||
|
config.CasaOSGlobalVariables.AppChange = true
|
||||||
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -670,7 +701,7 @@ func UnInstallApp(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//step:删除容器
|
//step:删除容器
|
||||||
err = service.MyService.Docker().DockerContainerRemove(appId)
|
err = service.MyService.Docker().DockerContainerRemove(appId, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.UNINSTALL_APP_ERROR, Message: oasis_err2.GetMsg(oasis_err2.UNINSTALL_APP_ERROR), Data: err.Error()})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.UNINSTALL_APP_ERROR, Message: oasis_err2.GetMsg(oasis_err2.UNINSTALL_APP_ERROR), Data: err.Error()})
|
||||||
return
|
return
|
||||||
@@ -685,10 +716,15 @@ func UnInstallApp(c *gin.Context) {
|
|||||||
if info.Origin != "custom" {
|
if info.Origin != "custom" {
|
||||||
|
|
||||||
//step: 删除文件夹
|
//step: 删除文件夹
|
||||||
service.MyService.App().DelAppConfigDir(appId)
|
vol := gjson.Get(info.Volumes, "#.host")
|
||||||
|
for _, v := range vol.Array() {
|
||||||
|
if strings.Contains(v.String(), appId) {
|
||||||
|
service.MyService.App().DelAppConfigDir(v.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//step: 删除install log
|
//step: 删除install log
|
||||||
service.MyService.Notify().DelLog(appId)
|
//service.MyService.Notify().DelLog(appId)
|
||||||
|
|
||||||
// for k, v := range info.Rely {
|
// for k, v := range info.Rely {
|
||||||
//
|
//
|
||||||
@@ -727,6 +763,13 @@ func UnInstallApp(c *gin.Context) {
|
|||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
config.CasaOSGlobalVariables.AppChange = true
|
||||||
|
unInstallLog := model2.AppNotify{}
|
||||||
|
unInstallLog.State = 0
|
||||||
|
unInstallLog.CustomId = appId
|
||||||
|
unInstallLog.Message = "uninstalled"
|
||||||
|
unInstallLog.Id = uuid.NewV4().String()
|
||||||
|
service.MyService.Notify().UpdateLog(unInstallLog)
|
||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
|
|
||||||
@@ -899,7 +942,9 @@ func UpdateSetting(c *gin.Context) {
|
|||||||
envsStr, _ := json2.Marshal(m.Envs)
|
envsStr, _ := json2.Marshal(m.Envs)
|
||||||
volumesStr, _ := json2.Marshal(m.Volumes)
|
volumesStr, _ := json2.Marshal(m.Volumes)
|
||||||
devicesStr, _ := json2.Marshal(m.Devices)
|
devicesStr, _ := json2.Marshal(m.Devices)
|
||||||
if !reflect.DeepEqual(string(portsStr), appInfo.Ports) || !reflect.DeepEqual(string(envsStr), appInfo.Envs) || !reflect.DeepEqual(string(volumesStr), appInfo.Volumes) || m.PortMap != appInfo.PortMap || m.NetworkModel != appInfo.NetModel {
|
capAddStr, _ := json2.Marshal(m.CapAdd)
|
||||||
|
cmdStr, _ := json.Marshal(m.Cmd)
|
||||||
|
if !reflect.DeepEqual(string(portsStr), appInfo.Ports) || !reflect.DeepEqual(string(envsStr), appInfo.Envs) || !reflect.DeepEqual(string(volumesStr), appInfo.Volumes) || m.PortMap != appInfo.PortMap || m.NetworkModel != appInfo.NetModel || m.HostName != appInfo.HostName || !reflect.DeepEqual(string(cmdStr), appInfo.Cmd) || !reflect.DeepEqual(string(capAddStr), appInfo.CapAdd) || m.Privileged != appInfo.Privileged {
|
||||||
|
|
||||||
var newUUid = uuid.NewV4().String()
|
var newUUid = uuid.NewV4().String()
|
||||||
var err error
|
var err error
|
||||||
@@ -916,7 +961,7 @@ func UpdateSetting(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = service.MyService.Docker().DockerContainerRemove(id)
|
err = service.MyService.Docker().DockerContainerRemove(id, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
|
||||||
return
|
return
|
||||||
@@ -1017,6 +1062,10 @@ func UpdateSetting(c *gin.Context) {
|
|||||||
appInfo.Restart = m.Restart
|
appInfo.Restart = m.Restart
|
||||||
appInfo.Memory = m.Memory
|
appInfo.Memory = m.Memory
|
||||||
appInfo.CpuShares = m.CpuShares
|
appInfo.CpuShares = m.CpuShares
|
||||||
|
appInfo.Cmd = string(cmdStr)
|
||||||
|
appInfo.Privileged = m.Privileged
|
||||||
|
appInfo.CapAdd = string(capAddStr)
|
||||||
|
appInfo.HostName = m.HostName
|
||||||
appInfo.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
appInfo.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
||||||
service.MyService.App().UpdateApp(appInfo)
|
service.MyService.App().UpdateApp(appInfo)
|
||||||
|
|
||||||
@@ -1112,25 +1161,32 @@ func ContainerRelyInfo(c *gin.Context) {
|
|||||||
func ContainerUpdateInfo(c *gin.Context) {
|
func ContainerUpdateInfo(c *gin.Context) {
|
||||||
appId := c.Param("id")
|
appId := c.Param("id")
|
||||||
appInfo := service.MyService.App().GetAppDBInfo(appId)
|
appInfo := service.MyService.App().GetAppDBInfo(appId)
|
||||||
|
|
||||||
info, err := service.MyService.Docker().DockerContainerInfo(appId)
|
info, err := service.MyService.Docker().DockerContainerInfo(appId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//todo 需要自定义错误
|
//todo 需要自定义错误
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: err.Error()})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var port model.PortArrey
|
var port model.PortArray
|
||||||
json2.Unmarshal([]byte(appInfo.Ports), &port)
|
json2.Unmarshal([]byte(appInfo.Ports), &port)
|
||||||
|
|
||||||
var envs model.EnvArrey
|
var envs model.EnvArray
|
||||||
json2.Unmarshal([]byte(appInfo.Envs), &envs)
|
json2.Unmarshal([]byte(appInfo.Envs), &envs)
|
||||||
|
|
||||||
var vol model.PathArrey
|
var vol model.PathArray
|
||||||
json2.Unmarshal([]byte(appInfo.Volumes), &vol)
|
json2.Unmarshal([]byte(appInfo.Volumes), &vol)
|
||||||
|
|
||||||
var dir model.PathArrey
|
for i := 0; i < len(vol); i++ {
|
||||||
|
vol[i].Path = strings.ReplaceAll(vol[i].Path, "$AppID", appId)
|
||||||
|
}
|
||||||
|
|
||||||
|
var dir model.PathArray
|
||||||
json2.Unmarshal([]byte(appInfo.Devices), &dir)
|
json2.Unmarshal([]byte(appInfo.Devices), &dir)
|
||||||
|
|
||||||
|
var cmd []string
|
||||||
|
json2.Unmarshal([]byte(appInfo.Cmd), &cmd)
|
||||||
|
var capAdd []string
|
||||||
|
json2.Unmarshal([]byte(appInfo.CapAdd), &capAdd)
|
||||||
//volumesStr, _ := json2.Marshal(m.Volumes)
|
//volumesStr, _ := json2.Marshal(m.Volumes)
|
||||||
//devicesStr, _ := json2.Marshal(m.Devices)
|
//devicesStr, _ := json2.Marshal(m.Devices)
|
||||||
m := model.CustomizationPostData{}
|
m := model.CustomizationPostData{}
|
||||||
@@ -1152,6 +1208,11 @@ func ContainerUpdateInfo(c *gin.Context) {
|
|||||||
m.EnableUPNP = appInfo.EnableUPNP
|
m.EnableUPNP = appInfo.EnableUPNP
|
||||||
m.Position = appInfo.Position
|
m.Position = appInfo.Position
|
||||||
|
|
||||||
|
m.CapAdd = capAdd
|
||||||
|
m.Cmd = cmd
|
||||||
|
m.HostName = appInfo.HostName
|
||||||
|
m.Privileged = appInfo.Privileged
|
||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: m})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: m})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
318
route/v1/file.go
318
route/v1/file.go
@@ -7,14 +7,18 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
url2 "net/url"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/spf13/afero"
|
||||||
)
|
)
|
||||||
|
|
||||||
func downloadReadFile(c *gin.Context) {
|
func downloadReadFile(c *gin.Context) {
|
||||||
@@ -125,12 +129,12 @@ func GetLocalFile(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary 下载文件
|
// @Summary download
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept application/json
|
// @Accept application/json
|
||||||
// @Tags file
|
// @Tags file
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Param path query string true "路径"
|
// @Param path query string true "path of file"
|
||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /file/download [get]
|
// @Router /file/download [get]
|
||||||
func GetDownloadFile(c *gin.Context) {
|
func GetDownloadFile(c *gin.Context) {
|
||||||
@@ -155,15 +159,57 @@ func GetDownloadFile(c *gin.Context) {
|
|||||||
//获取文件的名称
|
//获取文件的名称
|
||||||
fileName := path.Base(filePath)
|
fileName := path.Base(filePath)
|
||||||
c.Header("Content-Type", "application/octet-stream")
|
c.Header("Content-Type", "application/octet-stream")
|
||||||
c.Header("Content-Disposition", "attachment; filename="+fileName)
|
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
|
||||||
c.Header("Content-Transfer-Encoding", "binary")
|
c.Header("Content-Transfer-Encoding", "binary")
|
||||||
c.Header("Cache-Control", "no-cache")
|
c.Header("Cache-Control", "no-cache")
|
||||||
c.Header("Content-Type", "application/octet-stream")
|
|
||||||
c.Header("Content-Disposition", "attachment; filename="+fileName)
|
|
||||||
c.Header("Content-Transfer-Encoding", "binary")
|
|
||||||
|
|
||||||
c.File(filePath)
|
c.File(filePath)
|
||||||
return
|
}
|
||||||
|
|
||||||
|
// @Summary download
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags file
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Param path query string true "path of file"
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /file/new/download [get]
|
||||||
|
func GetFileDownloadNew(c *gin.Context) {
|
||||||
|
filePath := c.Query("path")
|
||||||
|
if len(filePath) == 0 {
|
||||||
|
c.JSON(http.StatusOK, model.Result{
|
||||||
|
Success: oasis_err2.INVALID_PARAMS,
|
||||||
|
Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !file.Exists(filePath) {
|
||||||
|
c.JSON(http.StatusOK, model.Result{
|
||||||
|
Success: oasis_err2.FILE_DOES_NOT_EXIST,
|
||||||
|
Message: oasis_err2.GetMsg(oasis_err2.FILE_DOES_NOT_EXIST),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//打开文件
|
||||||
|
fileStat, _ := os.Stat(filePath)
|
||||||
|
var AppFs = afero.NewOsFs()
|
||||||
|
fileT, _ := AppFs.Open(filePath)
|
||||||
|
//fileTmp, _ := os.Open(filePath)
|
||||||
|
//defer fileTmp.Close()
|
||||||
|
//获取文件的名称
|
||||||
|
//fileName := path.Base(filePath)
|
||||||
|
|
||||||
|
//c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
|
||||||
|
//在线
|
||||||
|
//c.Header("Content-Disposition", "inline")
|
||||||
|
// extraHeaders := map[string]string{
|
||||||
|
// "Content-Disposition": `attachment; filename="` + url2.PathEscape(fileName) + `"`,
|
||||||
|
// }
|
||||||
|
|
||||||
|
//c.Header("Cache-Control", "private")
|
||||||
|
//c.Header("Content-Type", "application/octet-stream")
|
||||||
|
|
||||||
|
http.ServeContent(c.Writer, c.Request, fileStat.Name(), fileStat.ModTime(), fileT)
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary 获取目录列表
|
// @Summary 获取目录列表
|
||||||
@@ -175,18 +221,58 @@ func GetDownloadFile(c *gin.Context) {
|
|||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /file/dirpath [get]
|
// @Router /file/dirpath [get]
|
||||||
func DirPath(c *gin.Context) {
|
func DirPath(c *gin.Context) {
|
||||||
path := c.DefaultQuery("path", "/")
|
path := c.DefaultQuery("path", "")
|
||||||
info := service.MyService.ZiMa().GetDirPath(path)
|
info := service.MyService.ZiMa().GetDirPath(path)
|
||||||
|
if path == "/DATA/AppData" {
|
||||||
|
list := service.MyService.App().GetAllDBApps()
|
||||||
|
apps := make(map[string]string, len(list))
|
||||||
|
for _, v := range list {
|
||||||
|
apps[v.CustomId] = v.Label
|
||||||
|
}
|
||||||
|
for i := 0; i < len(info); i++ {
|
||||||
|
if v, ok := apps[info[i].Name]; ok {
|
||||||
|
info[i].Label = v
|
||||||
|
info[i].Type = "application"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if path == "/DATA" {
|
||||||
|
disk := make(map[string]string)
|
||||||
|
lsblk := service.MyService.Disk().LSBLK(true)
|
||||||
|
for _, v := range lsblk {
|
||||||
|
if len(v.Children) > 0 {
|
||||||
|
t := v.Tran
|
||||||
|
for _, c := range v.Children {
|
||||||
|
if len(c.Children) > 0 {
|
||||||
|
for _, gc := range c.Children {
|
||||||
|
if len(gc.MountPoint) > 0 {
|
||||||
|
disk[gc.MountPoint] = t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(c.MountPoint) > 0 {
|
||||||
|
disk[c.MountPoint] = t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := 0; i < len(info); i++ {
|
||||||
|
if v, ok := disk[info[i].Path]; ok {
|
||||||
|
info[i].Type = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary 重命名目录或文件
|
// @Summary rename file or dir
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept application/json
|
// @Accept application/json
|
||||||
// @Tags file
|
// @Tags file
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Param oldpath formData string true "旧的路径"
|
// @Param oldpath formData string true "path of old"
|
||||||
// @Param newpath formData string true "新路径"
|
// @Param newpath formData string true "path of new"
|
||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /file/rename [put]
|
// @Router /file/rename [put]
|
||||||
func RenamePath(c *gin.Context) {
|
func RenamePath(c *gin.Context) {
|
||||||
@@ -196,16 +282,16 @@ func RenamePath(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
service.MyService.ZiMa().RenameFile(op, np)
|
success, err := service.MyService.ZiMa().RenameFile(op, np)
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: success, Message: oasis_err2.GetMsg(success), Data: err})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary 创建文件夹
|
// @Summary create folder
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept multipart/form-data
|
// @Accept multipart/form-data
|
||||||
// @Tags file
|
// @Tags file
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Param path formData string false "路径"
|
// @Param path formData string true "path of folder"
|
||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /file/mkdir [post]
|
// @Router /file/mkdir [post]
|
||||||
func MkdirAll(c *gin.Context) {
|
func MkdirAll(c *gin.Context) {
|
||||||
@@ -219,7 +305,7 @@ func MkdirAll(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, model.Result{Success: code, Message: oasis_err2.GetMsg(code)})
|
c.JSON(http.StatusOK, model.Result{Success: code, Message: oasis_err2.GetMsg(code)})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary 创建文件
|
// @Summary create file
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept multipart/form-data
|
// @Accept multipart/form-data
|
||||||
// @Tags file
|
// @Tags file
|
||||||
@@ -238,21 +324,201 @@ func PostCreateFile(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, model.Result{Success: code, Message: oasis_err2.GetMsg(code)})
|
c.JSON(http.StatusOK, model.Result{Success: code, Message: oasis_err2.GetMsg(code)})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary 上传文件
|
// @Summary upload file
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept multipart/form-data
|
// @Accept multipart/form-data
|
||||||
// @Tags file
|
// @Tags file
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Param path formData string false "路径"
|
// @Param path formData string false "file path"
|
||||||
|
// @Param file formData file true "file"
|
||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /file/mkdir [post]
|
// @Router /file/upload [get]
|
||||||
func PostFileUpload(c *gin.Context) {
|
func GetFileUpload(c *gin.Context) {
|
||||||
file, _, _ := c.Request.FormFile("file")
|
|
||||||
//file.Read()
|
relative := c.Query("relativePath")
|
||||||
|
fileName := c.Query("filename")
|
||||||
|
chunkNumber := c.Query("chunkNumber")
|
||||||
|
totalChunks, _ := strconv.Atoi(c.DefaultQuery("totalChunks", "0"))
|
||||||
path := c.Query("path")
|
path := c.Query("path")
|
||||||
//上传文件
|
dirPath := ""
|
||||||
out, _ := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0644)
|
hash := file.GetHashByContent([]byte(fileName))
|
||||||
defer out.Close()
|
tempDir := "/casaOS/temp/" + hash + strconv.Itoa(totalChunks) + "/"
|
||||||
io.Copy(out, file)
|
if fileName != relative {
|
||||||
|
dirPath = strings.TrimSuffix(relative, fileName)
|
||||||
|
tempDir += dirPath
|
||||||
|
file.MkDir(path + "/" + dirPath)
|
||||||
|
}
|
||||||
|
tempDir += chunkNumber
|
||||||
|
if !file.CheckNotExist(tempDir) {
|
||||||
|
c.JSON(200, model.Result{Success: 200, Message: oasis_err2.GetMsg(oasis_err2.FILE_ALREADY_EXISTS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(204, model.Result{Success: 204, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary upload file
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept multipart/form-data
|
||||||
|
// @Tags file
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Param path formData string false "file path"
|
||||||
|
// @Param file formData file true "file"
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /file/upload [post]
|
||||||
|
func PostFileUpload(c *gin.Context) {
|
||||||
|
f, _, _ := c.Request.FormFile("file")
|
||||||
|
relative := c.PostForm("relativePath")
|
||||||
|
fileName := c.PostForm("filename")
|
||||||
|
totalChunks, _ := strconv.Atoi(c.DefaultPostForm("totalChunks", "0"))
|
||||||
|
chunkNumber := c.PostForm("chunkNumber")
|
||||||
|
dirPath := ""
|
||||||
|
path := c.PostForm("path")
|
||||||
|
|
||||||
|
hash := file.GetHashByContent([]byte(fileName))
|
||||||
|
|
||||||
|
if len(path) == 0 {
|
||||||
|
c.JSON(oasis_err2.INVALID_PARAMS, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tempDir := "/casaOS/temp/" + hash + strconv.Itoa(totalChunks) + "/"
|
||||||
|
|
||||||
|
if fileName != relative {
|
||||||
|
dirPath = strings.TrimSuffix(relative, fileName)
|
||||||
|
tempDir += dirPath
|
||||||
|
file.MkDir(path + "/" + dirPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
path += "/" + relative
|
||||||
|
|
||||||
|
if !file.CheckNotExist(tempDir + chunkNumber) {
|
||||||
|
file.RMDir(tempDir + chunkNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
if totalChunks > 1 {
|
||||||
|
file.IsNotExistMkDir(tempDir)
|
||||||
|
|
||||||
|
out, _ := os.OpenFile(tempDir+chunkNumber, os.O_WRONLY|os.O_CREATE, 0644)
|
||||||
|
defer out.Close()
|
||||||
|
_, err := io.Copy(out, f)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(oasis_err2.ERROR, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out, _ := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0644)
|
||||||
|
defer out.Close()
|
||||||
|
_, err := io.Copy(out, f)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(oasis_err2.ERROR, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fileNum, err := ioutil.ReadDir(tempDir)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(oasis_err2.ERROR, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if totalChunks == len(fileNum) {
|
||||||
|
file.SpliceFiles(tempDir, path, totalChunks, 1)
|
||||||
|
file.RMDir(tempDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary copy or move file
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept multipart/form-data
|
||||||
|
// @Tags file
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Param from formData string true "from path"
|
||||||
|
// @Param to formData string true "to path"
|
||||||
|
// @Param type formData string true "action" Enums(move,copy)
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /file/operate [post]
|
||||||
|
func PostOperateFileOrDir(c *gin.Context) {
|
||||||
|
from := c.PostForm("from")
|
||||||
|
to := c.PostForm("to")
|
||||||
|
t := c.PostForm("type")
|
||||||
|
if len(from) == 0 || len(t) == 0 || len(to) == 0 {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if t == "move" {
|
||||||
|
lastPath := from[strings.LastIndex(from, "/")+1:]
|
||||||
|
if !file.CheckNotExist(to + "/" + lastPath) {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_OR_DIR_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.FILE_ALREADY_EXISTS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err := os.Rename(from, to+"/"+lastPath)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else if t == "copy" {
|
||||||
|
err := file.CopyDir(from, to)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary delete file
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept multipart/form-data
|
||||||
|
// @Tags file
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Param path query string true "path"
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /file/delete [delete]
|
||||||
|
func DeleteFile(c *gin.Context) {
|
||||||
|
path := c.Query("path")
|
||||||
|
//err := os.Remove(path)
|
||||||
|
err := os.RemoveAll(path)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_DELETE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.FILE_DELETE_ERROR), Data: err})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary update file
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept multipart/form-data
|
||||||
|
// @Tags file
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Param path formData string true "path"
|
||||||
|
// @Param content formData string true "content"
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /file/update [put]
|
||||||
|
func PutFileContent(c *gin.Context) {
|
||||||
|
path := c.PostForm("path")
|
||||||
|
content := c.PostForm("content")
|
||||||
|
if !file.Exists(path) {
|
||||||
|
c.JSON(oasis_err2.FILE_ALREADY_EXISTS, model.Result{Success: oasis_err2.FILE_ALREADY_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.FILE_ALREADY_EXISTS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//err := os.Remove(path)
|
||||||
|
err := os.RemoveAll(path)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_DELETE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.FILE_DELETE_ERROR), Data: err})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = file.CreateFileAndWriteContent(path, content)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err})
|
||||||
|
return
|
||||||
|
}
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
json2 "encoding/json"
|
"fmt"
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"net/http"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
"github.com/IceWhaleTech/CasaOS/types"
|
"github.com/IceWhaleTech/CasaOS/types"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var upGrader = websocket.Upgrader{
|
var upGrader = websocket.Upgrader{
|
||||||
@@ -33,24 +31,17 @@ func NotifyWS(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer ws.Close()
|
defer ws.Close()
|
||||||
|
service.WebSocketConns = append(service.WebSocketConns, ws)
|
||||||
|
|
||||||
|
if !service.SocketRun {
|
||||||
|
service.SocketRun = true
|
||||||
|
service.SendMeg()
|
||||||
|
}
|
||||||
for {
|
for {
|
||||||
mt, message, err := ws.ReadMessage()
|
mt, message, err := ws.ReadMessage()
|
||||||
if err != nil {
|
fmt.Println(mt, message, err)
|
||||||
break
|
|
||||||
}
|
|
||||||
if string(message) != "notify" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for {
|
|
||||||
list := service.MyService.Notify().GetList()
|
|
||||||
json, _ := json2.Marshal(list)
|
|
||||||
err = ws.WriteMessage(mt, json)
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
time.Sleep(time.Second * 2)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary 标记notify已读
|
// @Summary 标记notify已读
|
||||||
@@ -62,9 +53,10 @@ func NotifyWS(c *gin.Context) {
|
|||||||
// @Router /notify/read/{id} [put]
|
// @Router /notify/read/{id} [put]
|
||||||
func PutNotifyRead(c *gin.Context) {
|
func PutNotifyRead(c *gin.Context) {
|
||||||
id := c.Param("id")
|
id := c.Param("id")
|
||||||
if len(id) == 0 {
|
// if len(id) == 0 {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
|
// c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
fmt.Println(id)
|
||||||
service.MyService.Notify().MarkRead(id, types.NOTIFY_READ)
|
service.MyService.Notify().MarkRead(id, types.NOTIFY_READ)
|
||||||
}
|
}
|
||||||
|
|||||||
496
route/v1/persion.go
Normal file
496
route/v1/persion.go
Normal file
@@ -0,0 +1,496 @@
|
|||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
|
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/types"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
uuid "github.com/satori/go.uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PersonTest(c *gin.Context) {
|
||||||
|
token := c.Query("token")
|
||||||
|
_, err := uuid.FromString(token)
|
||||||
|
fmt.Println(err)
|
||||||
|
|
||||||
|
//service.MyService.Person().GetPersionInfo("fb2333a1-72b2-4cb4-9e31-61ccaffa55b9")
|
||||||
|
|
||||||
|
msg := model.MessageModel{}
|
||||||
|
msg.Type = types.PERSONHELLO
|
||||||
|
msg.Data = ""
|
||||||
|
msg.From = config.ServerInfo.Token
|
||||||
|
msg.To = token
|
||||||
|
msg.UUId = uuid.NewV4().String()
|
||||||
|
|
||||||
|
dd, err := service.Dial(msg, true)
|
||||||
|
if err == nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
fmt.Println(dd)
|
||||||
|
user := service.MyService.Casa().GetUserInfoByShareId(token)
|
||||||
|
if reflect.DeepEqual(user, model.UserInfo{}) {
|
||||||
|
fmt.Println("空数据")
|
||||||
|
}
|
||||||
|
fmt.Println(user)
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Retry the file that failed to download
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags person
|
||||||
|
// @Param uui path string true "download uuid"
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /person/refile/{uuid} [get]
|
||||||
|
func GetPersonReFile(c *gin.Context) {
|
||||||
|
|
||||||
|
uid := c.Param("uuid")
|
||||||
|
_, err := uuid.FromString(uid)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
task := service.MyService.Download().GetDownloadById(uid)
|
||||||
|
if reflect.DeepEqual(task, model2.PersonDownloadDBModel{}) {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_REMOTE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.PERSON_REMOTE_ERROR)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
token := task.From
|
||||||
|
if _, ok := service.UDPAddressMap[token]; !ok {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_REMOTE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.PERSON_REMOTE_ERROR)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m := model.MessageModel{}
|
||||||
|
m.Data = task.Path
|
||||||
|
m.From = config.ServerInfo.Token
|
||||||
|
m.To = token
|
||||||
|
m.Type = types.PERSONDOWNLOAD
|
||||||
|
m.UUId = uid
|
||||||
|
go service.Dial(m, false)
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary download file
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags person
|
||||||
|
// @Param share_id query string true "opponent share_id"
|
||||||
|
// @Param path query string true "file path"
|
||||||
|
// @Param file_name query string true "file name"
|
||||||
|
// @Param local_path query string true "local_path"
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /person/file [get]
|
||||||
|
func GetPersonFile(c *gin.Context) {
|
||||||
|
|
||||||
|
path := c.Query("path")
|
||||||
|
localPath := c.Query("local_path")
|
||||||
|
token := c.Query("share_id")
|
||||||
|
fileName := c.Query("file_name")
|
||||||
|
_, err := uuid.FromString(token)
|
||||||
|
if len(path) == 0 || err != nil || len(localPath) == 0 || len(fileName) == 0 {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if file.CheckNotExist(localPath) {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.DIR_NOT_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.DIR_NOT_EXISTS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, ok := service.UDPAddressMap[token]; !ok {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_REMOTE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.PERSON_REMOTE_ERROR)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := service.UDPAddressMap[token]; !ok {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_REMOTE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.PERSON_REMOTE_ERROR)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// task id
|
||||||
|
uuid := uuid.NewV4().String()
|
||||||
|
|
||||||
|
task := model2.PersonDownloadDBModel{}
|
||||||
|
task.UUID = uuid
|
||||||
|
task.Name = fileName
|
||||||
|
task.Length = 0
|
||||||
|
task.From = token
|
||||||
|
task.Path = path
|
||||||
|
task.Size = 0
|
||||||
|
task.State = types.DOWNLOADAWAIT
|
||||||
|
task.Created = time.Now().Unix()
|
||||||
|
task.Type = 0
|
||||||
|
task.LocalPath = localPath
|
||||||
|
if service.MyService.Download().GetDownloadListByPath(task) > 0 {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_EXIST_DOWNLOAD, Message: oasis_err2.GetMsg(oasis_err2.PERSON_EXIST_DOWNLOAD)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
service.MyService.Download().AddDownloadTask(task)
|
||||||
|
|
||||||
|
m := model.MessageModel{}
|
||||||
|
m.Data = path
|
||||||
|
m.From = config.ServerInfo.Token
|
||||||
|
m.To = token
|
||||||
|
m.Type = types.PERSONDOWNLOAD
|
||||||
|
m.UUId = uuid
|
||||||
|
go service.Dial(m, false)
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary delete download file records
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags person
|
||||||
|
// @Param uuid path string true "download uuid"
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /person/file/{uuid} [delete]
|
||||||
|
func DeletePersonDownloadFile(c *gin.Context) {
|
||||||
|
|
||||||
|
id := c.Param("uuid")
|
||||||
|
_, err := uuid.FromString(id)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
task := service.MyService.Download().GetDownloadById(id)
|
||||||
|
if task.State == types.DOWNLOADING {
|
||||||
|
m := model.MessageModel{}
|
||||||
|
m.Data = ""
|
||||||
|
m.From = config.ServerInfo.Token
|
||||||
|
m.To = task.From
|
||||||
|
m.Type = types.PERSONCANCEL
|
||||||
|
m.UUId = task.UUID
|
||||||
|
service.CancelList[task.UUID] = task.UUID
|
||||||
|
service.Dial(m, false)
|
||||||
|
}
|
||||||
|
service.MyService.Download().DelDownload(id)
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Get file download list
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags person
|
||||||
|
// @Param state query int false "wait:0,downloading:1,pause:2,finish:3,error:4,finished:5" Enums(0,1,2,3,4,5)
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {object} []model2.PersonDownloadDBModel
|
||||||
|
// @Router /person/list [get]
|
||||||
|
func GetPersonDownloadList(c *gin.Context) {
|
||||||
|
state := c.DefaultQuery("state", "")
|
||||||
|
list := service.MyService.Download().GetDownloadListByState(state)
|
||||||
|
//if it is downloading, it need to add 'already'
|
||||||
|
for i := 0; i < len(list); i++ {
|
||||||
|
if list[i].State == types.DOWNLOADING {
|
||||||
|
tempDir := config.AppInfo.RootPath + "/temp" + "/" + list[i].UUID
|
||||||
|
files, err := ioutil.ReadDir(tempDir)
|
||||||
|
if err == nil {
|
||||||
|
list[i].Already = len(files)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list[i].Duration = time.Now().Unix() - list[i].Created
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary edit friend's remarks
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags person
|
||||||
|
// @Param remarks formData string true "remarks name"
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /person/remarks/{shareid} [put]
|
||||||
|
func PutPersonRemarks(c *gin.Context) {
|
||||||
|
token := c.Param("shareid")
|
||||||
|
_, err := uuid.FromString(token)
|
||||||
|
mark := c.PostForm("remarks")
|
||||||
|
if err != nil || len(mark) == 0 {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
friend := model2.FriendModel{}
|
||||||
|
friend.Token = token
|
||||||
|
friend.Mark = mark
|
||||||
|
service.MyService.Friend().EditFriendMark(friend)
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary get my friend list
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags person
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {object} []model2.FriendModel
|
||||||
|
// @Router /person/users [get]
|
||||||
|
func GetPersonFriend(c *gin.Context) {
|
||||||
|
list := service.MyService.Friend().GetFriendList()
|
||||||
|
for i := 0; i < len(list); i++ {
|
||||||
|
if v, ok := service.UDPAddressMap[list[i].Token]; ok && len(v) > 0 {
|
||||||
|
list[i].OnLine = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary add friend
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags person
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /person/user/{shareids} [post]
|
||||||
|
func PostAddPersonFriend(c *gin.Context) {
|
||||||
|
token := c.Param("shareids")
|
||||||
|
tokenList := strings.Split(token, ",")
|
||||||
|
|
||||||
|
for _, v := range tokenList {
|
||||||
|
_, err := uuid.FromString(v)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if v == config.ServerInfo.Token {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_MYSELF, Message: oasis_err2.GetMsg(oasis_err2.PERSON_MYSELF)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
udb := service.MyService.Friend().GetFriendById(model2.FriendModel{Token: v})
|
||||||
|
if !reflect.DeepEqual(udb, model2.FriendModel{Token: v}) {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_EXIST_FRIEND, Message: oasis_err2.GetMsg(oasis_err2.PERSON_EXIST_FRIEND)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
user := service.MyService.Casa().GetUserInfoByShareId(v)
|
||||||
|
if reflect.DeepEqual(user, model.UserInfo{}) {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_NOT_EXIST_USER, Message: oasis_err2.GetMsg(oasis_err2.PERSON_NOT_EXIST_USER)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
message := model.MessageModel{}
|
||||||
|
message.Type = types.PERSONCONNECTION
|
||||||
|
message.Data = v
|
||||||
|
message.From = config.ServerInfo.Token
|
||||||
|
message.To = v
|
||||||
|
message.UUId = uuid.NewV4().String()
|
||||||
|
|
||||||
|
go service.Dial(message, true)
|
||||||
|
|
||||||
|
friend := model2.FriendModel{}
|
||||||
|
friend.Token = v
|
||||||
|
friend.Avatar = user.Avatar
|
||||||
|
friend.Block = false
|
||||||
|
friend.NickName = user.NickName
|
||||||
|
friend.Profile = user.Desc
|
||||||
|
friend.Version = user.Version
|
||||||
|
service.MyService.Friend().AddFriend(friend)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Get a list of directories
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags person
|
||||||
|
// @Param share_id query string true "Opponent share_id"
|
||||||
|
// @Param path query string true "dir path"
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {object} []model.Path
|
||||||
|
// @Router /person/directory [get]
|
||||||
|
func GetPersonDirectory(c *gin.Context) {
|
||||||
|
path := c.Query("path")
|
||||||
|
token := c.Query("share_id")
|
||||||
|
_, err := uuid.FromString(token)
|
||||||
|
if len(path) == 0 || err != nil {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, ok := service.UDPAddressMap[token]; !ok {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_REMOTE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.PERSON_REMOTE_ERROR)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
uuid := uuid.NewV4().String()
|
||||||
|
m := model.MessageModel{}
|
||||||
|
m.Data = path
|
||||||
|
m.From = config.ServerInfo.Token
|
||||||
|
m.To = token
|
||||||
|
m.Type = types.PERSONDIRECTORY
|
||||||
|
m.UUId = uuid
|
||||||
|
result, err := service.Dial(m, false)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dataModel := []model.Path{}
|
||||||
|
if uuid == m.UUId {
|
||||||
|
dataModelByte, _ := json.Marshal(result.Data)
|
||||||
|
err := json.Unmarshal(dataModelByte, &dataModel)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: dataModel})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Modify the download storage directory
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept multipart/form-data
|
||||||
|
// @Tags person
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Param path formData string true "path"
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /person/down/dir [post]
|
||||||
|
func PostPersonDownDir(c *gin.Context) {
|
||||||
|
|
||||||
|
downPath := c.PostForm("path")
|
||||||
|
|
||||||
|
if len(downPath) == 0 {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if file.CheckNotExist(downPath) {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.DIR_NOT_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.DIR_NOT_EXISTS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
config.Cfg.Section("file").Key("DownloadDir").SetValue(downPath)
|
||||||
|
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||||
|
config.FileSettingInfo.DownloadDir = downPath
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Get the download storage directory
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags person
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /person/down/dir [get]
|
||||||
|
func GetPersonDownDir(c *gin.Context) {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: config.FileSettingInfo.DownloadDir})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Modify the shared directory
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept multipart/form-data
|
||||||
|
// @Tags person
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Param share formData string true "share"
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /person/share [post]
|
||||||
|
func PostPersonShare(c *gin.Context) {
|
||||||
|
|
||||||
|
share := c.PostForm("share")
|
||||||
|
|
||||||
|
if len(share) == 0 {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var list []string
|
||||||
|
json.Unmarshal([]byte(share), &list)
|
||||||
|
|
||||||
|
if len(list) == 0 {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, v := range list {
|
||||||
|
if !file.Exists(v) {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_ALREADY_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.FILE_ALREADY_EXISTS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
config.Cfg.Section("file").Key("ShareDir").SetValue(strings.Join(list, "|"))
|
||||||
|
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||||
|
config.FileSettingInfo.ShareDir = list
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Get the shared directory
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags person
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /person/share [get]
|
||||||
|
func GetPersonShare(c *gin.Context) {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: config.FileSettingInfo.ShareDir})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Modify disabled status
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags person
|
||||||
|
// @Param block formData bool false "Disable or not,Default:false "
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /person/block/{shareid} [put]
|
||||||
|
func PutPersonBlock(c *gin.Context) {
|
||||||
|
token := c.Param("shareid")
|
||||||
|
_, err := uuid.FromString(token)
|
||||||
|
block, _ := strconv.ParseBool(c.PostForm("block"))
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
friend := model2.FriendModel{}
|
||||||
|
friend.Token = token
|
||||||
|
friend.Block = block
|
||||||
|
service.MyService.Friend().EditFriendBlock(friend)
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Delete my friend
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags person
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /person/user/{shareid} [delete]
|
||||||
|
func DeletePersonFriend(c *gin.Context) {
|
||||||
|
token := c.Param("shareid")
|
||||||
|
_, err := uuid.FromString(token)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
friend := model2.FriendModel{}
|
||||||
|
friend.Token = token
|
||||||
|
|
||||||
|
service.MyService.Friend().DeleteFriend(friend)
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Get public person
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags person
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /person/public [delete]
|
||||||
|
func GetPersonPublic(c *gin.Context) {
|
||||||
|
list := service.MyService.Casa().GetPersonPublic()
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
|
||||||
|
}
|
||||||
35
route/v1/sync.go
Normal file
35
route/v1/sync.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/http/httputil"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SyncToSyncthing(c *gin.Context) {
|
||||||
|
u := c.Param("url")
|
||||||
|
target := "http://" + strings.Split(c.Request.Host, ":")[0] + ":" + config.SystemConfigInfo.SyncPort
|
||||||
|
remote, err := url.Parse(target)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
proxy := httputil.NewSingleHostReverseProxy(remote)
|
||||||
|
c.Request.Header.Add("X-API-Key", config.SystemConfigInfo.SyncKey)
|
||||||
|
//c.Request.Header.Add("X-API-Key", config.SystemConfigInfo.SyncKey)
|
||||||
|
c.Request.URL.Path = u
|
||||||
|
|
||||||
|
proxy.ServeHTTP(c.Writer, c.Request)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSyncConfig(c *gin.Context) {
|
||||||
|
data := make(map[string]string)
|
||||||
|
data["key"] = config.SystemConfigInfo.SyncKey
|
||||||
|
data["port"] = config.SystemConfigInfo.SyncPort
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: data})
|
||||||
|
}
|
||||||
@@ -4,12 +4,18 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||||
|
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||||
|
port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/version"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/version"
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
@@ -80,7 +86,7 @@ func GetCasaOSErrorLogs(c *gin.Context) {
|
|||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept multipart/form-data
|
// @Accept multipart/form-data
|
||||||
// @Tags sys
|
// @Tags sys
|
||||||
// @Param file formData file true "用户头像"
|
// @Param config formData string true "config json string"
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /sys/changhead [post]
|
// @Router /sys/changhead [post]
|
||||||
@@ -102,9 +108,33 @@ func GetSystemConfigDebug(c *gin.Context) {
|
|||||||
|
|
||||||
array := service.MyService.System().GetSystemConfigDebug()
|
array := service.MyService.System().GetSystemConfigDebug()
|
||||||
disk := service.MyService.ZiMa().GetDiskInfo()
|
disk := service.MyService.ZiMa().GetDiskInfo()
|
||||||
array = append(array, fmt.Sprintf("disk,totle:%v,used:%v,UsedPercent:%v", disk.Total>>20, disk.Used>>20, disk.UsedPercent))
|
sys := service.MyService.ZiMa().GetSysInfo()
|
||||||
|
//todo 准备sync需要显示的数据(镜像,容器)
|
||||||
|
var systemAppStatus string
|
||||||
|
images := service.MyService.Docker().IsExistImage("linuxserver/syncthing")
|
||||||
|
systemAppStatus += "Sync img: " + strconv.FormatBool(images) + "\n\t"
|
||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: array})
|
list := service.MyService.App().GetSystemAppList()
|
||||||
|
for _, v := range *list {
|
||||||
|
systemAppStatus += v.Image + ",\n\t"
|
||||||
|
}
|
||||||
|
|
||||||
|
systemAppStatus += "Sync Key length: " + strconv.Itoa(len(config.SystemConfigInfo.SyncKey))
|
||||||
|
|
||||||
|
var bugContent string = fmt.Sprintf(`
|
||||||
|
- OS: %s
|
||||||
|
- CasaOS Version: %s
|
||||||
|
- Disk Total: %v
|
||||||
|
- Disk Used: %v
|
||||||
|
- Sync State: %s
|
||||||
|
- System Info: %s
|
||||||
|
- Browser: $Browser$
|
||||||
|
- Version: $Version$
|
||||||
|
`, sys.OS, types.CURRENTVERSION, disk.Total>>20, disk.Used>>20, systemAppStatus, array)
|
||||||
|
|
||||||
|
// array = append(array, fmt.Sprintf("disk,total:%v,used:%v,UsedPercent:%v", disk.Total>>20, disk.Used>>20, disk.UsedPercent))
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: bugContent})
|
||||||
}
|
}
|
||||||
func Sys(c *gin.Context) {
|
func Sys(c *gin.Context) {
|
||||||
service.DockerPull()
|
service.DockerPull()
|
||||||
@@ -125,8 +155,9 @@ func GetWidgetConfig(c *gin.Context) {
|
|||||||
func PostSetWidgetConfig(c *gin.Context) {
|
func PostSetWidgetConfig(c *gin.Context) {
|
||||||
buf := make([]byte, 1024)
|
buf := make([]byte, 1024)
|
||||||
n, _ := c.Request.Body.Read(buf)
|
n, _ := c.Request.Body.Read(buf)
|
||||||
|
fmt.Println("错误", strconv.Itoa(n))
|
||||||
service.MyService.System().UpSystemConfig("", string(buf[0:n]))
|
service.MyService.System().UpSystemConfig("", string(buf[0:n]))
|
||||||
|
fmt.Println("错误1", string(buf[0:n]))
|
||||||
c.JSON(http.StatusOK,
|
c.JSON(http.StatusOK,
|
||||||
model.Result{
|
model.Result{
|
||||||
Success: oasis_err.SUCCESS,
|
Success: oasis_err.SUCCESS,
|
||||||
@@ -135,6 +166,58 @@ func PostSetWidgetConfig(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Summary get casaos server port
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags sys
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /sys/port [get]
|
||||||
|
func GetCasaOSPort(c *gin.Context) {
|
||||||
|
c.JSON(http.StatusOK,
|
||||||
|
model.Result{
|
||||||
|
Success: oasis_err.SUCCESS,
|
||||||
|
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
|
||||||
|
Data: config.ServerInfo.HttpPort,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary edit casaos server port
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags sys
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Param port formData string true "port"
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /sys/port [put]
|
||||||
|
func PutCasaOSPort(c *gin.Context) {
|
||||||
|
port, err := strconv.Atoi(c.PostForm("port"))
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusOK,
|
||||||
|
model.Result{
|
||||||
|
Success: oasis_err.ERROR,
|
||||||
|
Message: err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
isAvailable := port2.IsPortAvailable(port, "tcp")
|
||||||
|
if !isAvailable {
|
||||||
|
c.JSON(http.StatusOK,
|
||||||
|
model.Result{
|
||||||
|
Success: oasis_err.PORT_IS_OCCUPIED,
|
||||||
|
Message: oasis_err.GetMsg(oasis_err.PORT_IS_OCCUPIED),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
service.MyService.System().UpSystemPort(strconv.Itoa(port))
|
||||||
|
c.JSON(http.StatusOK,
|
||||||
|
model.Result{
|
||||||
|
Success: oasis_err.SUCCESS,
|
||||||
|
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// @Summary 检查是否进入引导状态
|
// @Summary 检查是否进入引导状态
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept application/json
|
// @Accept application/json
|
||||||
@@ -156,3 +239,203 @@ func GetGuideCheck(c *gin.Context) {
|
|||||||
Data: data,
|
Data: data,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Summary active killing casaos
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags sys
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /sys/kill [post]
|
||||||
|
func PostKillCasaOS(c *gin.Context) {
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Turn off usb auto-mount
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags sys
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /sys/usg/off [put]
|
||||||
|
func PutSystemOffUSBAutoMount(c *gin.Context) {
|
||||||
|
service.MyService.System().UpdateUSBAutoMount("False")
|
||||||
|
service.MyService.System().ExecUSBAutoMountShell("False")
|
||||||
|
c.JSON(http.StatusOK,
|
||||||
|
model.Result{
|
||||||
|
Success: oasis_err.SUCCESS,
|
||||||
|
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Turn off usb auto-mount
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags sys
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /sys/usb [get]
|
||||||
|
func GetSystemUSBAutoMount(c *gin.Context) {
|
||||||
|
state := "True"
|
||||||
|
if config.ServerInfo.USBAutoMount == "False" {
|
||||||
|
state = "False"
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK,
|
||||||
|
model.Result{
|
||||||
|
Success: oasis_err.SUCCESS,
|
||||||
|
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
|
||||||
|
Data: state,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Turn off usb auto-mount
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags sys
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /sys/usb/on [put]
|
||||||
|
func PutSystemOnUSBAutoMount(c *gin.Context) {
|
||||||
|
service.MyService.System().UpdateUSBAutoMount("True")
|
||||||
|
service.MyService.System().ExecUSBAutoMountShell("True")
|
||||||
|
c.JSON(http.StatusOK,
|
||||||
|
model.Result{
|
||||||
|
Success: oasis_err.SUCCESS,
|
||||||
|
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary system info
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags sys
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /sys/info [get]
|
||||||
|
func Info(c *gin.Context) {
|
||||||
|
var data = make(map[string]interface{}, 6)
|
||||||
|
|
||||||
|
list := service.MyService.Disk().LSBLK(true)
|
||||||
|
|
||||||
|
summary := model.Summary{}
|
||||||
|
healthy := true
|
||||||
|
findSystem := 0
|
||||||
|
|
||||||
|
for i := 0; i < len(list); i++ {
|
||||||
|
if len(list[i].Children) > 0 && findSystem == 0 {
|
||||||
|
|
||||||
|
for j := 0; j < len(list[i].Children); j++ {
|
||||||
|
|
||||||
|
if len(list[i].Children[j].Children) > 0 {
|
||||||
|
for _, v := range list[i].Children[j].Children {
|
||||||
|
if v.MountPoint == "/" {
|
||||||
|
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
|
||||||
|
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
|
||||||
|
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
|
||||||
|
summary.Size += s
|
||||||
|
summary.Avail += a
|
||||||
|
summary.Used += u
|
||||||
|
findSystem = 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if list[i].Children[j].MountPoint == "/" {
|
||||||
|
s, _ := strconv.ParseUint(list[i].Children[j].FSSize, 10, 64)
|
||||||
|
a, _ := strconv.ParseUint(list[i].Children[j].FSAvail, 10, 64)
|
||||||
|
u, _ := strconv.ParseUint(list[i].Children[j].FSUsed, 10, 64)
|
||||||
|
summary.Size += s
|
||||||
|
summary.Avail += a
|
||||||
|
summary.Used += u
|
||||||
|
findSystem = 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if findSystem == 1 {
|
||||||
|
findSystem += 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" {
|
||||||
|
temp := service.MyService.Disk().SmartCTL(list[i].Path)
|
||||||
|
if reflect.DeepEqual(temp, model.SmartctlA{}) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
//list[i].Temperature = temp.Temperature.Current
|
||||||
|
if !temp.SmartStatus.Passed {
|
||||||
|
healthy = false
|
||||||
|
}
|
||||||
|
if len(list[i].Children) > 0 {
|
||||||
|
for _, v := range list[i].Children {
|
||||||
|
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
|
||||||
|
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
|
||||||
|
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
|
||||||
|
summary.Size += s
|
||||||
|
summary.Avail += a
|
||||||
|
summary.Used += u
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
summary.Health = healthy
|
||||||
|
data["disk"] = summary
|
||||||
|
usbList := service.MyService.Disk().LSBLK(false)
|
||||||
|
usb := []model.DriveUSB{}
|
||||||
|
for _, v := range usbList {
|
||||||
|
if v.Tran == "usb" {
|
||||||
|
temp := model.DriveUSB{}
|
||||||
|
temp.Model = v.Model
|
||||||
|
temp.Name = v.Name
|
||||||
|
temp.Size = v.Size
|
||||||
|
mountTemp := true
|
||||||
|
if len(v.Children) == 0 {
|
||||||
|
mountTemp = false
|
||||||
|
}
|
||||||
|
for _, child := range v.Children {
|
||||||
|
if len(child.MountPoint) > 0 {
|
||||||
|
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
|
||||||
|
temp.Avail += avail
|
||||||
|
used, _ := strconv.ParseUint(child.FSUsed, 10, 64)
|
||||||
|
temp.Used += used
|
||||||
|
} else {
|
||||||
|
mountTemp = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
temp.Mount = mountTemp
|
||||||
|
usb = append(usb, temp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data["usb"] = usb
|
||||||
|
cpu := service.MyService.ZiMa().GetCpuPercent()
|
||||||
|
num := service.MyService.ZiMa().GetCpuCoreNum()
|
||||||
|
cpuData := make(map[string]interface{})
|
||||||
|
cpuData["percent"] = cpu
|
||||||
|
cpuData["num"] = num
|
||||||
|
data["cpu"] = cpuData
|
||||||
|
data["mem"] = service.MyService.ZiMa().GetMemInfo()
|
||||||
|
|
||||||
|
//拼装网络信息
|
||||||
|
netList := service.MyService.ZiMa().GetNetInfo()
|
||||||
|
newNet := []model.IOCountersStat{}
|
||||||
|
nets := service.MyService.ZiMa().GetNet(true)
|
||||||
|
for _, n := range netList {
|
||||||
|
for _, netCardName := range nets {
|
||||||
|
if n.Name == netCardName {
|
||||||
|
item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
|
||||||
|
item.State = strings.TrimSpace(service.MyService.ZiMa().GetNetState(n.Name))
|
||||||
|
item.Time = time.Now().Unix()
|
||||||
|
newNet = append(newNet, item)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data["net"] = newNet
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
|
||||||
|
}
|
||||||
|
|||||||
138
route/v1/user.go
138
route/v1/user.go
@@ -40,7 +40,7 @@ func Set_Name_Pwd(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
//开始设置
|
//开始设置
|
||||||
err := user_service.SetUser(username, pwd, "", "", "")
|
err := user_service.SetUser(username, pwd, "", "", "", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: fmt.Sprintf("%v", err)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: fmt.Sprintf("%v", err)})
|
||||||
return
|
return
|
||||||
@@ -102,7 +102,7 @@ func Login(c *gin.Context) {
|
|||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /user/changhead [post]
|
// @Router /user/changhead [post]
|
||||||
func Up_Load_Head(c *gin.Context) {
|
func PostUserHead(c *gin.Context) {
|
||||||
file, _, _ := c.Request.FormFile("file")
|
file, _, _ := c.Request.FormFile("file")
|
||||||
user_service.UpLoadFile(file, config.UserInfo.Head)
|
user_service.UpLoadFile(file, config.UserInfo.Head)
|
||||||
c.JSON(http.StatusOK,
|
c.JSON(http.StatusOK,
|
||||||
@@ -121,15 +121,19 @@ func Up_Load_Head(c *gin.Context) {
|
|||||||
// @Param oldname formData string true "Old user name"
|
// @Param oldname formData string true "Old user name"
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /user/changusername [put]
|
// @Router /user/username [put]
|
||||||
func Chang_User_Name(c *gin.Context) {
|
func PutUserName(c *gin.Context) {
|
||||||
|
if config.ServerInfo.LockAccount {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ACCOUNT_LOCK, Message: oasis_err2.GetMsg(oasis_err2.ACCOUNT_LOCK)})
|
||||||
|
return
|
||||||
|
}
|
||||||
oldname := c.PostForm("oldname")
|
oldname := c.PostForm("oldname")
|
||||||
username := c.PostForm("username")
|
username := c.PostForm("username")
|
||||||
if len(username) == 0 || config.UserInfo.UserName != oldname {
|
if len(username) == 0 || config.UserInfo.UserName != oldname {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user_service.SetUser(username, "", "", "", "")
|
user_service.SetUser(username, "", "", "", "", "")
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,68 +142,145 @@ func Chang_User_Name(c *gin.Context) {
|
|||||||
// @Accept multipart/form-data
|
// @Accept multipart/form-data
|
||||||
// @Tags user
|
// @Tags user
|
||||||
// @Param pwd formData string true "Password"
|
// @Param pwd formData string true "Password"
|
||||||
// @Param oldpwd formData string true "Old password"
|
// @Param old_pwd formData string true "Old password"
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /user/changuserpwd [put]
|
// @Router /user/password [put]
|
||||||
func Chang_User_Pwd(c *gin.Context) {
|
func PutUserPwd(c *gin.Context) {
|
||||||
oldpwd := c.PostForm("oldpwd")
|
oldPwd := c.PostForm("old_pwd")
|
||||||
pwd := c.PostForm("pwd")
|
pwd := c.PostForm("pwd")
|
||||||
if config.UserInfo.PWD != oldpwd {
|
if config.UserInfo.PWD != oldPwd {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PWD_INVALID_OLD, Message: oasis_err2.GetMsg(oasis_err2.PWD_INVALID_OLD)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PWD_INVALID_OLD, Message: oasis_err2.GetMsg(oasis_err2.PWD_INVALID_OLD)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if config.ServerInfo.LockAccount {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ACCOUNT_LOCK, Message: oasis_err2.GetMsg(oasis_err2.ACCOUNT_LOCK)})
|
||||||
|
return
|
||||||
|
}
|
||||||
if len(pwd) == 0 {
|
if len(pwd) == 0 {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PWD_IS_EMPTY, Message: oasis_err2.GetMsg(oasis_err2.PWD_IS_EMPTY)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PWD_IS_EMPTY, Message: oasis_err2.GetMsg(oasis_err2.PWD_IS_EMPTY)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user_service.SetUser("", pwd, "", "", "")
|
user_service.SetUser("", pwd, "", "", "", "")
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary 修改用户信息
|
// @Summary edit user info
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept multipart/form-data
|
// @Accept multipart/form-data
|
||||||
// @Tags user
|
// @Tags user
|
||||||
// @Param username formData string false "User Name"
|
// @Param user_name formData string false "User Name"
|
||||||
// @Param email formData string false "Email"
|
// @Param email formData string false "Email"
|
||||||
// @Param description formData string false "Description"
|
// @Param description formData string false "Description"
|
||||||
// @Param pwd formData string false "Password"
|
// @Param pwd formData string false "Password"
|
||||||
// @Param oldpwd formData string false "Old password"
|
// @Param old_pwd formData string false "Old password"
|
||||||
|
// @Param nick_name formData string false "nick name"
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /user/changuserinfo [post]
|
// @Router /user/info [post]
|
||||||
func Chang_User_Info(c *gin.Context) {
|
func PostUserChangeInfo(c *gin.Context) {
|
||||||
username := c.PostForm("username")
|
username := c.PostForm("user_name")
|
||||||
email := c.PostForm("email")
|
email := c.PostForm("email")
|
||||||
description := c.PostForm("description")
|
description := c.PostForm("description")
|
||||||
oldpwd := c.PostForm("oldpwd")
|
nickName := c.PostForm("nick_name")
|
||||||
|
oldpwd := c.PostForm("old_pwd")
|
||||||
pwd := c.PostForm("pwd")
|
pwd := c.PostForm("pwd")
|
||||||
if len(pwd) > 0 && config.UserInfo.PWD != oldpwd {
|
if len(pwd) > 0 && config.UserInfo.PWD != oldpwd {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PWD_INVALID, Message: oasis_err2.GetMsg(oasis_err2.PWD_INVALID)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PWD_INVALID, Message: oasis_err2.GetMsg(oasis_err2.PWD_INVALID)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user_service.SetUser(username, pwd, "", email, description)
|
user_service.SetUser(username, pwd, "", email, description, nickName)
|
||||||
data := make(map[string]string, 2)
|
data := make(map[string]string, 4)
|
||||||
|
|
||||||
data["token"] = jwt2.GetToken(username, pwd)
|
data["token"] = jwt2.GetToken(username, pwd)
|
||||||
data["user_name"] = username
|
data["user_name"] = username
|
||||||
data["head"] = config.UserInfo.Head
|
data["head"] = config.UserInfo.Head
|
||||||
|
data["nick_name"] = config.UserInfo.NickName
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary 获取用户详情
|
// @Summary edit user nick
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept multipart/form-data
|
||||||
|
// @Tags user
|
||||||
|
// @Param nick_name formData string false "nick name"
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /user/nick [put]
|
||||||
|
func PutUserChangeNick(c *gin.Context) {
|
||||||
|
|
||||||
|
nickName := c.PostForm("nick_name")
|
||||||
|
|
||||||
|
if len(nickName) == 0 {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
user_service.SetUser("", "", "", "", "", nickName)
|
||||||
|
data := make(map[string]string, 1)
|
||||||
|
data["nick_name"] = config.UserInfo.NickName
|
||||||
|
go service.MyService.Casa().PushUserInfo()
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary edit user description
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept multipart/form-data
|
||||||
|
// @Tags user
|
||||||
|
// @Param description formData string false "Description"
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /user/desc [put]
|
||||||
|
func PutUserChangeDesc(c *gin.Context) {
|
||||||
|
desc := c.PostForm("description")
|
||||||
|
|
||||||
|
if len(desc) == 0 {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
user_service.SetUser("", "", "", "", desc, "")
|
||||||
|
data := make(map[string]string, 1)
|
||||||
|
data["description"] = config.UserInfo.Description
|
||||||
|
go service.MyService.Casa().PushUserInfo()
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Modify user person information (Initialization use)
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept multipart/form-data
|
||||||
|
// @Tags user
|
||||||
|
// @Param nick_name formData string false "user nick name"
|
||||||
|
// @Param description formData string false "Description"
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /user/person/info [post]
|
||||||
|
func PostUserPersonInfo(c *gin.Context) {
|
||||||
|
desc := c.PostForm("description")
|
||||||
|
nickName := c.PostForm("nick_name")
|
||||||
|
if len(desc) == 0 || len(nickName) == 0 {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
user_service.SetUser("", "", "", "", desc, nickName)
|
||||||
|
data := make(map[string]string, 2)
|
||||||
|
data["description"] = config.UserInfo.Description
|
||||||
|
data["nick_name"] = config.UserInfo.NickName
|
||||||
|
go service.MyService.Casa().PushUserInfo()
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary get user info
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept mapplication/json
|
// @Accept mapplication/json
|
||||||
// @Tags user
|
// @Tags user
|
||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /user/info [get]
|
// @Router /user/info [get]
|
||||||
func UserInfo(c *gin.Context) {
|
func GetUserInfo(c *gin.Context) {
|
||||||
var u = make(map[string]string, 2)
|
var u = make(map[string]string, 5)
|
||||||
u["user_name"] = config.UserInfo.UserName
|
u["user_name"] = config.UserInfo.UserName
|
||||||
u["head"] = config.UserInfo.Head
|
u["head"] = config.UserInfo.Head
|
||||||
u["email"] = config.UserInfo.Email
|
u["email"] = config.UserInfo.Email
|
||||||
u["description"] = config.UserInfo.Description
|
u["description"] = config.UserInfo.Description
|
||||||
|
u["nick_name"] = config.UserInfo.NickName
|
||||||
c.JSON(http.StatusOK,
|
c.JSON(http.StatusOK,
|
||||||
model.Result{
|
model.Result{
|
||||||
Success: oasis_err2.SUCCESS,
|
Success: oasis_err2.SUCCESS,
|
||||||
@@ -207,3 +288,14 @@ func UserInfo(c *gin.Context) {
|
|||||||
Data: u,
|
Data: u,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Summary Get my shareId
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags user
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /user/shareid [get]
|
||||||
|
func GetUserShareID(c *gin.Context) {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: config.ServerInfo.Token})
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,459 +0,0 @@
|
|||||||
package v1
|
|
||||||
|
|
||||||
import (
|
|
||||||
json2 "encoding/json"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
|
||||||
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
// @Summary 登录zerotier获取token
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept multipart/form-data
|
|
||||||
// @Tags zerotier
|
|
||||||
// @Param username formData string true "User name"
|
|
||||||
// @Param pwd formData string true "password"
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /zerotier/login [post]
|
|
||||||
func ZeroTierGetToken(c *gin.Context) {
|
|
||||||
username := c.PostForm("username")
|
|
||||||
pwd := c.PostForm("pwd")
|
|
||||||
if len(username) == 0 || len(pwd) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
errInfo := service.MyService.ZeroTier().GetToken(username, pwd)
|
|
||||||
|
|
||||||
if len(errInfo) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.GET_TOKEN_ERROR)})
|
|
||||||
} else {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 注册zerotier
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept multipart/form-data
|
|
||||||
// @Tags zerotier
|
|
||||||
// @Param firstName formData string true "first name"
|
|
||||||
// @Param pwd formData string true "password"
|
|
||||||
// @Param email formData string true "email"
|
|
||||||
// @Param lastName formData string true "last name"
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /zerotier/register [post]
|
|
||||||
func ZeroTierRegister(c *gin.Context) {
|
|
||||||
firstName := c.PostForm("firstName")
|
|
||||||
pwd := c.PostForm("pwd")
|
|
||||||
email := c.PostForm("email")
|
|
||||||
lastName := c.PostForm("lastName")
|
|
||||||
if len(firstName) == 0 || len(pwd) == 0 || len(email) == 0 || len(lastName) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
errInfo := service.MyService.ZeroTier().ZeroTierRegister(email, lastName, firstName, pwd)
|
|
||||||
if len(errInfo) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
|
||||||
} else {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: errInfo})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 是否需要登录zerotier
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags zerotier
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "false:需要登录,true:不需要登录"
|
|
||||||
// @Router /zerotier/islogin [get]
|
|
||||||
func ZeroTierIsNeedLogin(c *gin.Context) {
|
|
||||||
if len(config.ZeroTierInfo.Token) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: false})
|
|
||||||
} else {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: true})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 获取zerotier网络列表
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags zerotier
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /zerotier/list [get]
|
|
||||||
func ZeroTierGetNetworkList(c *gin.Context) {
|
|
||||||
jsonList, joined := service.MyService.ZeroTier().ZeroTierNetworkList(config.ZeroTierInfo.Token)
|
|
||||||
rdata := make(map[string]interface{})
|
|
||||||
rdata["network_list"] = jsonList
|
|
||||||
rdata["joined"] = joined
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: rdata})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 获取zerotier网络详情
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags zerotier
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param id path string true "network id"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /zerotier/info/{id} [get]
|
|
||||||
func ZeroTierGetNetworkGetInfo(c *gin.Context) {
|
|
||||||
id := c.Param("id")
|
|
||||||
if len(id) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
info, joined := service.MyService.ZeroTier().ZeroTierGetInfo(config.ZeroTierInfo.Token, id)
|
|
||||||
rdata := make(map[string]interface{})
|
|
||||||
rdata["info"] = info
|
|
||||||
rdata["joined"] = joined
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: rdata})
|
|
||||||
}
|
|
||||||
|
|
||||||
//// @Summary 获取zerotier网络状态
|
|
||||||
//// @Produce application/json
|
|
||||||
//// @Accept application/json
|
|
||||||
//// @Tags zerotier
|
|
||||||
//// @Security ApiKeyAuth
|
|
||||||
//// @Success 200 {string} string "ok"
|
|
||||||
//// @Router /zerotier/status [get]
|
|
||||||
//func ZeroTierGetNetworkGetStatus(c *gin.Context) {
|
|
||||||
// status := service.MyService.ZeroTier().ZeroTierGetStatus(config.ZeroTierInfo.Token)
|
|
||||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: status})
|
|
||||||
//}
|
|
||||||
|
|
||||||
//// @Summary 修改网络类型
|
|
||||||
//// @Produce application/json
|
|
||||||
//// @Accept application/json
|
|
||||||
//// @Tags zerotier
|
|
||||||
//// @Security ApiKeyAuth
|
|
||||||
//// @Param id path string true "network id"
|
|
||||||
//// @Param type formData string true "Private true/false"
|
|
||||||
//// @Success 200 {string} string "ok"
|
|
||||||
//// @Router /zerotier/type/{id} [put]
|
|
||||||
//func ZeroTierEditType(c *gin.Context) {
|
|
||||||
// id := c.Param("id")
|
|
||||||
// t := c.PostForm("type")
|
|
||||||
// if len(id) == 0 || len(t) == 0 {
|
|
||||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// postData := `{"config":{"private":` + t + `}}`
|
|
||||||
// info := service.MyService.ZeroTier().EditNetwork(config.ZeroTierInfo.Token, postData, id)
|
|
||||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
|
|
||||||
//}
|
|
||||||
|
|
||||||
//// @Summary 修改名称
|
|
||||||
//// @Produce application/json
|
|
||||||
//// @Accept application/json
|
|
||||||
//// @Tags zerotier
|
|
||||||
//// @Security ApiKeyAuth
|
|
||||||
//// @Param id path string true "network id"
|
|
||||||
//// @Param name formData string true "需要过滤特殊字符串"
|
|
||||||
//// @Success 200 {string} string "ok"
|
|
||||||
//// @Router /zerotier/name/{id} [put]
|
|
||||||
//func ZeroTierEditName(c *gin.Context) {
|
|
||||||
// id := c.Param("id")
|
|
||||||
// name := c.PostForm("name")
|
|
||||||
// if len(id) == 0 || len(name) == 0 {
|
|
||||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// postData := `{"config":{"name":"` + name + `"}}`
|
|
||||||
// info := service.MyService.ZeroTier().EditNetwork(config.ZeroTierInfo.Token, postData, id)
|
|
||||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
|
|
||||||
//}
|
|
||||||
|
|
||||||
//// @Summary V6Assign (注意三个属性需要一起传过来,不传的会被zerotier设置成false)
|
|
||||||
//// @Produce application/json
|
|
||||||
//// @Accept application/json
|
|
||||||
//// @Tags zerotier
|
|
||||||
//// @Security ApiKeyAuth
|
|
||||||
//// @Param id path string true "network id"
|
|
||||||
//// @Param v6plan formData string false "true/false"
|
|
||||||
//// @Param rfc formData string false "true/false"
|
|
||||||
//// @Param auto formData string false "true/false"
|
|
||||||
//// @Success 200 {string} string "ok"
|
|
||||||
//// @Router /zerotier/v6assign/{id} [put]
|
|
||||||
//func ZeroTierEditV6Assign(c *gin.Context) {
|
|
||||||
// id := c.Param("id")
|
|
||||||
// v6plan := c.PostForm("v6plan")
|
|
||||||
// rfc := c.PostForm("rfc")
|
|
||||||
// auto := c.PostForm("auto")
|
|
||||||
// if len(id) == 0 {
|
|
||||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// var spicing string
|
|
||||||
// if len(v6plan) > 0 {
|
|
||||||
// spicing = `"6plane":` + v6plan
|
|
||||||
// }
|
|
||||||
// if len(rfc) > 0 {
|
|
||||||
// if len(spicing) > 0 {
|
|
||||||
// spicing += ","
|
|
||||||
// }
|
|
||||||
// spicing += `"rfc4193":` + rfc
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if len(auto) > 0 {
|
|
||||||
// if len(spicing) > 0 {
|
|
||||||
// spicing += ","
|
|
||||||
// }
|
|
||||||
// spicing += `"zt":` + auto
|
|
||||||
// }
|
|
||||||
// postData := `{"config":{"v6AssignMode":{` + spicing + `}}}`
|
|
||||||
// info := service.MyService.ZeroTier().EditNetwork(config.ZeroTierInfo.Token, postData, id)
|
|
||||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
|
|
||||||
//}
|
|
||||||
|
|
||||||
//// @Summary Broadcast
|
|
||||||
//// @Produce application/json
|
|
||||||
//// @Accept application/json
|
|
||||||
//// @Tags zerotier
|
|
||||||
//// @Security ApiKeyAuth
|
|
||||||
//// @Param id path string true "network id"
|
|
||||||
//// @Param broadcast formData string true "true/false"
|
|
||||||
//// @Success 200 {string} string "ok"
|
|
||||||
//// @Router /zerotier/broadcast/{id} [put]
|
|
||||||
//func ZeroTierEditBroadcast(c *gin.Context) {
|
|
||||||
// id := c.Param("id")
|
|
||||||
// broadcast := c.PostForm("broadcast")
|
|
||||||
// if len(id) == 0 || len(broadcast) == 0 {
|
|
||||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// postData := `{"config":{"enableBroadcast":` + broadcast + `}}`
|
|
||||||
// info := service.MyService.ZeroTier().EditNetwork(config.ZeroTierInfo.Token, postData, id)
|
|
||||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
|
|
||||||
//}
|
|
||||||
|
|
||||||
// @Summary 网络列表
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags zerotier
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param id path string true "network id"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /zerotier/member/{id} [get]
|
|
||||||
func ZeroTierMemberList(c *gin.Context) {
|
|
||||||
id := c.Param("id")
|
|
||||||
if len(id) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
info := service.MyService.ZeroTier().MemberList(config.ZeroTierInfo.Token, id)
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary create new network
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags zerotier
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /zerotier/create [post]
|
|
||||||
func ZeroTierCreateNetwork(c *gin.Context) {
|
|
||||||
info := service.MyService.ZeroTier().CreateNetwork(config.ZeroTierInfo.Token)
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
|
|
||||||
}
|
|
||||||
|
|
||||||
//// @Summary 通过/拒绝客户端
|
|
||||||
//// @Produce application/json
|
|
||||||
//// @Accept application/json
|
|
||||||
//// @Tags zerotier
|
|
||||||
//// @Security ApiKeyAuth
|
|
||||||
//// @Param id path string true "network id"
|
|
||||||
//// @Param mId path string true "member_id"
|
|
||||||
//// @Param auth formData string true "true/false"
|
|
||||||
//// @Success 200 {string} string "ok"
|
|
||||||
//// @Router /zerotier/member/{id}/auth/{mId} [put]
|
|
||||||
//func ZeroTierMemberAuth(c *gin.Context) {
|
|
||||||
// id := c.Param("id")
|
|
||||||
// mId := c.Param("mId")
|
|
||||||
// auth := c.PostForm("auth")
|
|
||||||
// if len(id) == 0 || len(mId) == 0 || len(auth) == 0 {
|
|
||||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// postData := `{"config":{"authorized":` + auth + `}}`
|
|
||||||
// info := service.MyService.ZeroTier().EditNetworkMember(config.ZeroTierInfo.Token, postData, id, mId)
|
|
||||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
|
|
||||||
//}
|
|
||||||
|
|
||||||
//// @Summary 修改名字
|
|
||||||
//// @Produce application/json
|
|
||||||
//// @Accept application/json
|
|
||||||
//// @Tags zerotier
|
|
||||||
//// @Security ApiKeyAuth
|
|
||||||
//// @Param id path string true "network id"
|
|
||||||
//// @Param mId path string true "member_id"
|
|
||||||
//// @Param name formData string true "name"
|
|
||||||
//// @Success 200 {string} string "ok"
|
|
||||||
//// @Router /zerotier/member/{id}/name/{mId} [put]
|
|
||||||
//func ZeroTierMemberName(c *gin.Context) {
|
|
||||||
// id := c.Param("id")
|
|
||||||
// mId := c.Param("mId")
|
|
||||||
// name := c.PostForm("name")
|
|
||||||
// if len(id) == 0 || len(mId) == 0 || len(name) == 0 {
|
|
||||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// postData := `{"name":"` + name + `"}`
|
|
||||||
// info := service.MyService.ZeroTier().EditNetworkMember(config.ZeroTierInfo.Token, postData, id, mId)
|
|
||||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
|
|
||||||
//}
|
|
||||||
|
|
||||||
//// @Summary 修改桥接
|
|
||||||
//// @Produce application/json
|
|
||||||
//// @Accept application/json
|
|
||||||
//// @Tags zerotier
|
|
||||||
//// @Security ApiKeyAuth
|
|
||||||
//// @Param id path string true "network id"
|
|
||||||
//// @Param mId path string true "member_id"
|
|
||||||
//// @Param bridge formData string true "true/false"
|
|
||||||
//// @Success 200 {string} string "ok"
|
|
||||||
//// @Router /zerotier/member/{id}/bridge/{mId} [put]
|
|
||||||
//func ZeroTierMemberBridge(c *gin.Context) {
|
|
||||||
// id := c.Param("id")
|
|
||||||
// mId := c.Param("mId")
|
|
||||||
// bridge := c.PostForm("bridge")
|
|
||||||
// if len(id) == 0 || len(mId) == 0 || len(bridge) == 0 {
|
|
||||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// postData := `{"config":{"activeBridge":` + bridge + `}}`
|
|
||||||
// info := service.MyService.ZeroTier().EditNetworkMember(config.ZeroTierInfo.Token, postData, id, mId)
|
|
||||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
|
|
||||||
//}
|
|
||||||
|
|
||||||
// @Summary 修改网络
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags zerotier
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param id path string true "network id"
|
|
||||||
// @Param json formData string true "json数据"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /zerotier/edit/{id} [put]
|
|
||||||
func ZeroTierEdit(c *gin.Context) {
|
|
||||||
id := c.Param("id")
|
|
||||||
json := c.PostForm("json")
|
|
||||||
if len(id) == 0 || len(json) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
info := service.MyService.ZeroTier().EditNetwork(config.ZeroTierInfo.Token, json, id)
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 获取已加入的网络
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags zerotier
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /zerotier/joined/list [get]
|
|
||||||
func ZeroTierJoinedList(c *gin.Context) {
|
|
||||||
info := service.MyService.ZeroTier().GetJoinNetworks()
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: json2.RawMessage(info)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 修改网络用户信息
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags zerotier
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param id path string true "network id"
|
|
||||||
// @Param mId path string true "mId"
|
|
||||||
// @Param json formData string true "json数据"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /zerotier/member/{id}/edit/{mId} [put]
|
|
||||||
func ZeroTierMemberEdit(c *gin.Context) {
|
|
||||||
id := c.Param("id")
|
|
||||||
mId := c.Param("mId")
|
|
||||||
json := c.PostForm("json")
|
|
||||||
if len(id) == 0 || len(json) == 0 || len(mId) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
info := service.MyService.ZeroTier().EditNetworkMember(config.ZeroTierInfo.Token, json, id, mId)
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 删除网络中的用户
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags zerotier
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param id path string true "network id"
|
|
||||||
// @Param mId path string true "member_id"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /zerotier/member/{id}/del/{mId} [delete]
|
|
||||||
func ZeroTierMemberDelete(c *gin.Context) {
|
|
||||||
id := c.Param("id")
|
|
||||||
mId := c.Param("mId")
|
|
||||||
if len(id) == 0 || len(mId) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
info := service.MyService.ZeroTier().DeleteMember(config.ZeroTierInfo.Token, id, mId)
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 删除网络
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags zerotier
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param id path string true "network id"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /zerotier/network/{id}/del [delete]
|
|
||||||
func ZeroTierDeleteNetwork(c *gin.Context) {
|
|
||||||
id := c.Param("id")
|
|
||||||
if len(id) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
info := service.MyService.ZeroTier().DeleteNetwork(config.ZeroTierInfo.Token, id)
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 加入网络
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept multipart/form-data
|
|
||||||
// @Tags zerotier
|
|
||||||
// @Param id path string true "network id"
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /zerotier/join/{id} [post]
|
|
||||||
func ZeroTierJoinNetwork(c *gin.Context) {
|
|
||||||
networkId := c.Param("id")
|
|
||||||
service.MyService.ZeroTier().ZeroTierJoinNetwork(networkId)
|
|
||||||
if len(networkId) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 获取zerotier网络列表
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept multipart/form-data
|
|
||||||
// @Tags zerotier
|
|
||||||
// @Param id path string true "network id"
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /zerotier/leave/{id} [post]
|
|
||||||
func ZeroTierLeaveNetwork(c *gin.Context) {
|
|
||||||
networkId := c.Param("id")
|
|
||||||
service.MyService.ZeroTier().ZeroTierLeaveNetwork(networkId)
|
|
||||||
if len(networkId) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
|
||||||
}
|
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/shirou/gopsutil/v3/disk"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
// @Summary 获取cpu信息
|
// @Summary 获取cpu信息
|
||||||
@@ -73,7 +73,7 @@ func NetInfo(c *gin.Context) {
|
|||||||
if n.Name == netCardName {
|
if n.Name == netCardName {
|
||||||
item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
|
item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
|
||||||
item.State = strings.TrimSpace(service.MyService.ZiMa().GetNetState(n.Name))
|
item.State = strings.TrimSpace(service.MyService.ZiMa().GetNetState(n.Name))
|
||||||
item.DateTime = time.Now()
|
item.Time = time.Now().Unix()
|
||||||
newNet = append(newNet, item)
|
newNet = append(newNet, item)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -83,48 +83,6 @@ func NetInfo(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: newNet})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: newNet})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary 获取信息
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags zima
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /zima/getinfo [get]
|
|
||||||
func Info(c *gin.Context) {
|
|
||||||
var data = make(map[string]interface{}, 4)
|
|
||||||
|
|
||||||
var diskArr []*disk.UsageStat
|
|
||||||
diskArr = append(diskArr, service.MyService.ZiMa().GetDiskInfo())
|
|
||||||
data["disk"] = diskArr
|
|
||||||
cpu := service.MyService.ZiMa().GetCpuPercent()
|
|
||||||
num := service.MyService.ZiMa().GetCpuCoreNum()
|
|
||||||
cpuData := make(map[string]interface{})
|
|
||||||
cpuData["percent"] = cpu
|
|
||||||
cpuData["num"] = num
|
|
||||||
data["cpu"] = cpuData
|
|
||||||
data["mem"] = service.MyService.ZiMa().GetMemInfo()
|
|
||||||
|
|
||||||
//拼装网络信息
|
|
||||||
netList := service.MyService.ZiMa().GetNetInfo()
|
|
||||||
newNet := []model.IOCountersStat{}
|
|
||||||
nets := service.MyService.ZiMa().GetNet(true)
|
|
||||||
for _, n := range netList {
|
|
||||||
for _, netCardName := range nets {
|
|
||||||
if n.Name == netCardName {
|
|
||||||
item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
|
|
||||||
item.State = strings.TrimSpace(service.MyService.ZiMa().GetNetState(n.Name))
|
|
||||||
item.DateTime = time.Now()
|
|
||||||
newNet = append(newNet, item)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data["net"] = newNet
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 获取信息系统信息
|
// @Summary 获取信息系统信息
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept application/json
|
// @Accept application/json
|
||||||
|
|||||||
240
service/app.go
240
service/app.go
@@ -2,35 +2,41 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
json2 "encoding/json"
|
"encoding/json"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/docker"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||||
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
|
||||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
client2 "github.com/docker/docker/client"
|
client2 "github.com/docker/docker/client"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/tidwall/gjson"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type AppService interface {
|
type AppService interface {
|
||||||
GetMyList(index, size int, position bool) *[]model2.MyAppList
|
GetMyList(index, size int, position bool) *[]model2.MyAppList
|
||||||
SaveContainer(m model2.AppListDBModel)
|
SaveContainer(m model2.AppListDBModel)
|
||||||
GetServerAppInfo(id string) model.ServerAppList
|
|
||||||
GetUninstallInfo(id string) model2.AppListDBModel
|
GetUninstallInfo(id string) model2.AppListDBModel
|
||||||
RemoveContainerById(id string)
|
RemoveContainerById(id string)
|
||||||
GetContainerInfo(name string) (types.Container, error)
|
GetContainerInfo(name string) (types.Container, error)
|
||||||
GetAppDBInfo(id string) model2.AppListDBModel
|
GetAppDBInfo(id string) model2.AppListDBModel
|
||||||
UpdateApp(m model2.AppListDBModel)
|
UpdateApp(m model2.AppListDBModel)
|
||||||
GetSimpleContainerInfo(name string) (types.Container, error)
|
GetSimpleContainerInfo(name string) (types.Container, error)
|
||||||
DelAppConfigDir(id string)
|
DelAppConfigDir(path string)
|
||||||
|
GetSystemAppList() *[]model2.MyAppList
|
||||||
|
GetHardwareUsageSteam()
|
||||||
|
GetHardwareUsage() []model.DockerStatsModel
|
||||||
|
GetAppStats(id string) string
|
||||||
|
GetAllDBApps() []model2.AppListDBModel
|
||||||
}
|
}
|
||||||
|
|
||||||
type appStruct struct {
|
type appStruct struct {
|
||||||
@@ -41,7 +47,7 @@ type appStruct struct {
|
|||||||
//获取我的应用列表
|
//获取我的应用列表
|
||||||
func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppList {
|
func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppList {
|
||||||
//获取docker应用
|
//获取docker应用
|
||||||
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
cli, err := client2.NewClientWithOpts(client2.FromEnv, client2.WithTimeout(time.Second*5))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.log.Error("初始化client失败", "app.getmylist", "line:36", err)
|
a.log.Error("初始化client失败", "app.getmylist", "line:36", err)
|
||||||
}
|
}
|
||||||
@@ -52,11 +58,10 @@ func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppLis
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
a.log.Error("获取docker容器失败", "app.getmylist", "line:42", err)
|
a.log.Error("获取docker容器失败", "app.getmylist", "line:42", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
//获取本地数据库应用
|
//获取本地数据库应用
|
||||||
|
|
||||||
var lm []model2.AppListDBModel
|
var lm []model2.AppListDBModel
|
||||||
a.db.Table(model2.CONTAINERTABLENAME).Select("title,icon,port_map,`index`,container_id,position,label,slogan").Find(&lm)
|
a.db.Table(model2.CONTAINERTABLENAME).Select("title,icon,port_map,`index`,container_id,position,label,slogan,image").Find(&lm)
|
||||||
|
|
||||||
list := []model2.MyAppList{}
|
list := []model2.MyAppList{}
|
||||||
lMap := make(map[string]interface{})
|
lMap := make(map[string]interface{})
|
||||||
@@ -69,11 +74,70 @@ func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppLis
|
|||||||
lMap[dbModel.ContainerId] = dbModel
|
lMap[dbModel.ContainerId] = dbModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, container := range containers {
|
||||||
|
|
||||||
|
if lMap[container.ID] != nil && container.Labels["origin"] != "system" {
|
||||||
|
m := lMap[container.ID].(model2.AppListDBModel)
|
||||||
|
if len(m.Label) == 0 {
|
||||||
|
m.Label = m.Title
|
||||||
|
}
|
||||||
|
|
||||||
|
// info, err := cli.ContainerInspect(context.Background(), container.ID)
|
||||||
|
// var tm string
|
||||||
|
// if err != nil {
|
||||||
|
// tm = time.Now().String()
|
||||||
|
// } else {
|
||||||
|
// tm = info.State.StartedAt
|
||||||
|
//}
|
||||||
|
list = append(list, model2.MyAppList{
|
||||||
|
Name: m.Label,
|
||||||
|
Icon: m.Icon,
|
||||||
|
State: container.State,
|
||||||
|
CustomId: strings.ReplaceAll(container.Names[0], "/", ""),
|
||||||
|
Port: m.PortMap,
|
||||||
|
Index: m.Index,
|
||||||
|
//UpTime: tm,
|
||||||
|
Image: m.Image,
|
||||||
|
Slogan: m.Slogan,
|
||||||
|
//Rely: m.Rely,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return &list
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//system application list
|
||||||
|
func (a *appStruct) GetSystemAppList() *[]model2.MyAppList {
|
||||||
|
//获取docker应用
|
||||||
|
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
|
if err != nil {
|
||||||
|
a.log.Error("初始化client失败", "app.getmylist", "line:36", err)
|
||||||
|
}
|
||||||
|
defer cli.Close()
|
||||||
|
fts := filters.NewArgs()
|
||||||
|
fts.Add("label", "origin=system")
|
||||||
|
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: fts})
|
||||||
|
if err != nil {
|
||||||
|
a.log.Error("获取docker容器失败", "app.sys", "line:123", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取本地数据库应用
|
||||||
|
|
||||||
|
var lm []model2.AppListDBModel
|
||||||
|
a.db.Table(model2.CONTAINERTABLENAME).Select("title,icon,port_map,`index`,container_id,position,label,slogan,image,volumes").Find(&lm)
|
||||||
|
|
||||||
|
list := []model2.MyAppList{}
|
||||||
|
lMap := make(map[string]interface{})
|
||||||
|
for _, dbModel := range lm {
|
||||||
|
lMap[dbModel.ContainerId] = dbModel
|
||||||
|
}
|
||||||
for _, container := range containers {
|
for _, container := range containers {
|
||||||
|
|
||||||
if lMap[container.ID] != nil {
|
if lMap[container.ID] != nil {
|
||||||
var m model2.AppListDBModel
|
m := lMap[container.ID].(model2.AppListDBModel)
|
||||||
m = lMap[container.ID].(model2.AppListDBModel)
|
|
||||||
if len(m.Label) == 0 {
|
if len(m.Label) == 0 {
|
||||||
m.Label = m.Title
|
m.Label = m.Title
|
||||||
}
|
}
|
||||||
@@ -93,16 +157,22 @@ func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppLis
|
|||||||
Port: m.PortMap,
|
Port: m.PortMap,
|
||||||
Index: m.Index,
|
Index: m.Index,
|
||||||
UpTime: tm,
|
UpTime: tm,
|
||||||
|
Image: m.Image,
|
||||||
Slogan: m.Slogan,
|
Slogan: m.Slogan,
|
||||||
|
Volumes: m.Volumes,
|
||||||
//Rely: m.Rely,
|
//Rely: m.Rely,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &list
|
return &list
|
||||||
|
|
||||||
}
|
}
|
||||||
|
func (a *appStruct) GetAllDBApps() []model2.AppListDBModel {
|
||||||
|
var lm []model2.AppListDBModel
|
||||||
|
a.db.Table(model2.CONTAINERTABLENAME).Select("custom_id,title,icon,container_id,label,slogan,image").Find(&lm)
|
||||||
|
return lm
|
||||||
|
}
|
||||||
|
|
||||||
//获取我的应用列表
|
//获取我的应用列表
|
||||||
func (a *appStruct) GetContainerInfo(name string) (types.Container, error) {
|
func (a *appStruct) GetContainerInfo(name string) (types.Container, error) {
|
||||||
@@ -115,7 +185,7 @@ func (a *appStruct) GetContainerInfo(name string) (types.Container, error) {
|
|||||||
filters.Add("name", name)
|
filters.Add("name", name)
|
||||||
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: filters})
|
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: filters})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.log.Error("获取docker容器失败", "app.getmylist", "line:42", err)
|
a.log.Error("获取docker容器失败", "app.getcontainerinfo", "line:182", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(containers) > 0 {
|
if len(containers) > 0 {
|
||||||
@@ -135,6 +205,10 @@ func (a *appStruct) GetSimpleContainerInfo(name string) (types.Container, error)
|
|||||||
filters := filters.NewArgs()
|
filters := filters.NewArgs()
|
||||||
filters.Add("name", name)
|
filters.Add("name", name)
|
||||||
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: filters})
|
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: filters})
|
||||||
|
if err != nil {
|
||||||
|
return types.Container{}, err
|
||||||
|
}
|
||||||
|
|
||||||
if len(containers) > 0 {
|
if len(containers) > 0 {
|
||||||
return containers[0], nil
|
return containers[0], nil
|
||||||
}
|
}
|
||||||
@@ -155,27 +229,6 @@ func (a *appStruct) GetUninstallInfo(id string) model2.AppListDBModel {
|
|||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *appStruct) GetServerAppInfo(id string) model.ServerAppList {
|
|
||||||
|
|
||||||
head := make(map[string]string)
|
|
||||||
|
|
||||||
t := make(chan string)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
str := httper2.Get(config.ServerInfo.ServerApi+"/token", nil)
|
|
||||||
|
|
||||||
t <- gjson.Get(str, "data").String()
|
|
||||||
}()
|
|
||||||
head["Authorization"] = <-t
|
|
||||||
|
|
||||||
infoS := httper2.Get(config.ServerInfo.ServerApi+"/v1/app/info/"+id, head)
|
|
||||||
|
|
||||||
info := model.ServerAppList{}
|
|
||||||
json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
|
|
||||||
|
|
||||||
return info
|
|
||||||
}
|
|
||||||
|
|
||||||
//创建容器成功后保存容器
|
//创建容器成功后保存容器
|
||||||
func (a *appStruct) SaveContainer(m model2.AppListDBModel) {
|
func (a *appStruct) SaveContainer(m model2.AppListDBModel) {
|
||||||
a.db.Table(model2.CONTAINERTABLENAME).Create(&m)
|
a.db.Table(model2.CONTAINERTABLENAME).Create(&m)
|
||||||
@@ -185,14 +238,125 @@ func (a *appStruct) UpdateApp(m model2.AppListDBModel) {
|
|||||||
a.db.Table(model2.CONTAINERTABLENAME).Save(&m)
|
a.db.Table(model2.CONTAINERTABLENAME).Save(&m)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *appStruct) DelAppConfigDir(id string) {
|
func (a *appStruct) DelAppConfigDir(path string) {
|
||||||
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;DelAppConfigDir " + docker.GetDir(id, "/config"))
|
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;DelAppConfigDir " + path)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *appStruct) RemoveContainerById(id string) {
|
func (a *appStruct) RemoveContainerById(id string) {
|
||||||
a.db.Table(model2.CONTAINERTABLENAME).Where("custom_id = ?", id).Delete(&model2.AppListDBModel{})
|
a.db.Table(model2.CONTAINERTABLENAME).Where("custom_id = ?", id).Delete(&model2.AppListDBModel{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var dataStats sync.Map
|
||||||
|
|
||||||
|
var isFinish bool = false
|
||||||
|
|
||||||
|
func (a *appStruct) GetAppStats(id string) string {
|
||||||
|
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
defer cli.Close()
|
||||||
|
con, err := cli.ContainerStats(context.Background(), id, false)
|
||||||
|
if err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
defer con.Body.Close()
|
||||||
|
c, _ := ioutil.ReadAll(con.Body)
|
||||||
|
return string(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *appStruct) GetHardwareUsage() []model.DockerStatsModel {
|
||||||
|
|
||||||
|
steam := true
|
||||||
|
for !isFinish {
|
||||||
|
if steam {
|
||||||
|
steam = false
|
||||||
|
go func() {
|
||||||
|
a.GetHardwareUsageSteam()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
runtime.Gosched()
|
||||||
|
}
|
||||||
|
list := []model.DockerStatsModel{}
|
||||||
|
|
||||||
|
dataStats.Range(func(key, value interface{}) bool {
|
||||||
|
list = append(list, value.(model.DockerStatsModel))
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return list
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *appStruct) GetHardwareUsageSteam() {
|
||||||
|
|
||||||
|
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
|
||||||
|
var lm []model2.AppListDBModel
|
||||||
|
a.db.Table(model2.CONTAINERTABLENAME).Select("label,title,icon,container_id").Where("origin != ?", "system").Find(&lm)
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
if config.CasaOSGlobalVariables.AppChange {
|
||||||
|
lm = []model2.AppListDBModel{}
|
||||||
|
config.CasaOSGlobalVariables.AppChange = false
|
||||||
|
a.db.Table(model2.CONTAINERTABLENAME).Select("label,title,icon,container_id").Where("origin != ?", "system").Find(&lm)
|
||||||
|
dataApps := dataStats
|
||||||
|
dataStats.Range(func(key, value interface{}) bool {
|
||||||
|
dataStats.Delete(key)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
for _, v := range lm {
|
||||||
|
m, _ := dataApps.Load(v.ContainerId)
|
||||||
|
if m != nil {
|
||||||
|
dataStats.Store(v.ContainerId, m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for _, v := range lm {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(v model2.AppListDBModel, i int) {
|
||||||
|
defer wg.Done()
|
||||||
|
stats, err := cli.ContainerStats(ctx, v.ContainerId, true)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
decode := json.NewDecoder(stats.Body)
|
||||||
|
var data interface{}
|
||||||
|
if err := decode.Decode(&data); err == io.EOF {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
m, _ := dataStats.Load(v.ContainerId)
|
||||||
|
dockerStats := model.DockerStatsModel{}
|
||||||
|
if m != nil {
|
||||||
|
dockerStats.Pre = m.(model.DockerStatsModel).Data
|
||||||
|
}
|
||||||
|
dockerStats.Data = data
|
||||||
|
dockerStats.Icon = v.Icon
|
||||||
|
if len(v.Label) > 0 {
|
||||||
|
dockerStats.Title = v.Label
|
||||||
|
} else {
|
||||||
|
dockerStats.Title = v.Title
|
||||||
|
}
|
||||||
|
dataStats.Store(v.ContainerId, dockerStats)
|
||||||
|
if i == 99 {
|
||||||
|
stats.Body.Close()
|
||||||
|
}
|
||||||
|
}(v, i)
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
isFinish = true
|
||||||
|
time.Sleep(time.Second * 3)
|
||||||
|
}
|
||||||
|
isFinish = false
|
||||||
|
cancel()
|
||||||
|
}
|
||||||
|
|
||||||
func NewAppService(db *gorm.DB, logger loger2.OLog) AppService {
|
func NewAppService(db *gorm.DB, logger loger2.OLog) AppService {
|
||||||
return &appStruct{db: db, log: logger}
|
return &appStruct{db: db, log: logger}
|
||||||
}
|
}
|
||||||
|
|||||||
233
service/casa.go
Normal file
233
service/casa.go
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
json2 "encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
|
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
||||||
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CasaService interface {
|
||||||
|
GetServerList(index, size, tp, categoryId, key, language string) (recommend, list, community []model.ServerAppList)
|
||||||
|
GetServerCategoryList() []model.ServerCategoryList
|
||||||
|
GetTaskList(size int) []model2.TaskDBModel
|
||||||
|
GetServerAppInfo(id, t string, language string) model.ServerAppList
|
||||||
|
ShareAppFile(body []byte) string
|
||||||
|
PushHeart(id, t string, language string)
|
||||||
|
PushAppAnalyse(uuid, t string, name, language string)
|
||||||
|
PushConnectionStatus(uuid, err string, from, to, event string)
|
||||||
|
PushUserInfo()
|
||||||
|
GetUserInfoByShareId(shareId string) model.UserInfo
|
||||||
|
GetPersonPublic() (list []model.FriendsModel)
|
||||||
|
}
|
||||||
|
|
||||||
|
type casaService struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *casaService) ShareAppFile(body []byte) string {
|
||||||
|
head := make(map[string]string)
|
||||||
|
|
||||||
|
head["Authorization"] = GetToken()
|
||||||
|
|
||||||
|
content := httper2.Post(config.ServerInfo.ServerApi+"/v1/community/add", body, "application/json", head)
|
||||||
|
return content
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *casaService) GetTaskList(size int) []model2.TaskDBModel {
|
||||||
|
head := make(map[string]string)
|
||||||
|
|
||||||
|
head["Authorization"] = GetToken()
|
||||||
|
|
||||||
|
listS := httper2.Get(config.ServerInfo.ServerApi+"/v1/task/list/"+strconv.Itoa(size), head)
|
||||||
|
|
||||||
|
list := []model2.TaskDBModel{}
|
||||||
|
json2.Unmarshal([]byte(gjson.Get(listS, "data").String()), &list)
|
||||||
|
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *casaService) GetServerList(index, size, tp, categoryId, key, language string) (recommend, list, community []model.ServerAppList) {
|
||||||
|
|
||||||
|
keyName := fmt.Sprintf("list_%s_%s_%s_%s_%s", index, size, tp, categoryId, language)
|
||||||
|
|
||||||
|
if result, ok := Cache.Get(keyName); ok {
|
||||||
|
res, ok := result.(string)
|
||||||
|
if ok {
|
||||||
|
json2.Unmarshal([]byte(gjson.Get(res, "data.list").String()), &list)
|
||||||
|
json2.Unmarshal([]byte(gjson.Get(res, "data.recommend").String()), &recommend)
|
||||||
|
json2.Unmarshal([]byte(gjson.Get(res, "data.community").String()), &community)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
head := make(map[string]string)
|
||||||
|
|
||||||
|
head["Authorization"] = GetToken()
|
||||||
|
|
||||||
|
listS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/newlist?index="+index+"&size="+size+"&rank="+tp+"&category_id="+categoryId+"&key="+key+"&language="+language, head)
|
||||||
|
|
||||||
|
json2.Unmarshal([]byte(gjson.Get(listS, "data.list").String()), &list)
|
||||||
|
json2.Unmarshal([]byte(gjson.Get(listS, "data.recommend").String()), &recommend)
|
||||||
|
json2.Unmarshal([]byte(gjson.Get(listS, "data.community").String()), &community)
|
||||||
|
|
||||||
|
if len(list) > 0 {
|
||||||
|
Cache.SetDefault(keyName, listS)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *casaService) GetServerCategoryList() []model.ServerCategoryList {
|
||||||
|
|
||||||
|
head := make(map[string]string)
|
||||||
|
head["Authorization"] = GetToken()
|
||||||
|
|
||||||
|
listS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/category", head)
|
||||||
|
|
||||||
|
list := []model.ServerCategoryList{}
|
||||||
|
|
||||||
|
json2.Unmarshal([]byte(gjson.Get(listS, "data").String()), &list)
|
||||||
|
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
func (o *casaService) GetServerAppInfo(id, t string, language string) model.ServerAppList {
|
||||||
|
|
||||||
|
head := make(map[string]string)
|
||||||
|
|
||||||
|
head["Authorization"] = GetToken()
|
||||||
|
infoS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/info/"+id+"?t="+t+"&language="+language, head)
|
||||||
|
|
||||||
|
info := model.ServerAppList{}
|
||||||
|
json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
|
||||||
|
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
func GetToken() string {
|
||||||
|
t := make(chan string)
|
||||||
|
keyName := "casa_token"
|
||||||
|
|
||||||
|
var auth string
|
||||||
|
if result, ok := Cache.Get(keyName); ok {
|
||||||
|
auth, ok = result.(string)
|
||||||
|
if ok {
|
||||||
|
|
||||||
|
return auth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
str := httper2.Get(config.ServerInfo.ServerApi+"/token", nil)
|
||||||
|
t <- gjson.Get(str, "data").String()
|
||||||
|
}()
|
||||||
|
auth = <-t
|
||||||
|
|
||||||
|
Cache.SetDefault(keyName, auth)
|
||||||
|
return auth
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *casaService) PushHeart(id, t string, language string) {
|
||||||
|
|
||||||
|
m := model.CasaOSHeart{}
|
||||||
|
m.UuId = id
|
||||||
|
m.Type = t
|
||||||
|
b, _ := json.Marshal(m)
|
||||||
|
|
||||||
|
head := make(map[string]string)
|
||||||
|
|
||||||
|
head["Authorization"] = GetToken()
|
||||||
|
|
||||||
|
infoS := httper2.Post(config.ServerInfo.ServerApi+"/v1/analyse/heart", b, "application/json", head)
|
||||||
|
|
||||||
|
info := model.ServerAppList{}
|
||||||
|
json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *casaService) PushAppAnalyse(uuid, t string, name, language string) {
|
||||||
|
|
||||||
|
m := model.AppAnalyse{}
|
||||||
|
m.UUId = uuid
|
||||||
|
m.Type = t
|
||||||
|
m.Name = name
|
||||||
|
m.Language = language
|
||||||
|
b, _ := json.Marshal(m)
|
||||||
|
|
||||||
|
head := make(map[string]string)
|
||||||
|
|
||||||
|
head["Authorization"] = GetToken()
|
||||||
|
|
||||||
|
infoS := httper2.Post(config.ServerInfo.ServerApi+"/v1/analyse/app", b, "application/json", head)
|
||||||
|
|
||||||
|
info := model.ServerAppList{}
|
||||||
|
json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
|
||||||
|
|
||||||
|
}
|
||||||
|
func (o *casaService) PushConnectionStatus(uuid, err string, from, to, event string) {
|
||||||
|
|
||||||
|
m := model.ConnectionStatus{}
|
||||||
|
m.UUId = uuid
|
||||||
|
m.Error = err
|
||||||
|
m.From = from
|
||||||
|
m.To = to
|
||||||
|
m.Event = event
|
||||||
|
b, _ := json.Marshal(m)
|
||||||
|
|
||||||
|
head := make(map[string]string)
|
||||||
|
|
||||||
|
head["Authorization"] = GetToken()
|
||||||
|
|
||||||
|
infoS := httper2.Post(config.ServerInfo.ServerApi+"/v1/analyse/connect", b, "application/json", head)
|
||||||
|
|
||||||
|
info := model.ServerAppList{}
|
||||||
|
json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
|
||||||
|
|
||||||
|
}
|
||||||
|
func (o *casaService) PushUserInfo() {
|
||||||
|
m := model.UserInfo{}
|
||||||
|
m.Desc = config.UserInfo.Description
|
||||||
|
m.Avatar = config.UserInfo.Avatar
|
||||||
|
m.NickName = config.UserInfo.NickName
|
||||||
|
m.ShareId = config.ServerInfo.Token
|
||||||
|
b, _ := json.Marshal(m)
|
||||||
|
|
||||||
|
head := make(map[string]string)
|
||||||
|
|
||||||
|
head["Authorization"] = GetToken()
|
||||||
|
|
||||||
|
infoS := httper2.Post(config.ServerInfo.ServerApi+"/v1/user/info", b, "application/json", head)
|
||||||
|
|
||||||
|
info := model.ServerAppList{}
|
||||||
|
json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *casaService) GetUserInfoByShareId(shareId string) model.UserInfo {
|
||||||
|
|
||||||
|
head := make(map[string]string)
|
||||||
|
|
||||||
|
head["Authorization"] = GetToken()
|
||||||
|
|
||||||
|
infoS := httper2.Get(config.ServerInfo.ServerApi+"/v1/user/info/"+shareId, head)
|
||||||
|
|
||||||
|
info := model.UserInfo{}
|
||||||
|
json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
func (o *casaService) GetPersonPublic() (list []model.FriendsModel) {
|
||||||
|
head := make(map[string]string)
|
||||||
|
|
||||||
|
head["Authorization"] = GetToken()
|
||||||
|
|
||||||
|
listS := httper2.Get(config.ServerInfo.ServerApi+"/v1/person/public", head)
|
||||||
|
|
||||||
|
json2.Unmarshal([]byte(gjson.Get(listS, "data").String()), &list)
|
||||||
|
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
func NewCasaService() CasaService {
|
||||||
|
return &casaService{}
|
||||||
|
}
|
||||||
1
service/data_ handling.go
Normal file
1
service/data_ handling.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package service
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
ip_helper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
|
ip_helper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
|
||||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||||
"github.com/IceWhaleTech/CasaOS/service/ddns"
|
"github.com/IceWhaleTech/CasaOS/service/ddns"
|
||||||
"github.com/IceWhaleTech/CasaOS/service/model"
|
"github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"os/exec"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ddnsStruct struct {
|
type ddnsStruct struct {
|
||||||
@@ -20,17 +21,15 @@ type DDNSService interface {
|
|||||||
GetConfigList() *[]model.DDNSList
|
GetConfigList() *[]model.DDNSList
|
||||||
DeleteConfig(id uint) bool
|
DeleteConfig(id uint) bool
|
||||||
GetType(name string) (uint, string)
|
GetType(name string) (uint, string)
|
||||||
SaveConfig(model model.DDNSUpdataDBModel) error
|
SaveConfig(model model.DDNSUpdateDBModel) error
|
||||||
}
|
}
|
||||||
|
|
||||||
//判断当前添加的是否存在
|
//判断当前添加的是否存在
|
||||||
func (d *ddnsStruct) IsExis(t int, domain string, host string) bool {
|
func (d *ddnsStruct) IsExis(t int, domain string, host string) bool {
|
||||||
var count int64
|
var count int64
|
||||||
d.db.Table(model.DDNSLISTTABLENAME).Where("type=? AND domain=? AND host=?", t, domain, host).Count(&count)
|
d.db.Table(model.DDNSLISTTABLENAME).Where("type=? AND domain=? AND host=?", t, domain, host).Count(&count)
|
||||||
if count > 0 {
|
|
||||||
return true
|
return count > 0
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//前台获取已配置的ddns列表
|
//前台获取已配置的ddns列表
|
||||||
@@ -41,7 +40,7 @@ func (d *ddnsStruct) GetConfigList() *[]model.DDNSList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *ddnsStruct) DeleteConfig(id uint) bool {
|
func (d *ddnsStruct) DeleteConfig(id uint) bool {
|
||||||
d.db.Delete(&model.DDNSUpdataDBModel{Id: id})
|
d.db.Delete(&model.DDNSUpdateDBModel{Id: id})
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,12 +65,12 @@ func (d *ddnsStruct) GetType(name string) (uint, string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//保存配置到数据库
|
//保存配置到数据库
|
||||||
func (d *ddnsStruct) GetDockerRootDir(model model.DDNSUpdataDBModel) error {
|
func (d *ddnsStruct) GetDockerRootDir(model model.DDNSUpdateDBModel) error {
|
||||||
return d.db.Create(&model).Error
|
return d.db.Create(&model).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
//保存配置到数据库
|
//保存配置到数据库
|
||||||
func (d *ddnsStruct) SaveConfig(model model.DDNSUpdataDBModel) error {
|
func (d *ddnsStruct) SaveConfig(model model.DDNSUpdateDBModel) error {
|
||||||
return d.db.Create(&model).Error
|
return d.db.Create(&model).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +86,7 @@ func chackPing(b chan bool, url string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//更新列表
|
//更新列表
|
||||||
func UpdataDDNSList(db *gorm.DB) {
|
func UpdateDDNSList(db *gorm.DB) {
|
||||||
var s []model.DDNSCoreList
|
var s []model.DDNSCoreList
|
||||||
db.Table(model.DDNSLISTTABLENAME).Select("o_ddns_type.name as name,o_ddns_type.api_host as api_host,o_ddns.id,`host`,domain,user_name,`password`,`key`,secret,type").Joins("left join o_ddns_type on o_ddns.type=o_ddns_type.id").Scan(&s)
|
db.Table(model.DDNSLISTTABLENAME).Select("o_ddns_type.name as name,o_ddns_type.api_host as api_host,o_ddns.id,`host`,domain,user_name,`password`,`key`,secret,type").Joins("left join o_ddns_type on o_ddns.type=o_ddns_type.id").Scan(&s)
|
||||||
for _, item := range s {
|
for _, item := range s {
|
||||||
|
|||||||
@@ -31,4 +31,3 @@ func SetOauth(request *http.Request, value string) {
|
|||||||
func SetXFilter(request *http.Request, value string) {
|
func SetXFilter(request *http.Request, value string) {
|
||||||
request.Header.Set("X-Filter", value)
|
request.Header.Set("X-Filter", value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
188
service/disk.go
188
service/disk.go
@@ -3,28 +3,73 @@ package service
|
|||||||
import (
|
import (
|
||||||
json2 "encoding/json"
|
json2 "encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||||
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
"github.com/shirou/gopsutil/v3/disk"
|
"github.com/shirou/gopsutil/v3/disk"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
"strconv"
|
"gorm.io/gorm"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type DiskService interface {
|
type DiskService interface {
|
||||||
GetPlugInDisk() []string
|
GetPlugInDisk() []string
|
||||||
LSBLK() []model.LSBLKModel
|
LSBLK(isUseCache bool) []model.LSBLKModel
|
||||||
FormatDisk(path, format string) string
|
SmartCTL(path string) model.SmartctlA
|
||||||
UmountPointAndRemoveDir(path string) string
|
FormatDisk(path, format string) []string
|
||||||
|
UmountPointAndRemoveDir(path string) []string
|
||||||
GetDiskInfo(path string) model.LSBLKModel
|
GetDiskInfo(path string) model.LSBLKModel
|
||||||
DelPartition(path, num string) string
|
DelPartition(path, num string) string
|
||||||
AddPartition(path, num string, size uint64) string
|
AddPartition(path string) string
|
||||||
GetDiskInfoByPath(path string) *disk.UsageStat
|
GetDiskInfoByPath(path string) *disk.UsageStat
|
||||||
|
MountDisk(path, volume string)
|
||||||
|
GetSerialAll() []model2.SerialDisk
|
||||||
|
SaveMountPoint(m model2.SerialDisk)
|
||||||
|
DeleteMountPoint(path, mountPoint string)
|
||||||
|
DeleteMount(id string)
|
||||||
|
UpdateMountPoint(m model2.SerialDisk)
|
||||||
|
RemoveLSBLKCache()
|
||||||
}
|
}
|
||||||
type diskService struct {
|
type diskService struct {
|
||||||
log loger2.OLog
|
log loger2.OLog
|
||||||
|
db *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *diskService) RemoveLSBLKCache() {
|
||||||
|
key := "system_lsblk"
|
||||||
|
Cache.Delete(key)
|
||||||
|
}
|
||||||
|
func (d *diskService) SmartCTL(path string) model.SmartctlA {
|
||||||
|
|
||||||
|
key := "system_smart_" + path
|
||||||
|
if result, ok := Cache.Get(key); ok {
|
||||||
|
|
||||||
|
res, ok := result.(model.SmartctlA)
|
||||||
|
if ok {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var m model.SmartctlA
|
||||||
|
str := command2.ExecSmartCTLByPath(path)
|
||||||
|
if str == nil {
|
||||||
|
d.log.Error("smartctl exec error,smartctl")
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
err := json2.Unmarshal([]byte(str), &m)
|
||||||
|
if err != nil {
|
||||||
|
d.log.Error("json ummarshal error", err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(m, model.SmartctlA{}) {
|
||||||
|
Cache.Add(key, m, time.Second*10)
|
||||||
|
}
|
||||||
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
//通过脚本获取外挂磁盘
|
//通过脚本获取外挂磁盘
|
||||||
@@ -33,18 +78,15 @@ func (d *diskService) GetPlugInDisk() []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//格式化硬盘
|
//格式化硬盘
|
||||||
func (d *diskService) FormatDisk(path, format string) string {
|
func (d *diskService) FormatDisk(path, format string) []string {
|
||||||
|
|
||||||
r := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;FormatDisk " + path + " " + format)
|
r := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;FormatDisk " + path + " " + format)
|
||||||
fmt.Println(r)
|
return r
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//移除挂载点,删除目录
|
//移除挂载点,删除目录
|
||||||
func (d *diskService) UmountPointAndRemoveDir(path string) string {
|
func (d *diskService) UmountPointAndRemoveDir(path string) []string {
|
||||||
r := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;UMountPorintAndRemoveDir " + path)
|
r := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;UMountPorintAndRemoveDir " + path)
|
||||||
fmt.Println(r)
|
return r
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//删除分区
|
//删除分区
|
||||||
@@ -54,46 +96,44 @@ func (d *diskService) DelPartition(path, num string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
//添加分区
|
//part
|
||||||
func (d *diskService) AddPartition(path, num string, size uint64) string {
|
func (d *diskService) AddPartition(path string) string {
|
||||||
|
command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;AddPartition " + path)
|
||||||
var maxSector uint64 = 0
|
|
||||||
|
|
||||||
chiList := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetPartitionSectors " + path)
|
|
||||||
if len(chiList) == 0 {
|
|
||||||
d.log.Error("chiList length error")
|
|
||||||
}
|
|
||||||
for i := 0; i < len(chiList); i++ {
|
|
||||||
tempArr := strings.Split(chiList[i], ",")
|
|
||||||
tempSector, _ := strconv.ParseUint(tempArr[2], 10, 64)
|
|
||||||
if tempSector > maxSector {
|
|
||||||
maxSector = tempSector
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r := command2.ExecResultStrArray("source ./shell/helper.sh ;AddPartition " + path + " " + num + " " + strconv.FormatUint(maxSector+1, 10) + " " + strconv.FormatUint(size+maxSector+1, 10))
|
|
||||||
fmt.Println(r)
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *diskService) AddAllPartition(path string) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
//获取硬盘详情
|
//获取硬盘详情
|
||||||
func (d *diskService) GetDiskInfoByPath(path string) *disk.UsageStat {
|
func (d *diskService) GetDiskInfoByPath(path string) *disk.UsageStat {
|
||||||
diskInfo, err := disk.Usage(path + "1")
|
diskInfo, err := disk.Usage(path + "1")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
fmt.Println(path)
|
|
||||||
fmt.Println(diskInfo)
|
|
||||||
diskInfo.UsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.UsedPercent), 64)
|
diskInfo.UsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.UsedPercent), 64)
|
||||||
diskInfo.InodesUsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.InodesUsedPercent), 64)
|
diskInfo.InodesUsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.InodesUsedPercent), 64)
|
||||||
return diskInfo
|
return diskInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
//获取磁盘信息
|
//get disk details
|
||||||
func (d *diskService) LSBLK() []model.LSBLKModel {
|
func (d *diskService) LSBLK(isUseCache bool) []model.LSBLKModel {
|
||||||
|
key := "system_lsblk"
|
||||||
|
var n []model.LSBLKModel
|
||||||
|
|
||||||
|
if result, ok := Cache.Get(key); ok && isUseCache {
|
||||||
|
|
||||||
|
res, ok := result.([]model.LSBLKModel)
|
||||||
|
if ok {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
str := command2.ExecLSBLK()
|
str := command2.ExecLSBLK()
|
||||||
if str == nil {
|
if str == nil {
|
||||||
d.log.Error("lsblk exec error")
|
d.log.Error("lsblk exec error,lsblk")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var m []model.LSBLKModel
|
var m []model.LSBLKModel
|
||||||
@@ -102,15 +142,13 @@ func (d *diskService) LSBLK() []model.LSBLKModel {
|
|||||||
d.log.Error("json ummarshal error", err)
|
d.log.Error("json ummarshal error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var n []model.LSBLKModel
|
|
||||||
|
|
||||||
var c []model.LSBLKModel
|
var c []model.LSBLKModel
|
||||||
|
|
||||||
var fsused uint64
|
var fsused uint64
|
||||||
|
|
||||||
var health = true
|
var health = true
|
||||||
for _, i := range m {
|
for _, i := range m {
|
||||||
if i.Children != nil {
|
if i.Type != "loop" && !i.RO {
|
||||||
fsused = 0
|
fsused = 0
|
||||||
for _, child := range i.Children {
|
for _, child := range i.Children {
|
||||||
if child.RM {
|
if child.RM {
|
||||||
@@ -133,7 +171,9 @@ func (d *diskService) LSBLK() []model.LSBLKModel {
|
|||||||
i.Children = c
|
i.Children = c
|
||||||
if fsused > 0 {
|
if fsused > 0 {
|
||||||
i.UsedPercent, err = strconv.ParseFloat(fmt.Sprintf("%.4f", float64(fsused)/float64(i.Size)), 64)
|
i.UsedPercent, err = strconv.ParseFloat(fmt.Sprintf("%.4f", float64(fsused)/float64(i.Size)), 64)
|
||||||
fmt.Println(err)
|
if err != nil {
|
||||||
|
d.log.Fatal("diskservice_lsblk_fsused", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
n = append(n, i)
|
n = append(n, i)
|
||||||
health = true
|
health = true
|
||||||
@@ -141,15 +181,19 @@ func (d *diskService) LSBLK() []model.LSBLKModel {
|
|||||||
fsused = 0
|
fsused = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(n) > 0 {
|
||||||
|
Cache.Add(key, n, time.Second*100)
|
||||||
|
}
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
|
func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
|
||||||
str := command2.ExecLSBLKByPath(path)
|
str := command2.ExecLSBLKByPath(path)
|
||||||
if str == nil {
|
if str == nil {
|
||||||
d.log.Error("lsblk exec error")
|
d.log.Error("lsblk exec error,str")
|
||||||
return model.LSBLKModel{}
|
return model.LSBLKModel{}
|
||||||
}
|
}
|
||||||
|
|
||||||
var ml []model.LSBLKModel
|
var ml []model.LSBLKModel
|
||||||
err := json2.Unmarshal([]byte(gjson.Get(string(str), "blockdevices").String()), &ml)
|
err := json2.Unmarshal([]byte(gjson.Get(string(str), "blockdevices").String()), &ml)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -157,9 +201,13 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
|
|||||||
d.log.Error("json ummarshal error", err)
|
d.log.Error("json ummarshal error", err)
|
||||||
return model.LSBLKModel{}
|
return model.LSBLKModel{}
|
||||||
}
|
}
|
||||||
//todo 需要判断长度
|
|
||||||
m := ml[0]
|
m := model.LSBLKModel{}
|
||||||
//声明数组
|
if len(ml) > 0 {
|
||||||
|
m = ml[0]
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
// 下面为计算是否可以继续分区的部分,暂时不需要
|
||||||
chiArr := make(map[string]string)
|
chiArr := make(map[string]string)
|
||||||
chiList := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetPartitionSectors " + m.Path)
|
chiList := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetPartitionSectors " + m.Path)
|
||||||
if len(chiList) == 0 {
|
if len(chiList) == 0 {
|
||||||
@@ -170,7 +218,6 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
|
|||||||
tempArr := strings.Split(chiList[i], ",")
|
tempArr := strings.Split(chiList[i], ",")
|
||||||
chiArr[tempArr[0]] = chiList[i]
|
chiArr[tempArr[0]] = chiList[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
var maxSector uint64 = 0
|
var maxSector uint64 = 0
|
||||||
for i := 0; i < len(m.Children); i++ {
|
for i := 0; i < len(m.Children); i++ {
|
||||||
tempArr := strings.Split(chiArr[m.Children[i].Path], ",")
|
tempArr := strings.Split(chiArr[m.Children[i].Path], ",")
|
||||||
@@ -179,13 +226,13 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
|
|||||||
if m.Children[i].EndSector > maxSector {
|
if m.Children[i].EndSector > maxSector {
|
||||||
maxSector = m.Children[i].EndSector
|
maxSector = m.Children[i].EndSector
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
diskEndSector := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetDiskSizeAndSectors " + m.Path)
|
diskEndSector := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetDiskSizeAndSectors " + m.Path)
|
||||||
|
|
||||||
if len(diskEndSector) < 2 {
|
if len(diskEndSector) < 2 {
|
||||||
d.log.Error("diskEndSector length error")
|
d.log.Error("diskEndSector length error")
|
||||||
}
|
}
|
||||||
|
|
||||||
diskEndSectorInt, _ := strconv.ParseUint(diskEndSector[len(diskEndSector)-1], 10, 64)
|
diskEndSectorInt, _ := strconv.ParseUint(diskEndSector[len(diskEndSector)-1], 10, 64)
|
||||||
if (diskEndSectorInt-maxSector)*m.MinIO/1024/1024 > 100 {
|
if (diskEndSectorInt-maxSector)*m.MinIO/1024/1024 > 100 {
|
||||||
//添加可以分区情况
|
//添加可以分区情况
|
||||||
@@ -196,17 +243,38 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
|
|||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
//func GetDiskInfo(path string) *disk.UsageStat {
|
func (d *diskService) MountDisk(path, volume string) {
|
||||||
// diskInfo, _ := disk.Usage(path)
|
r := command2.ExecResultStr("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;do_mount " + path + " " + volume)
|
||||||
// diskInfo.UsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.UsedPercent), 64)
|
fmt.Print(r)
|
||||||
// diskInfo.InodesUsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.InodesUsedPercent), 64)
|
}
|
||||||
// return diskInfo
|
|
||||||
//}
|
func (d *diskService) SaveMountPoint(m model2.SerialDisk) {
|
||||||
|
d.db.Where("uuid = ?", m.UUID).Delete(&model2.SerialDisk{})
|
||||||
//func (d *diskService) GetPlugInDisk() []string {
|
d.db.Create(&m)
|
||||||
// return disk.Partitions(false)
|
}
|
||||||
//}
|
|
||||||
|
func (d *diskService) UpdateMountPoint(m model2.SerialDisk) {
|
||||||
func NewDiskService(log loger2.OLog) DiskService {
|
d.db.Model(&model2.SerialDisk{}).Where("uui = ?", m.UUID).Update("mount_point", m.MountPoint)
|
||||||
return &diskService{log: log}
|
}
|
||||||
|
|
||||||
|
func (d *diskService) DeleteMount(id string) {
|
||||||
|
|
||||||
|
d.db.Delete(&model2.SerialDisk{}).Where("id = ?", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *diskService) DeleteMountPoint(path, mountPoint string) {
|
||||||
|
|
||||||
|
d.db.Where("path = ? AND mount_point = ?", path, mountPoint).Delete(&model2.SerialDisk{})
|
||||||
|
|
||||||
|
command2.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;do_umount " + path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *diskService) GetSerialAll() []model2.SerialDisk {
|
||||||
|
var m []model2.SerialDisk
|
||||||
|
d.db.Find(&m)
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDiskService(log loger2.OLog, db *gorm.DB) DiskService {
|
||||||
|
return &diskService{log: log, db: db}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
json2 "encoding/json"
|
json2 "encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"reflect"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
@@ -20,6 +20,7 @@ import (
|
|||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/docker"
|
"github.com/IceWhaleTech/CasaOS/pkg/docker"
|
||||||
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/env_helper"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||||
|
|
||||||
@@ -51,7 +52,7 @@ type DockerService interface {
|
|||||||
DockerListByImage(image, version string) (*types.Container, error)
|
DockerListByImage(image, version string) (*types.Container, error)
|
||||||
DockerContainerInfo(name string) (*types.ContainerJSON, error)
|
DockerContainerInfo(name string) (*types.ContainerJSON, error)
|
||||||
DockerImageRemove(name string) error
|
DockerImageRemove(name string) error
|
||||||
DockerContainerRemove(name string) error
|
DockerContainerRemove(name string, update bool) error
|
||||||
DockerContainerStop(id string) error
|
DockerContainerStop(id string) error
|
||||||
DockerContainerUpdateName(name, id string) (err error)
|
DockerContainerUpdateName(name, id string) (err error)
|
||||||
DockerContainerUpdate(m model.CustomizationPostData, id string) (err error)
|
DockerContainerUpdate(m model.CustomizationPostData, id string) (err error)
|
||||||
@@ -60,6 +61,7 @@ type DockerService interface {
|
|||||||
DockerNetworkModelList() []types.NetworkResource
|
DockerNetworkModelList() []types.NetworkResource
|
||||||
DockerImageInfo(image string)
|
DockerImageInfo(image string)
|
||||||
GetNetWorkNameByNetWorkID(id string) (string, error)
|
GetNetWorkNameByNetWorkID(id string) (string, error)
|
||||||
|
ContainerExecShell(container_id string) string
|
||||||
}
|
}
|
||||||
|
|
||||||
type dockerService struct {
|
type dockerService struct {
|
||||||
@@ -67,15 +69,20 @@ type dockerService struct {
|
|||||||
log loger2.OLog
|
log loger2.OLog
|
||||||
}
|
}
|
||||||
|
|
||||||
func DockerPs() {
|
func (ds *dockerService) ContainerExecShell(container_id string) string {
|
||||||
cli, _ := client2.NewClientWithOpts(client2.FromEnv)
|
cli, _ := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{})
|
exec, err := cli.ContainerExecCreate(context.Background(), container_id, types.ExecConfig{
|
||||||
|
User: "1000:1000",
|
||||||
|
Cmd: []string{"echo -e \"hellow\nworld\" >> /a.txt"},
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.Exit(5)
|
os.Exit(5)
|
||||||
}
|
}
|
||||||
for _, container := range containers {
|
err = cli.ContainerExecStart(context.Background(), exec.ID, types.ExecStartCheck{})
|
||||||
fmt.Printf("%s %s\n", container.ID[:10], container.Image)
|
if err != nil {
|
||||||
|
fmt.Println("exec script error ", err)
|
||||||
}
|
}
|
||||||
|
return exec.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
//创建默认网络
|
//创建默认网络
|
||||||
@@ -99,7 +106,7 @@ func (ds *dockerService) GetNetWorkNameByNetWorkID(id string) (string, error) {
|
|||||||
defer cli.Close()
|
defer cli.Close()
|
||||||
filter := filters.NewArgs()
|
filter := filters.NewArgs()
|
||||||
filter.Add("id", id)
|
filter.Add("id", id)
|
||||||
d, err := cli.NetworkList(context.Background(), types.NetworkListOptions{filter})
|
d, err := cli.NetworkList(context.Background(), types.NetworkListOptions{Filters: filter})
|
||||||
if err == nil && len(d) > 0 {
|
if err == nil && len(d) > 0 {
|
||||||
return d[0].Name, nil
|
return d[0].Name, nil
|
||||||
}
|
}
|
||||||
@@ -150,7 +157,7 @@ func DockerEx() {
|
|||||||
importResponse.Close()
|
importResponse.Close()
|
||||||
println(string(response))
|
println(string(response))
|
||||||
if string(response) != "response" {
|
if string(response) != "response" {
|
||||||
fmt.Println("expected response to contain 'response', got %s", string(response))
|
fmt.Printf("expected response to contain 'response', got %s", string(response))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +186,6 @@ func (ds *dockerService) DockerImageInfo(image string) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Print(err)
|
fmt.Print(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func MsqlExec(container string) error {
|
func MsqlExec(container string) error {
|
||||||
@@ -258,6 +264,8 @@ func DockerLogs() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
defer i.Close()
|
||||||
|
|
||||||
hdr := make([]byte, 8)
|
hdr := make([]byte, 8)
|
||||||
for {
|
for {
|
||||||
_, err := i.Read(hdr)
|
_, err := i.Read(hdr)
|
||||||
@@ -276,7 +284,6 @@ func DockerLogs() {
|
|||||||
_, err = i.Read(dat)
|
_, err = i.Read(dat)
|
||||||
fmt.Fprint(w, string(dat))
|
fmt.Fprint(w, string(dat))
|
||||||
}
|
}
|
||||||
defer i.Close()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//正式内容
|
//正式内容
|
||||||
@@ -325,10 +332,13 @@ func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) e
|
|||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
m.Type = types2.NOTIFY_TYPE_INSTALL_LOG
|
if !reflect.DeepEqual(m, model2.AppNotify{}) {
|
||||||
m.State = 0
|
m.Type = types2.NOTIFY_TYPE_INSTALL_LOG
|
||||||
m.Message = string(buf[:n])
|
m.State = 0
|
||||||
MyService.Notify().UpdateLog(m)
|
m.Message = string(buf[:n])
|
||||||
|
MyService.Notify().UpdateLog(m)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -341,7 +351,7 @@ func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) e
|
|||||||
//param udp 容器其他udp端口
|
//param udp 容器其他udp端口
|
||||||
func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId string, m model.CustomizationPostData, net string) (containerId string, err error) {
|
func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId string, m model.CustomizationPostData, net string) (containerId string, err error) {
|
||||||
if len(net) == 0 {
|
if len(net) == 0 {
|
||||||
net = "oasis"
|
net = "bridge"
|
||||||
}
|
}
|
||||||
|
|
||||||
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
@@ -355,18 +365,18 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
|||||||
// if net != "host" {
|
// if net != "host" {
|
||||||
// portMaps[nat.Port(fmt.Sprint(m.Port)+"/tcp")] = []nat.PortBinding{{HostIP: "", HostPort: m.PortMap}}
|
// portMaps[nat.Port(fmt.Sprint(m.Port)+"/tcp")] = []nat.PortBinding{{HostIP: "", HostPort: m.PortMap}}
|
||||||
// }
|
// }
|
||||||
port := ""
|
//port := ""
|
||||||
for _, portMap := range m.Ports {
|
for _, portMap := range m.Ports {
|
||||||
if portMap.CommendPort == m.PortMap && portMap.Protocol == "tcp" || portMap.Protocol == "both" {
|
// if portMap.CommendPort == m.PortMap && portMap.Protocol == "tcp" || portMap.Protocol == "both" {
|
||||||
port = portMap.ContainerPort
|
// port = portMap.ContainerPort
|
||||||
}
|
// }
|
||||||
if portMap.Protocol == "tcp" {
|
if portMap.Protocol == "tcp" {
|
||||||
|
|
||||||
tContainer, _ := strconv.Atoi(portMap.ContainerPort)
|
tContainer, _ := strconv.Atoi(portMap.ContainerPort)
|
||||||
if tContainer > 0 {
|
if tContainer > 0 {
|
||||||
ports[nat.Port(portMap.ContainerPort+"/tcp")] = struct{}{}
|
ports[nat.Port(portMap.ContainerPort+"/tcp")] = struct{}{}
|
||||||
if net != "host" {
|
if net != "host" {
|
||||||
portMaps[nat.Port(portMap.ContainerPort+"/tcp")] = []nat.PortBinding{{HostIP: "0.0.0.0", HostPort: portMap.CommendPort}}
|
portMaps[nat.Port(portMap.ContainerPort+"/tcp")] = []nat.PortBinding{{HostPort: portMap.CommendPort}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if portMap.Protocol == "both" {
|
} else if portMap.Protocol == "both" {
|
||||||
@@ -375,7 +385,7 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
|||||||
if tContainer > 0 {
|
if tContainer > 0 {
|
||||||
ports[nat.Port(portMap.ContainerPort+"/tcp")] = struct{}{}
|
ports[nat.Port(portMap.ContainerPort+"/tcp")] = struct{}{}
|
||||||
if net != "host" {
|
if net != "host" {
|
||||||
portMaps[nat.Port(portMap.ContainerPort+"/tcp")] = []nat.PortBinding{{HostIP: "0.0.0.0", HostPort: portMap.CommendPort}}
|
portMaps[nat.Port(portMap.ContainerPort+"/tcp")] = []nat.PortBinding{{HostPort: portMap.CommendPort}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,7 +393,7 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
|||||||
if uContainer > 0 {
|
if uContainer > 0 {
|
||||||
ports[nat.Port(portMap.ContainerPort+"/udp")] = struct{}{}
|
ports[nat.Port(portMap.ContainerPort+"/udp")] = struct{}{}
|
||||||
if net != "host" {
|
if net != "host" {
|
||||||
portMaps[nat.Port(portMap.ContainerPort+"/udp")] = []nat.PortBinding{{HostIP: "0.0.0.0", HostPort: portMap.CommendPort}}
|
portMaps[nat.Port(portMap.ContainerPort+"/udp")] = []nat.PortBinding{{HostPort: portMap.CommendPort}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,7 +402,7 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
|||||||
if uContainer > 0 {
|
if uContainer > 0 {
|
||||||
ports[nat.Port(portMap.ContainerPort+"/udp")] = struct{}{}
|
ports[nat.Port(portMap.ContainerPort+"/udp")] = struct{}{}
|
||||||
if net != "host" {
|
if net != "host" {
|
||||||
portMaps[nat.Port(portMap.ContainerPort+"/udp")] = []nat.PortBinding{{HostIP: "0.0.0.0", HostPort: portMap.CommendPort}}
|
portMaps[nat.Port(portMap.ContainerPort+"/udp")] = []nat.PortBinding{{HostPort: portMap.CommendPort}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -401,6 +411,10 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
|||||||
|
|
||||||
var envArr []string
|
var envArr []string
|
||||||
for _, e := range m.Envs {
|
for _, e := range m.Envs {
|
||||||
|
if strings.HasPrefix(e.Value, "$") {
|
||||||
|
envArr = append(envArr, e.Name+"="+env_helper.ReplaceDefaultENV(e.Value, MyService.System().GetTimeZone()))
|
||||||
|
continue
|
||||||
|
}
|
||||||
if len(e.Value) > 0 {
|
if len(e.Value) > 0 {
|
||||||
if e.Value == "port_map" {
|
if e.Value == "port_map" {
|
||||||
envArr = append(envArr, e.Name+"="+m.PortMap)
|
envArr = append(envArr, e.Name+"="+m.PortMap)
|
||||||
@@ -419,7 +433,7 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
|||||||
}
|
}
|
||||||
for _, p := range m.Devices {
|
for _, p := range m.Devices {
|
||||||
if len(p.Path) > 0 {
|
if len(p.Path) > 0 {
|
||||||
res.Devices = append(res.Devices, container.DeviceMapping{PathOnHost: p.Path, PathInContainer: p.ContainerPath})
|
res.Devices = append(res.Devices, container.DeviceMapping{PathOnHost: p.Path, PathInContainer: p.ContainerPath, CgroupPermissions: "rwm"})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hostConfingBind := []string{}
|
hostConfingBind := []string{}
|
||||||
@@ -428,26 +442,28 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
|||||||
for _, v := range m.Volumes {
|
for _, v := range m.Volumes {
|
||||||
path := v.Path
|
path := v.Path
|
||||||
if len(path) == 0 {
|
if len(path) == 0 {
|
||||||
path = docker.GetDir(containerDbId, v.ContainerPath)
|
path = docker.GetDir(containerDbId, v.Path)
|
||||||
if len(path) == 0 {
|
if len(path) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reg1 := regexp.MustCompile(`([^<>/\\\|:""\*\?]+\.\w+$)`)
|
path = strings.ReplaceAll(path, "$AppID", containerDbId)
|
||||||
result1 := reg1.FindAllStringSubmatch(path, -1)
|
//reg1 := regexp.MustCompile(`([^<>/\\\|:""\*\?]+\.\w+$)`)
|
||||||
if len(result1) == 0 {
|
//result1 := reg1.FindAllStringSubmatch(path, -1)
|
||||||
err = file.IsNotExistMkDir(path)
|
//if len(result1) == 0 {
|
||||||
if err != nil {
|
err = file.IsNotExistMkDir(path)
|
||||||
ds.log.Error("mkdir error", err)
|
if err != nil {
|
||||||
continue
|
ds.log.Error("mkdir error", err)
|
||||||
}
|
continue
|
||||||
} else {
|
|
||||||
err = file.IsNotExistCreateFile(path)
|
|
||||||
if err != nil {
|
|
||||||
ds.log.Error("mkdir error", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
//}
|
||||||
|
// else {
|
||||||
|
// err = file.IsNotExistCreateFile(path)
|
||||||
|
// if err != nil {
|
||||||
|
// ds.log.Error("mkdir error", err)
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
volumes = append(volumes, mount.Mount{
|
volumes = append(volumes, mount.Mount{
|
||||||
Type: mount.TypeBind,
|
Type: mount.TypeBind,
|
||||||
@@ -463,25 +479,29 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
|||||||
if len(m.Restart) > 0 {
|
if len(m.Restart) > 0 {
|
||||||
rp.Name = m.Restart
|
rp.Name = m.Restart
|
||||||
}
|
}
|
||||||
//fmt.Print(port)
|
// healthTest := []string{}
|
||||||
healthTest := []string{}
|
// if len(port) > 0 {
|
||||||
if len(port) > 0 {
|
// healthTest = []string{"CMD-SHELL", "curl -f http://localhost:" + port + m.Index + " || exit 1"}
|
||||||
healthTest = []string{"CMD-SHELL", "curl -f http://localhost:" + port + m.Index + " || exit 1"}
|
// }
|
||||||
}
|
|
||||||
|
|
||||||
health := &container.HealthConfig{
|
// health := &container.HealthConfig{
|
||||||
Test: healthTest,
|
// Test: healthTest,
|
||||||
//Test: []string{},
|
// StartPeriod: 0,
|
||||||
StartPeriod: 0,
|
// Retries: 1000,
|
||||||
Retries: 1000,
|
// }
|
||||||
|
// fmt.Print(health)
|
||||||
|
if len(m.HostName) == 0 {
|
||||||
|
m.HostName = m.Label
|
||||||
}
|
}
|
||||||
config := &container.Config{
|
config := &container.Config{
|
||||||
Image: imageName,
|
Image: imageName,
|
||||||
Labels: map[string]string{"origin": m.Origin, m.Origin: m.Origin},
|
Labels: map[string]string{"origin": m.Origin, m.Origin: m.Origin},
|
||||||
Env: envArr,
|
Env: envArr,
|
||||||
Healthcheck: health,
|
// Healthcheck: health,
|
||||||
|
Hostname: m.HostName,
|
||||||
|
Cmd: m.Cmd,
|
||||||
}
|
}
|
||||||
hostConfig := &container.HostConfig{Resources: res, Mounts: volumes, RestartPolicy: rp, NetworkMode: container.NetworkMode(net)}
|
hostConfig := &container.HostConfig{Resources: res, Mounts: volumes, RestartPolicy: rp, NetworkMode: container.NetworkMode(net), Privileged: m.Privileged, CapAdd: m.CapAdd}
|
||||||
//if net != "host" {
|
//if net != "host" {
|
||||||
config.ExposedPorts = ports
|
config.ExposedPorts = ports
|
||||||
hostConfig.PortBindings = portMaps
|
hostConfig.PortBindings = portMaps
|
||||||
@@ -500,7 +520,7 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
|||||||
}
|
}
|
||||||
|
|
||||||
//删除容器
|
//删除容器
|
||||||
func (ds *dockerService) DockerContainerRemove(name string) error {
|
func (ds *dockerService) DockerContainerRemove(name string, update bool) error {
|
||||||
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -509,9 +529,11 @@ func (ds *dockerService) DockerContainerRemove(name string) error {
|
|||||||
err = cli.ContainerRemove(context.Background(), name, types.ContainerRemoveOptions{})
|
err = cli.ContainerRemove(context.Background(), name, types.ContainerRemoveOptions{})
|
||||||
|
|
||||||
//路径处理
|
//路径处理
|
||||||
path := docker.GetDir(name, "/config")
|
if !update {
|
||||||
if !file.CheckNotExist(path) {
|
path := docker.GetDir(name, "/config")
|
||||||
file.RMDir(path)
|
if !file.CheckNotExist(path) {
|
||||||
|
file.RMDir(path)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -737,7 +759,7 @@ func (ds *dockerService) DockerContainerUpdate(m model.CustomizationPostData, id
|
|||||||
res.CPUShares = m.CpuShares
|
res.CPUShares = m.CpuShares
|
||||||
}
|
}
|
||||||
for _, p := range m.Devices {
|
for _, p := range m.Devices {
|
||||||
res.Devices = append(res.Devices, container.DeviceMapping{PathOnHost: p.Path, PathInContainer: p.ContainerPath})
|
res.Devices = append(res.Devices, container.DeviceMapping{PathOnHost: p.Path, PathInContainer: p.ContainerPath, CgroupPermissions: "rwm"})
|
||||||
}
|
}
|
||||||
_, err = cli.ContainerUpdate(context.Background(), id, container.UpdateConfig{RestartPolicy: rp, Resources: res})
|
_, err = cli.ContainerUpdate(context.Background(), id, container.UpdateConfig{RestartPolicy: rp, Resources: res})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -772,7 +794,7 @@ func (ds *dockerService) DockerNetworkModelList() []types.NetworkResource {
|
|||||||
networks, _ := cli.NetworkList(context.Background(), types.NetworkListOptions{})
|
networks, _ := cli.NetworkList(context.Background(), types.NetworkListOptions{})
|
||||||
return networks
|
return networks
|
||||||
}
|
}
|
||||||
func NewDcokerService(log loger2.OLog) DockerService {
|
func NewDockerService(log loger2.OLog) DockerService {
|
||||||
return &dockerService{rootDir: command2.ExecResultStr(`source ./shell/helper.sh ;GetDockerRootDir`), log: log}
|
return &dockerService{rootDir: command2.ExecResultStr(`source ./shell/helper.sh ;GetDockerRootDir`), log: log}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -816,7 +838,6 @@ func Containerd() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("333")
|
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
defer container.Delete(ctx, containerd.WithSnapshotCleanup)
|
defer container.Delete(ctx, containerd.WithSnapshotCleanup)
|
||||||
@@ -824,7 +845,6 @@ func Containerd() {
|
|||||||
// create a task from the container
|
// create a task from the container
|
||||||
task, err := container.NewTask(ctx, cio.NewCreator(cio.WithStdio))
|
task, err := container.NewTask(ctx, cio.NewCreator(cio.WithStdio))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("444")
|
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
defer task.Delete(ctx)
|
defer task.Delete(ctx)
|
||||||
@@ -837,7 +857,6 @@ func Containerd() {
|
|||||||
|
|
||||||
// call start on the task to execute the redis server
|
// call start on the task to execute the redis server
|
||||||
if err = task.Start(ctx); err != nil {
|
if err = task.Start(ctx); err != nil {
|
||||||
fmt.Println("555")
|
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -847,7 +866,6 @@ func Containerd() {
|
|||||||
|
|
||||||
// kill the process and get the exit status
|
// kill the process and get the exit status
|
||||||
if err = task.Kill(ctx, syscall.SIGTERM); err != nil {
|
if err = task.Kill(ctx, syscall.SIGTERM); err != nil {
|
||||||
fmt.Println("666")
|
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -856,7 +874,6 @@ func Containerd() {
|
|||||||
status := <-exitStatusC
|
status := <-exitStatusC
|
||||||
code, _, err := status.Result()
|
code, _, err := status.Result()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("777")
|
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
fmt.Printf("redis-server exited with status: %d\n", code)
|
fmt.Printf("redis-server exited with status: %d\n", code)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package docker_base
|
|||||||
import "github.com/IceWhaleTech/CasaOS/model"
|
import "github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
|
||||||
//过滤mysql关键字
|
//过滤mysql关键字
|
||||||
func MysqlFilter(c MysqlConfig, envs model.EnvArrey) model.EnvArrey {
|
func MysqlFilter(c MysqlConfig, envs model.EnvArray) model.EnvArray {
|
||||||
for i := 0; i < len(envs); i++ {
|
for i := 0; i < len(envs); i++ {
|
||||||
switch envs[i].Value {
|
switch envs[i].Value {
|
||||||
case "$MYSQL_HOST":
|
case "$MYSQL_HOST":
|
||||||
|
|||||||
@@ -7,5 +7,3 @@ type MysqlConfig struct {
|
|||||||
DataBasePassword string `json:"data_base_password"`
|
DataBasePassword string `json:"data_base_password"`
|
||||||
DataBaseDB string `json:"data_base_db"`
|
DataBaseDB string `json:"data_base_db"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
66
service/download.go
Normal file
66
service/download.go
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DownloadService interface {
|
||||||
|
AddDownloadTask(m model2.PersonDownloadDBModel) //添加下载任务
|
||||||
|
EditDownloadState(m model2.PersonDownloadDBModel) //只修改状态
|
||||||
|
SaveDownload(m model2.PersonDownloadDBModel)
|
||||||
|
DelDownload(uuid string)
|
||||||
|
GetDownloadById(uuid string) model2.PersonDownloadDBModel
|
||||||
|
GetDownloadListByState(state string) []model2.PersonDownloadDBModel
|
||||||
|
SetDownloadError(m model2.PersonDownloadDBModel)
|
||||||
|
GetDownloadListByPath(m model2.PersonDownloadDBModel) int
|
||||||
|
}
|
||||||
|
type downloadService struct {
|
||||||
|
db *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *downloadService) GetDownloadListByPath(m model2.PersonDownloadDBModel) int {
|
||||||
|
var list []model2.PersonDownloadDBModel
|
||||||
|
d.db.Select("path").Where("path = ? AND `from` = ? AND state = 0", m.Path, m.From).Find(&list)
|
||||||
|
return len(list)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *downloadService) AddDownloadTask(m model2.PersonDownloadDBModel) {
|
||||||
|
|
||||||
|
d.db.Create(&m)
|
||||||
|
}
|
||||||
|
func (d *downloadService) EditDownloadState(m model2.PersonDownloadDBModel) {
|
||||||
|
|
||||||
|
d.db.Model(&m).Where("uuid = ?", m.UUID).Update("state", m.State)
|
||||||
|
}
|
||||||
|
|
||||||
|
//failed during download
|
||||||
|
func (d *downloadService) SetDownloadError(m model2.PersonDownloadDBModel) {
|
||||||
|
d.db.Model(&m).Updates(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *downloadService) DelDownload(uuid string) {
|
||||||
|
var m model2.PersonDownloadDBModel
|
||||||
|
d.db.Where("uuid = ?", uuid).Delete(&m)
|
||||||
|
}
|
||||||
|
func (d *downloadService) GetDownloadById(uuid string) model2.PersonDownloadDBModel {
|
||||||
|
var m model2.PersonDownloadDBModel
|
||||||
|
d.db.Model(m).Where("uuid = ?", uuid).First(&m)
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
func (d *downloadService) GetDownloadListByState(state string) (list []model2.PersonDownloadDBModel) {
|
||||||
|
if len(state) == 0 {
|
||||||
|
d.db.Find(&list)
|
||||||
|
} else {
|
||||||
|
d.db.Where("state = ?", state).Find(&list)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *downloadService) SaveDownload(m model2.PersonDownloadDBModel) {
|
||||||
|
d.db.Save(&m)
|
||||||
|
}
|
||||||
|
func NewDownloadService(db *gorm.DB) DownloadService {
|
||||||
|
return &downloadService{db: db}
|
||||||
|
}
|
||||||
85
service/file.go
Normal file
85
service/file.go
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// type InteruptReader struct {
|
||||||
|
// r io.Reader
|
||||||
|
// interupt chan int
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func NewInteruptReader(r io.Reader) InteruptReader {
|
||||||
|
// return InteruptReader{
|
||||||
|
// r,
|
||||||
|
// make(chan int),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (r InteruptReader) Read(p []byte) (n int, err error) {
|
||||||
|
// if r.r == nil {
|
||||||
|
// return 0, io.EOF
|
||||||
|
// }
|
||||||
|
// select {
|
||||||
|
// case <-r.interupt:
|
||||||
|
// return r.r.Read(p)
|
||||||
|
// default:
|
||||||
|
// r.r = nil
|
||||||
|
// return 0, io.EOF
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (r InteruptReader) Cancel() {
|
||||||
|
// r.interupt <- 0
|
||||||
|
// }
|
||||||
|
|
||||||
|
type reader struct {
|
||||||
|
ctx context.Context
|
||||||
|
r io.Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewReader wraps an io.Reader to handle context cancellation.
|
||||||
|
//
|
||||||
|
// Context state is checked BEFORE every Read.
|
||||||
|
func NewReader(ctx context.Context, r io.Reader) io.Reader {
|
||||||
|
if r, ok := r.(*reader); ok && ctx == r.ctx {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
return &reader{ctx: ctx, r: r}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *reader) Read(p []byte) (n int, err error) {
|
||||||
|
select {
|
||||||
|
case <-r.ctx.Done():
|
||||||
|
return 0, r.ctx.Err()
|
||||||
|
default:
|
||||||
|
return r.r.Read(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type writer struct {
|
||||||
|
ctx context.Context
|
||||||
|
w io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
type copier struct {
|
||||||
|
writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWriter(ctx context.Context, w io.Writer) io.Writer {
|
||||||
|
if w, ok := w.(*copier); ok && ctx == w.ctx {
|
||||||
|
return w
|
||||||
|
}
|
||||||
|
return &copier{writer{ctx: ctx, w: w}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write implements io.Writer, but with context awareness.
|
||||||
|
func (w *writer) Write(p []byte) (n int, err error) {
|
||||||
|
select {
|
||||||
|
case <-w.ctx.Done():
|
||||||
|
return 0, w.ctx.Err()
|
||||||
|
default:
|
||||||
|
return w.w.Write(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
81
service/file_test.go
Normal file
81
service/file_test.go
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ctx context.Context
|
||||||
|
var cancel context.CancelFunc
|
||||||
|
|
||||||
|
func TestNewInteruptReader(t *testing.T) {
|
||||||
|
ctx, cancel = context.WithCancel(context.Background())
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
// 在初始上下文的基础上创建一个有取消功能的上下文
|
||||||
|
// ctx, cancel := context.WithCancel(ctx)
|
||||||
|
fmt.Println("开始")
|
||||||
|
fIn, err := os.Open("/Users/liangjianli/Downloads/demo_data.tar.gz")
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
}
|
||||||
|
defer fIn.Close()
|
||||||
|
fmt.Println("创建新文件")
|
||||||
|
fOut, err := os.Create("/Users/liangjianli/Downloads/demo_data1.tar.gz")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer fOut.Close()
|
||||||
|
|
||||||
|
fmt.Println("准备复制")
|
||||||
|
// _, err = io.Copy(out, NewReader(ctx, f))
|
||||||
|
// time.Sleep(time.Second * 2)
|
||||||
|
//ctx.Done()
|
||||||
|
// cancel()
|
||||||
|
|
||||||
|
// interrupt context after 500ms
|
||||||
|
|
||||||
|
// interrupt context with SIGTERM (CTRL+C)
|
||||||
|
//sigs := make(chan os.Signal, 1)
|
||||||
|
//signal.Notify(sigs, os.Interrupt)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reader that fails when context is canceled
|
||||||
|
in := NewReader(ctx, fIn)
|
||||||
|
// Writer that fails when context is canceled
|
||||||
|
out := NewWriter(ctx, fOut)
|
||||||
|
|
||||||
|
//time.Sleep(2 * time.Second)
|
||||||
|
|
||||||
|
//cancel()
|
||||||
|
|
||||||
|
n, err := io.Copy(out, in)
|
||||||
|
log.Println(n, "bytes copied.")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Err:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Closing.")
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
//<-sigs
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
fmt.Println("退出")
|
||||||
|
ddd()
|
||||||
|
}()
|
||||||
|
time.Sleep(time.Second * 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ddd() {
|
||||||
|
cancel()
|
||||||
|
}
|
||||||
64
service/friend.go
Normal file
64
service/friend.go
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FriendService interface {
|
||||||
|
AddFriend(m model2.FriendModel)
|
||||||
|
DeleteFriend(m model2.FriendModel)
|
||||||
|
EditFriendMark(m model2.FriendModel)
|
||||||
|
EditFriendBlock(m model2.FriendModel)
|
||||||
|
GetFriendById(m model2.FriendModel) model2.FriendModel
|
||||||
|
GetFriendList() (list []model2.FriendModel)
|
||||||
|
UpdateAddFriendType(m model2.FriendModel)
|
||||||
|
UpdateOrCreate(m model2.FriendModel)
|
||||||
|
}
|
||||||
|
|
||||||
|
type friendService struct {
|
||||||
|
db *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *friendService) AddFriend(m model2.FriendModel) {
|
||||||
|
p.db.Create(&m)
|
||||||
|
}
|
||||||
|
func (p *friendService) DeleteFriend(m model2.FriendModel) {
|
||||||
|
p.db.Where("token = ?", m.Token).Delete(&m)
|
||||||
|
}
|
||||||
|
func (p *friendService) EditFriendMark(m model2.FriendModel) {
|
||||||
|
p.db.Model(&m).Where("token = ?", m.Token).Update("mark", m.Mark)
|
||||||
|
}
|
||||||
|
func (p *friendService) EditFriendBlock(m model2.FriendModel) {
|
||||||
|
p.db.Model(&m).Where("token = ?", m.Token).Update("block", m.Block)
|
||||||
|
}
|
||||||
|
func (p *friendService) GetFriendById(m model2.FriendModel) model2.FriendModel {
|
||||||
|
p.db.Model(m).Where("token = ?", m.Token).First(&m)
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *friendService) GetFriendList() (list []model2.FriendModel) {
|
||||||
|
p.db.Select("nick_name", "avatar", "profile", "token", "state", "mark", "block", "version").Find(&list)
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *friendService) UpdateOrCreate(m model2.FriendModel) {
|
||||||
|
friend := model2.FriendModel{}
|
||||||
|
p.db.Where("token = ?", m.Token).First(&friend)
|
||||||
|
if reflect.DeepEqual(friend, model2.FriendModel{}) {
|
||||||
|
p.db.Create(&m)
|
||||||
|
} else {
|
||||||
|
p.db.Model(&m).Updates(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *friendService) UpdateAddFriendType(m model2.FriendModel) {
|
||||||
|
p.db.Model(&m).Updates(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFriendService(db *gorm.DB) FriendService {
|
||||||
|
return &friendService{db: db}
|
||||||
|
}
|
||||||
@@ -26,14 +26,10 @@ type AppListDBModel struct {
|
|||||||
PortMap string `json:"port_map"`
|
PortMap string `json:"port_map"`
|
||||||
Label string `json:"label"`
|
Label string `json:"label"`
|
||||||
EnableUPNP bool `json:"enable_upnp"`
|
EnableUPNP bool `json:"enable_upnp"`
|
||||||
//Envs model.EnvArrey `json:"envs" bson:"envs"`
|
Envs string `json:"envs"`
|
||||||
//Ports model.PortArrey `json:"ports" bson:"ports"`
|
Ports string `json:"ports"`
|
||||||
//Volumes model.PathArrey `json:"volumes" bson:"volumes"`
|
Volumes string `json:"volumes"`
|
||||||
//Devices model.PathArrey `json:"devices" bson:"devices"`
|
Devices string `json:"devices"`
|
||||||
Envs string `json:"envs"`
|
|
||||||
Ports string `json:"ports"`
|
|
||||||
Volumes string `json:"volumes"`
|
|
||||||
Devices string `json:"devices"`
|
|
||||||
//Envs []model.Env `json:"envs"`
|
//Envs []model.Env `json:"envs"`
|
||||||
//Ports []model.PortMap `gorm:"type:json" json:"ports"`
|
//Ports []model.PortMap `gorm:"type:json" json:"ports"`
|
||||||
//Volumes []model.PathMap `gorm:"type:json" json:"volumes"`
|
//Volumes []model.PathMap `gorm:"type:json" json:"volumes"`
|
||||||
@@ -44,7 +40,11 @@ type AppListDBModel struct {
|
|||||||
Memory int64 `json:"memory"`
|
Memory int64 `json:"memory"`
|
||||||
Restart string `json:"restart"`
|
Restart string `json:"restart"`
|
||||||
//Rely model.MapStrings `gorm:"type:json" json:"rely"` //[{"mysql":"id"},{"mysql":"id"}]
|
//Rely model.MapStrings `gorm:"type:json" json:"rely"` //[{"mysql":"id"},{"mysql":"id"}]
|
||||||
Origin string `json:"origin"`
|
Origin string `json:"origin"`
|
||||||
|
HostName string `json:"host_name"`
|
||||||
|
Privileged bool `json:"privileged"`
|
||||||
|
CapAdd string `json:"cap_add"`
|
||||||
|
Cmd string `gorm:"type:json" json:"cmd"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *AppListDBModel) TableName() string {
|
func (p *AppListDBModel) TableName() string {
|
||||||
@@ -61,4 +61,6 @@ type MyAppList struct {
|
|||||||
UpTime string `json:"up_time"`
|
UpTime string `json:"up_time"`
|
||||||
Slogan string `json:"slogan"`
|
Slogan string `json:"slogan"`
|
||||||
Rely model.MapStrings `json:"rely"` //[{"mysql":"id"},{"mysql":"id"}]
|
Rely model.MapStrings `json:"rely"` //[{"mysql":"id"},{"mysql":"id"}]
|
||||||
|
Image string `json:"image"`
|
||||||
|
Volumes string `json:"volumes"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ package model
|
|||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
func (p *DDNSUpdataDBModel) TableName() string {
|
func (p *DDNSUpdateDBModel) TableName() string {
|
||||||
return "o_ddns"
|
return "o_ddns"
|
||||||
}
|
}
|
||||||
|
|
||||||
type DDNSUpdataDBModel struct {
|
type DDNSUpdateDBModel struct {
|
||||||
Id uint `gorm:"column:id;primary_key" json:"id"`
|
Id uint `gorm:"column:id;primary_key" json:"id"`
|
||||||
Ipv4 string `gorm:"-"`
|
Ipv4 string `gorm:"-"`
|
||||||
Ipv6 string `gorm:"-"`
|
Ipv6 string `gorm:"-"`
|
||||||
@@ -17,8 +17,8 @@ type DDNSUpdataDBModel struct {
|
|||||||
Secret string `json:"secret" form:"secret"`
|
Secret string `json:"secret" form:"secret"`
|
||||||
UserName string `json:"user_name" form:"user_name"`
|
UserName string `json:"user_name" form:"user_name"`
|
||||||
Password string `json:"password" form:"password"`
|
Password string `json:"password" form:"password"`
|
||||||
CreatedAt time.Time `gorm:"<-:create" json:"created_at"`
|
CreatedAt time.Time `gorm:"<-:create" json:"created_at"`
|
||||||
UpdatedAt time.Time `gorm:"<-:create;<-:update" json:"updated_at"`
|
UpdatedAt time.Time `gorm:"<-:create;<-:update" json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
const DDNSLISTTABLENAME = "o_ddns"
|
const DDNSLISTTABLENAME = "o_ddns"
|
||||||
@@ -39,9 +39,9 @@ type DDNSList struct {
|
|||||||
|
|
||||||
//定时任务使用
|
//定时任务使用
|
||||||
type DDNSCoreList struct {
|
type DDNSCoreList struct {
|
||||||
Id uint `gorm:"column:id;primary_key" json:"id"`
|
Id uint `gorm:"column:id;primary_key" json:"id"`
|
||||||
Domain string `json:"domain" form:"domain"`
|
Domain string `json:"domain" form:"domain"`
|
||||||
Name string `json:"domain" form:"name"`
|
Name string `json:"name" form:"name"`
|
||||||
Type uint `json:"type"`
|
Type uint `json:"type"`
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
|
|||||||
15
service/model/o_disk.go
Normal file
15
service/model/o_disk.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
//SerialAdvanced Technology Attachment (STAT)
|
||||||
|
type SerialDisk struct {
|
||||||
|
Id uint `gorm:"column:id;primary_key" json:"id"`
|
||||||
|
UUID string `json:"uuid"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
State int `json:"state"`
|
||||||
|
MountPoint string `json:"mount_point"`
|
||||||
|
CreatedAt int64 `json:"created_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *SerialDisk) TableName() string {
|
||||||
|
return "o_disk"
|
||||||
|
}
|
||||||
24
service/model/o_download.go
Normal file
24
service/model/o_download.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type PersonDownloadDBModel struct {
|
||||||
|
UUID string `gorm:"column:uuid;primary_key" json:"uuid"`
|
||||||
|
State int `json:"state"` //
|
||||||
|
Type int `json:"type"` //defult 1
|
||||||
|
Name string `json:"name"` //file name
|
||||||
|
Size int64 `json:"size"` //file size
|
||||||
|
BlockSize int `json:"block_size"` //Size of each file block
|
||||||
|
Length int `json:"length"` //slice length
|
||||||
|
Hash string `json:"hash"` //File hash value
|
||||||
|
Error string `json:"error"` //
|
||||||
|
From string `json:"from"` //Error message
|
||||||
|
Path string `json:"path"` //Full path to the file
|
||||||
|
Already int `json:"already" gorm:"-"` //Folder blocks that have been downloaded
|
||||||
|
LocalPath string `json:"local_path"` //The address where the file is saved after download
|
||||||
|
Duration int64 `json:"duration" gorm:"-"` //Length of time
|
||||||
|
Created int64 `gorm:"autoCreateTime" json:"created"`
|
||||||
|
Updated int64 `gorm:"autoCreateTime;autoUpdateTime" json:"updated"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PersonDownloadDBModel) TableName() string {
|
||||||
|
return "o_person_download"
|
||||||
|
}
|
||||||
19
service/model/o_friend.go
Normal file
19
service/model/o_friend.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type FriendModel struct {
|
||||||
|
State int `json:"state"` //Reserved
|
||||||
|
CreatedAt int64 `gorm:"autoCreateTime" json:"created_at"`
|
||||||
|
UpdatedAt int64 `gorm:"autoCreateTime;autoUpdateTime" json:"updated_at"`
|
||||||
|
NickName string `json:"nick_name"`
|
||||||
|
Mark string `json:"mark"` //Remarks
|
||||||
|
Block bool `json:"block"` //Disable or not
|
||||||
|
Avatar string `json:"avatar"` //User avatar
|
||||||
|
Token string `gorm:"column:token;primary_key" json:"token"`
|
||||||
|
Profile string `json:"profile"` //Description
|
||||||
|
OnLine bool `json:"on_line" gorm:"-"`
|
||||||
|
Version int `json:"version"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *FriendModel) TableName() string {
|
||||||
|
return "o_friend"
|
||||||
|
}
|
||||||
@@ -6,9 +6,11 @@ type AppNotify struct {
|
|||||||
CreatedAt string `json:"created_at"`
|
CreatedAt string `json:"created_at"`
|
||||||
UpdatedAt string `json:"updated_at"`
|
UpdatedAt string `json:"updated_at"`
|
||||||
Id string `json:"id"`
|
Id string `json:"id"`
|
||||||
Type int `json:"type"` // 1:显示即为已读 2:info 3:warning 4:error 5:success
|
Type int `json:"type"`
|
||||||
Icon string `json:"icon"`
|
Icon string `json:"icon"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
Class int `json:"class"`
|
||||||
|
CustomId string `gorm:"column:custom_id;primary_key" json:"custom_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *AppNotify) TableName() string {
|
func (p *AppNotify) TableName() string {
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
json2 "encoding/json"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/service/model"
|
"github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/types"
|
"github.com/IceWhaleTech/CasaOS/types"
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -10,17 +14,19 @@ type NotifyServer interface {
|
|||||||
GetLog(id string) model.AppNotify
|
GetLog(id string) model.AppNotify
|
||||||
AddLog(log model.AppNotify)
|
AddLog(log model.AppNotify)
|
||||||
UpdateLog(log model.AppNotify)
|
UpdateLog(log model.AppNotify)
|
||||||
|
UpdateLogByCustomId(log model.AppNotify)
|
||||||
DelLog(id string)
|
DelLog(id string)
|
||||||
GetList() (list []model.AppNotify)
|
GetList(c int) (list []model.AppNotify)
|
||||||
MarkRead(id string, state int)
|
MarkRead(id string, state int)
|
||||||
|
SendText(m model.AppNotify)
|
||||||
}
|
}
|
||||||
|
|
||||||
type notifyServer struct {
|
type notifyServer struct {
|
||||||
db *gorm.DB
|
db *gorm.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i notifyServer) GetList() (list []model.AppNotify) {
|
func (i notifyServer) GetList(c int) (list []model.AppNotify) {
|
||||||
i.db.Where("state=? or state=?", types.NOTIFY_DYNAMICE, types.NOTIFY_UNREAD).Find(&list)
|
i.db.Where("class = ?", c).Where(i.db.Where("state = ?", types.NOTIFY_DYNAMICE).Or("state = ?", types.NOTIFY_UNREAD)).Find(&list)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,20 +37,92 @@ func (i *notifyServer) AddLog(log model.AppNotify) {
|
|||||||
func (i *notifyServer) UpdateLog(log model.AppNotify) {
|
func (i *notifyServer) UpdateLog(log model.AppNotify) {
|
||||||
i.db.Save(&log)
|
i.db.Save(&log)
|
||||||
}
|
}
|
||||||
|
func (i *notifyServer) UpdateLogByCustomId(log model.AppNotify) {
|
||||||
|
if len(log.CustomId) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
i.db.Model(&model.AppNotify{}).Select("*").Where("custom_id = ? ", log.CustomId).Updates(log)
|
||||||
|
}
|
||||||
func (i *notifyServer) GetLog(id string) model.AppNotify {
|
func (i *notifyServer) GetLog(id string) model.AppNotify {
|
||||||
var log model.AppNotify
|
var log model.AppNotify
|
||||||
i.db.Where("custom_id = ? ", id).First(&log)
|
i.db.Where("custom_id = ? ", id).First(&log)
|
||||||
return log
|
return log
|
||||||
}
|
}
|
||||||
func (i *notifyServer) MarkRead(id string, state int) {
|
func (i *notifyServer) MarkRead(id string, state int) {
|
||||||
i.db.Update("state=", state).Where("custom_id = ? ", id)
|
if id == "0" {
|
||||||
|
i.db.Model(&model.AppNotify{}).Where("1 = ?", 1).Update("state", state)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
i.db.Model(&model.AppNotify{}).Where("id = ? ", id).Update("state", state)
|
||||||
}
|
}
|
||||||
func (i *notifyServer) DelLog(id string) {
|
func (i *notifyServer) DelLog(id string) {
|
||||||
var log model.AppNotify
|
var log model.AppNotify
|
||||||
i.db.Where("custom_id = ?", id).Delete(&log)
|
i.db.Where("custom_id = ?", id).Delete(&log)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SendMeg() {
|
||||||
|
// for {
|
||||||
|
// mt, message, err := ws.ReadMessage()
|
||||||
|
// if err != nil {
|
||||||
|
// break
|
||||||
|
// }
|
||||||
|
// notify := model.NotifyMssage{}
|
||||||
|
// json2.Unmarshal(message, ¬ify)
|
||||||
|
// if notify.Type == "read" {
|
||||||
|
// service.MyService.Notify().MarkRead(notify.Data, types.NOTIFY_READ)
|
||||||
|
// }
|
||||||
|
// if notify.Type == "app" {
|
||||||
|
// go func(ws *websocket.Conn) {
|
||||||
|
|
||||||
|
for {
|
||||||
|
list := MyService.Notify().GetList(types.NOTIFY_APP)
|
||||||
|
json, _ := json2.Marshal(list)
|
||||||
|
|
||||||
|
if len(list) > 0 {
|
||||||
|
var temp []*websocket.Conn
|
||||||
|
for _, v := range WebSocketConns {
|
||||||
|
|
||||||
|
err := v.WriteMessage(1, json)
|
||||||
|
if err == nil {
|
||||||
|
temp = append(temp, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WebSocketConns = temp
|
||||||
|
for _, v := range list {
|
||||||
|
MyService.Notify().MarkRead(v.Id, types.NOTIFY_READ)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(WebSocketConns) == 0 {
|
||||||
|
SocketRun = false
|
||||||
|
}
|
||||||
|
time.Sleep(time.Second * 2)
|
||||||
|
}
|
||||||
|
// }(ws)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i notifyServer) SendText(m model.AppNotify) {
|
||||||
|
list := []model.AppNotify{}
|
||||||
|
list = append(list, m)
|
||||||
|
json, _ := json2.Marshal(list)
|
||||||
|
var temp []*websocket.Conn
|
||||||
|
for _, v := range WebSocketConns {
|
||||||
|
|
||||||
|
err := v.WriteMessage(1, json)
|
||||||
|
if err == nil {
|
||||||
|
temp = append(temp, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WebSocketConns = temp
|
||||||
|
|
||||||
|
if len(WebSocketConns) == 0 {
|
||||||
|
SocketRun = false
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func NewNotifyService(db *gorm.DB) NotifyServer {
|
func NewNotifyService(db *gorm.DB) NotifyServer {
|
||||||
return ¬ifyServer{db: db}
|
return ¬ifyServer{db: db}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,91 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
json2 "encoding/json"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
|
||||||
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
|
||||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
|
||||||
"github.com/tidwall/gjson"
|
|
||||||
)
|
|
||||||
|
|
||||||
type OasisService interface {
|
|
||||||
GetServerList(index, size, tp, categoryId, key string) ([]model.ServerAppList, int64)
|
|
||||||
GetServerCategoryList() []model.ServerCategoryList
|
|
||||||
GetTaskList(size int) []model2.TaskDBModel
|
|
||||||
}
|
|
||||||
|
|
||||||
type oasisService struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *oasisService) GetTaskList(size int) []model2.TaskDBModel {
|
|
||||||
head := make(map[string]string)
|
|
||||||
|
|
||||||
head["Authorization"] = GetToken()
|
|
||||||
|
|
||||||
listS := httper2.Get(config.ServerInfo.ServerApi+"/v1/task/list/"+strconv.Itoa(size), head)
|
|
||||||
|
|
||||||
list := []model2.TaskDBModel{}
|
|
||||||
json2.Unmarshal([]byte(gjson.Get(listS, "data").String()), &list)
|
|
||||||
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *oasisService) GetServerList(index, size, tp, categoryId, key string) ([]model.ServerAppList, int64) {
|
|
||||||
|
|
||||||
head := make(map[string]string)
|
|
||||||
|
|
||||||
head["Authorization"] = GetToken()
|
|
||||||
|
|
||||||
listS := httper2.Get(config.ServerInfo.ServerApi+"/v1/app/list?index="+index+"&size="+size+"&type="+tp+"&category_id="+categoryId+"&key="+key, head)
|
|
||||||
|
|
||||||
list := []model.ServerAppList{}
|
|
||||||
|
|
||||||
count := gjson.Get(listS, "data.count").Int()
|
|
||||||
json2.Unmarshal([]byte(gjson.Get(listS, "data.items").String()), &list)
|
|
||||||
|
|
||||||
return list, count
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *oasisService) GetServerCategoryList() []model.ServerCategoryList {
|
|
||||||
|
|
||||||
head := make(map[string]string)
|
|
||||||
head["Authorization"] = GetToken()
|
|
||||||
|
|
||||||
listS := httper2.Get(config.ServerInfo.ServerApi+"/v1/app/category", head)
|
|
||||||
|
|
||||||
list := []model.ServerCategoryList{}
|
|
||||||
|
|
||||||
json2.Unmarshal([]byte(gjson.Get(listS, "data").String()), &list)
|
|
||||||
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetToken() string {
|
|
||||||
t := make(chan string)
|
|
||||||
keyName := "casa_token"
|
|
||||||
|
|
||||||
var auth string
|
|
||||||
if result, ok := Cache.Get(keyName); ok {
|
|
||||||
auth, ok = result.(string)
|
|
||||||
if ok {
|
|
||||||
|
|
||||||
return auth
|
|
||||||
}
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
str := httper2.Get(config.ServerInfo.ServerApi+"/token", nil)
|
|
||||||
|
|
||||||
t <- gjson.Get(str, "data").String()
|
|
||||||
}()
|
|
||||||
auth = <-t
|
|
||||||
|
|
||||||
Cache.SetDefault(keyName, auth)
|
|
||||||
return auth
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewOasisService() OasisService {
|
|
||||||
return &oasisService{}
|
|
||||||
}
|
|
||||||
360
service/person.go
Normal file
360
service/person.go
Normal file
@@ -0,0 +1,360 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/quic_helper"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
|
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
||||||
|
port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
|
||||||
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/types"
|
||||||
|
"github.com/lucas-clemente/quic-go"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PersonService interface {
|
||||||
|
GetPersionInfo(token string) (m model.PersionModel, err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type personService struct {
|
||||||
|
db *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
var IpInfo model.PersionModel
|
||||||
|
var CancelList map[string]string
|
||||||
|
|
||||||
|
func PushIpInfo(token string) {
|
||||||
|
|
||||||
|
m := model.PersionModel{}
|
||||||
|
m.Ips = GetDeviceAllIP()
|
||||||
|
m.Token = token
|
||||||
|
b, _ := json.Marshal(m)
|
||||||
|
|
||||||
|
if reflect.DeepEqual(IpInfo, m) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
head := make(map[string]string)
|
||||||
|
infoS := httper2.Post(config.ServerInfo.Handshake+"/v1/update", b, "application/json", head)
|
||||||
|
fmt.Println(infoS)
|
||||||
|
}
|
||||||
|
func (p *personService) GetPersionInfo(token string) (m model.PersionModel, err error) {
|
||||||
|
infoS := httper2.Get(config.ServerInfo.Handshake+"/v1/ips/"+token, nil)
|
||||||
|
err = json.Unmarshal([]byte(infoS), &m)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPersonService(db *gorm.DB) PersonService {
|
||||||
|
return &personService{db: db}
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================================================================================================================================
|
||||||
|
|
||||||
|
var StreamList map[string]quic.Stream
|
||||||
|
var ServiceMessage chan model.MessageModel
|
||||||
|
|
||||||
|
func UDPService() {
|
||||||
|
port := 0
|
||||||
|
if len(config.ServerInfo.UDPPort) > 0 {
|
||||||
|
port, _ = strconv.Atoi(config.ServerInfo.UDPPort)
|
||||||
|
if port != 0 && !port2.IsPortAvailable(port, "udp") {
|
||||||
|
port = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
srcAddr := &net.UDPAddr{
|
||||||
|
IP: net.IPv4zero, Port: port}
|
||||||
|
var err error
|
||||||
|
UDPConn, err = net.ListenUDP("udp", srcAddr)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
listener, err := quic.Listen(UDPConn, quic_helper.GetGenerateTLSConfig(config.ServerInfo.Token), quic_helper.GetQUICConfig())
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
defer listener.Close()
|
||||||
|
ctx := context.Background()
|
||||||
|
acceptFailures := 0
|
||||||
|
const maxAcceptFailures = 10
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
fmt.Println(ctx.Err())
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
session, err := listener.Accept(ctx)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Listen (BEP/quic): Accepting connection:", err)
|
||||||
|
|
||||||
|
acceptFailures++
|
||||||
|
if acceptFailures > maxAcceptFailures {
|
||||||
|
// Return to restart the listener, because something
|
||||||
|
// seems permanently damaged.
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slightly increased delay for each failure.
|
||||||
|
time.Sleep(time.Duration(acceptFailures) * time.Second)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
acceptFailures = 0
|
||||||
|
|
||||||
|
streamCtx, cancel := context.WithTimeout(ctx, time.Second*10)
|
||||||
|
stream, err := session.AcceptStream(streamCtx)
|
||||||
|
cancel()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("failed to accept stream from %s: %v", session.RemoteAddr(), err)
|
||||||
|
_ = session.CloseWithError(1, err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// prefixByte := make([]byte, 4)
|
||||||
|
// c1, err := io.ReadFull(stream, prefixByte)
|
||||||
|
// fmt.Println(c1, err)
|
||||||
|
// prefixLength, err := strconv.Atoi(string(prefixByte))
|
||||||
|
// if err != nil {
|
||||||
|
// fmt.Println(err)
|
||||||
|
// }
|
||||||
|
// messageByte := make([]byte, prefixLength)
|
||||||
|
// t, err := io.ReadFull(stream, messageByte)
|
||||||
|
// fmt.Println(t, err)
|
||||||
|
// m := model.MessageModel{}
|
||||||
|
// err = json.Unmarshal(messageByte, &m)
|
||||||
|
// if err != nil {
|
||||||
|
// fmt.Println(err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
go ProcessingContent(stream)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//处理内容
|
||||||
|
func ProcessingContent(stream quic.Stream) {
|
||||||
|
for {
|
||||||
|
prefixByte := make([]byte, 6)
|
||||||
|
_, err := io.ReadFull(stream, prefixByte)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
prefixLength, err := strconv.Atoi(string(prefixByte))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
messageByte := make([]byte, prefixLength)
|
||||||
|
_, err = io.ReadFull(stream, messageByte)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
m := model.MessageModel{}
|
||||||
|
err = json.Unmarshal(messageByte, &m)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
if m.Type == types.PERSONHELLO {
|
||||||
|
//nothing
|
||||||
|
continue
|
||||||
|
} else if m.Type == types.PERSONDIRECTORY {
|
||||||
|
friend := model2.FriendModel{}
|
||||||
|
friend.Token = m.From
|
||||||
|
var list []model.Path
|
||||||
|
rFriend := MyService.Friend().GetFriendById(friend)
|
||||||
|
if !reflect.DeepEqual(rFriend, model2.FriendModel{Token: m.From}) && !rFriend.Block {
|
||||||
|
if m.Data.(string) == "" || m.Data.(string) == "/" {
|
||||||
|
for _, v := range config.FileSettingInfo.ShareDir {
|
||||||
|
//tempList := MyService.ZiMa().GetDirPath(v)
|
||||||
|
temp := MyService.ZiMa().GetDirPathOne(v)
|
||||||
|
list = append(list, temp)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
list = MyService.ZiMa().GetDirPath(m.Data.(string))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
list = []model.Path{}
|
||||||
|
}
|
||||||
|
m.To = m.From
|
||||||
|
m.Data = list
|
||||||
|
m.From = config.ServerInfo.Token
|
||||||
|
SendData(stream, m)
|
||||||
|
break
|
||||||
|
} else if m.Type == types.PERSONDOWNLOAD {
|
||||||
|
|
||||||
|
SendFileData(stream, m.Data.(string), m.From, m.UUId)
|
||||||
|
break
|
||||||
|
} else if m.Type == types.PERSONADDFRIEND {
|
||||||
|
fmt.Println("有用户来请求加好友", m)
|
||||||
|
friend := model2.FriendModel{}
|
||||||
|
dataModelByte, _ := json.Marshal(m.Data)
|
||||||
|
err := json.Unmarshal(dataModelByte, &friend)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
go MyService.Friend().UpdateOrCreate(friend)
|
||||||
|
mi := model2.FriendModel{}
|
||||||
|
mi.Avatar = config.UserInfo.Avatar
|
||||||
|
mi.Profile = config.UserInfo.Description
|
||||||
|
mi.NickName = config.UserInfo.NickName
|
||||||
|
m.To = m.From
|
||||||
|
m.Data = mi
|
||||||
|
m.Type = types.PERSONADDFRIEND
|
||||||
|
m.From = config.ServerInfo.Token
|
||||||
|
|
||||||
|
SendData(stream, m)
|
||||||
|
break
|
||||||
|
} else if m.Type == types.PERSONCONNECTION {
|
||||||
|
if len(m.Data.(string)) > 0 {
|
||||||
|
UDPAddressMap[m.From] = m.Data.(string)
|
||||||
|
} else {
|
||||||
|
delete(UDPAddressMap, m.From)
|
||||||
|
}
|
||||||
|
// mi := model2.FriendModel{}
|
||||||
|
// mi.Avatar = config.UserInfo.Avatar
|
||||||
|
// mi.Profile = config.UserInfo.Description
|
||||||
|
// mi.NickName = config.UserInfo.NickName
|
||||||
|
// mi.Token = config.ServerInfo.Token
|
||||||
|
|
||||||
|
user := MyService.Casa().GetUserInfoByShareId(m.From)
|
||||||
|
|
||||||
|
friend := model2.FriendModel{}
|
||||||
|
friend.Token = m.From
|
||||||
|
friend.Avatar = user.Avatar
|
||||||
|
friend.Block = false
|
||||||
|
friend.NickName = user.NickName
|
||||||
|
friend.Profile = user.Avatar
|
||||||
|
friend.Version = user.Version
|
||||||
|
MyService.Friend().AddFriend(friend)
|
||||||
|
|
||||||
|
msg := model.MessageModel{}
|
||||||
|
msg.Type = types.PERSONHELLO
|
||||||
|
msg.Data = ""
|
||||||
|
msg.To = m.From
|
||||||
|
msg.From = config.ServerInfo.Token
|
||||||
|
msg.UUId = m.UUId
|
||||||
|
Dial(msg, false)
|
||||||
|
|
||||||
|
break
|
||||||
|
} else if m.Type == types.PERSONCANCEL {
|
||||||
|
CancelList[m.UUId] = "cancel"
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
//不应有不做返回的数据
|
||||||
|
//ServiceMessage <- m
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stream.Close()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//文件分片发送
|
||||||
|
func SendFileData(stream quic.Stream, filePath, to, uuid string) error {
|
||||||
|
summary := model.FileSummaryModel{}
|
||||||
|
|
||||||
|
msg := model.MessageModel{}
|
||||||
|
msg.Type = types.PERSONSUMMARY
|
||||||
|
msg.From = config.ServerInfo.Token
|
||||||
|
msg.To = to
|
||||||
|
msg.UUId = uuid
|
||||||
|
|
||||||
|
fStat, err := os.Stat(filePath)
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
summary.Message = err.Error()
|
||||||
|
|
||||||
|
msg.Data = summary
|
||||||
|
|
||||||
|
summaryByte, _ := json.Marshal(msg)
|
||||||
|
summaryPrefixLength := file.PrefixLength(len(summaryByte))
|
||||||
|
summaryData := append(summaryPrefixLength, summaryByte...)
|
||||||
|
stream.Write(summaryData)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
blockSize, length := file.GetBlockInfo(fStat.Size())
|
||||||
|
|
||||||
|
f, err := os.Open(filePath)
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
summary.Message = err.Error()
|
||||||
|
msg.Data = summary
|
||||||
|
|
||||||
|
summaryByte, _ := json.Marshal(msg)
|
||||||
|
summaryPrefixLength := file.PrefixLength(len(summaryByte))
|
||||||
|
summaryData := append(summaryPrefixLength, summaryByte...)
|
||||||
|
stream.Write(summaryData)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//send file summary first
|
||||||
|
summary.BlockSize = blockSize
|
||||||
|
summary.Hash = file.GetHashByPath(filePath)
|
||||||
|
summary.Length = length
|
||||||
|
summary.Name = fStat.Name()
|
||||||
|
summary.Size = fStat.Size()
|
||||||
|
|
||||||
|
msg.Data = summary
|
||||||
|
|
||||||
|
summaryByte, _ := json.Marshal(msg)
|
||||||
|
summaryPrefixLength := file.PrefixLength(len(summaryByte))
|
||||||
|
summaryData := append(summaryPrefixLength, summaryByte...)
|
||||||
|
stream.Write(summaryData)
|
||||||
|
|
||||||
|
bufferedReader := bufio.NewReader(f)
|
||||||
|
buf := make([]byte, blockSize)
|
||||||
|
|
||||||
|
defer stream.Close()
|
||||||
|
|
||||||
|
for i := 0; i < length; i++ {
|
||||||
|
|
||||||
|
tran := model.TranFileModel{}
|
||||||
|
|
||||||
|
n, err := bufferedReader.Read(buf)
|
||||||
|
|
||||||
|
if err == io.EOF {
|
||||||
|
fmt.Println("读取完毕", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tran.Hash = file.GetHashByContent(buf[:n])
|
||||||
|
tran.Index = i
|
||||||
|
tran.Length = length
|
||||||
|
|
||||||
|
fileMsg := model.MessageModel{}
|
||||||
|
fileMsg.Type = types.PERSONDOWNLOAD
|
||||||
|
fileMsg.Data = tran
|
||||||
|
fileMsg.From = config.ServerInfo.Token
|
||||||
|
fileMsg.To = to
|
||||||
|
fileMsg.UUId = uuid
|
||||||
|
b, _ := json.Marshal(fileMsg)
|
||||||
|
prefixLength := file.PrefixLength(len(b))
|
||||||
|
dataLength := file.DataLength(len(buf[:n]))
|
||||||
|
data := append(append(append(prefixLength, b...), dataLength...), buf[:n]...)
|
||||||
|
if _, ok := CancelList[uuid]; ok {
|
||||||
|
delete(CancelList, uuid)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
stream.Write(data)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
"github.com/patrickmn/go-cache"
|
"github.com/patrickmn/go-cache"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
@@ -10,15 +11,18 @@ var Cache *cache.Cache
|
|||||||
|
|
||||||
var MyService Repository
|
var MyService Repository
|
||||||
|
|
||||||
|
var WebSocketConns []*websocket.Conn
|
||||||
|
|
||||||
|
var SocketRun bool
|
||||||
|
|
||||||
type Repository interface {
|
type Repository interface {
|
||||||
App() AppService
|
App() AppService
|
||||||
DDNS() DDNSService
|
DDNS() DDNSService
|
||||||
User() UserService
|
User() UserService
|
||||||
Docker() DockerService
|
Docker() DockerService
|
||||||
//Redis() RedisService
|
//Redis() RedisService
|
||||||
ZeroTier() ZeroTierService
|
|
||||||
ZiMa() ZiMaService
|
ZiMa() ZiMaService
|
||||||
OAPI() OasisService
|
Casa() CasaService
|
||||||
Disk() DiskService
|
Disk() DiskService
|
||||||
Notify() NotifyServer
|
Notify() NotifyServer
|
||||||
ShareDirectory() ShareDirService
|
ShareDirectory() ShareDirService
|
||||||
@@ -27,19 +31,22 @@ type Repository interface {
|
|||||||
System() SystemService
|
System() SystemService
|
||||||
Shortcuts() ShortcutsService
|
Shortcuts() ShortcutsService
|
||||||
Search() SearchService
|
Search() SearchService
|
||||||
|
Person() PersonService
|
||||||
|
Friend() FriendService
|
||||||
|
Download() DownloadService
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewService(db *gorm.DB, log loger2.OLog) Repository {
|
func NewService(db *gorm.DB, log loger2.OLog) Repository {
|
||||||
|
|
||||||
return &store{
|
return &store{
|
||||||
app: NewAppService(db, log),
|
app: NewAppService(db, log),
|
||||||
ddns: NewDDNSService(db, log),
|
ddns: NewDDNSService(db, log),
|
||||||
user: NewUserService(),
|
user: NewUserService(),
|
||||||
docker: NewDcokerService(log),
|
docker: NewDockerService(log),
|
||||||
//redis: NewRedisService(rp),
|
//redis: NewRedisService(rp),
|
||||||
zerotier: NewZeroTierService(),
|
|
||||||
zima: NewZiMaService(),
|
zima: NewZiMaService(),
|
||||||
oapi: NewOasisService(),
|
casa: NewCasaService(),
|
||||||
disk: NewDiskService(log),
|
disk: NewDiskService(log, db),
|
||||||
notify: NewNotifyService(db),
|
notify: NewNotifyService(db),
|
||||||
shareDirectory: NewShareDirService(db, log),
|
shareDirectory: NewShareDirService(db, log),
|
||||||
task: NewTaskService(db, log),
|
task: NewTaskService(db, log),
|
||||||
@@ -47,6 +54,9 @@ func NewService(db *gorm.DB, log loger2.OLog) Repository {
|
|||||||
system: NewSystemService(log),
|
system: NewSystemService(log),
|
||||||
shortcuts: NewShortcutsService(db),
|
shortcuts: NewShortcutsService(db),
|
||||||
search: NewSearchService(),
|
search: NewSearchService(),
|
||||||
|
person: NewPersonService(db),
|
||||||
|
friend: NewFriendService(db),
|
||||||
|
download: NewDownloadService(db),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,9 +66,8 @@ type store struct {
|
|||||||
ddns DDNSService
|
ddns DDNSService
|
||||||
user UserService
|
user UserService
|
||||||
docker DockerService
|
docker DockerService
|
||||||
zerotier ZeroTierService
|
|
||||||
zima ZiMaService
|
zima ZiMaService
|
||||||
oapi OasisService
|
casa CasaService
|
||||||
disk DiskService
|
disk DiskService
|
||||||
notify NotifyServer
|
notify NotifyServer
|
||||||
shareDirectory ShareDirService
|
shareDirectory ShareDirService
|
||||||
@@ -67,14 +76,26 @@ type store struct {
|
|||||||
system SystemService
|
system SystemService
|
||||||
shortcuts ShortcutsService
|
shortcuts ShortcutsService
|
||||||
search SearchService
|
search SearchService
|
||||||
|
person PersonService
|
||||||
|
friend FriendService
|
||||||
|
download DownloadService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *store) Download() DownloadService {
|
||||||
|
return c.download
|
||||||
|
}
|
||||||
|
func (c *store) Friend() FriendService {
|
||||||
|
return c.friend
|
||||||
|
}
|
||||||
func (c *store) Rely() RelyService {
|
func (c *store) Rely() RelyService {
|
||||||
return c.rely
|
return c.rely
|
||||||
}
|
}
|
||||||
func (c *store) Shortcuts() ShortcutsService {
|
func (c *store) Shortcuts() ShortcutsService {
|
||||||
return c.shortcuts
|
return c.shortcuts
|
||||||
}
|
}
|
||||||
|
func (c *store) Person() PersonService {
|
||||||
|
return c.person
|
||||||
|
}
|
||||||
func (c *store) System() SystemService {
|
func (c *store) System() SystemService {
|
||||||
return c.system
|
return c.system
|
||||||
}
|
}
|
||||||
@@ -99,14 +120,11 @@ func (c *store) Docker() DockerService {
|
|||||||
return c.docker
|
return c.docker
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *store) ZeroTier() ZeroTierService {
|
|
||||||
return c.zerotier
|
|
||||||
}
|
|
||||||
func (c *store) ZiMa() ZiMaService {
|
func (c *store) ZiMa() ZiMaService {
|
||||||
return c.zima
|
return c.zima
|
||||||
}
|
}
|
||||||
func (c *store) OAPI() OasisService {
|
func (c *store) Casa() CasaService {
|
||||||
return c.oapi
|
return c.casa
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *store) Disk() DiskService {
|
func (c *store) Disk() DiskService {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
@@ -14,6 +15,11 @@ type SystemService interface {
|
|||||||
UpdateSystemVersion(version string)
|
UpdateSystemVersion(version string)
|
||||||
GetSystemConfigDebug() []string
|
GetSystemConfigDebug() []string
|
||||||
GetCasaOSLogs(lineNumber int) string
|
GetCasaOSLogs(lineNumber int) string
|
||||||
|
UpdateAssist()
|
||||||
|
UpSystemPort(port string)
|
||||||
|
GetTimeZone() string
|
||||||
|
UpdateUSBAutoMount(state string)
|
||||||
|
ExecUSBAutoMountShell(state string)
|
||||||
}
|
}
|
||||||
type systemService struct {
|
type systemService struct {
|
||||||
log loger.OLog
|
log loger.OLog
|
||||||
@@ -25,6 +31,23 @@ func (s *systemService) UpdateSystemVersion(version string) {
|
|||||||
s.log.Error(command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/tools.sh ;update " + version))
|
s.log.Error(command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/tools.sh ;update " + version))
|
||||||
//s.log.Error(command2.ExecResultStr(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version))
|
//s.log.Error(command2.ExecResultStr(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version))
|
||||||
}
|
}
|
||||||
|
func (s *systemService) UpdateAssist() {
|
||||||
|
s.log.Error(command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/assist.sh"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *systemService) GetTimeZone() string {
|
||||||
|
return command2.ExecResultStr("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetTimeZone")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *systemService) ExecUSBAutoMountShell(state string) {
|
||||||
|
if state == "False" {
|
||||||
|
command2.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;USB_Remove_File")
|
||||||
|
} else {
|
||||||
|
command2.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;USB_Move_File")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (s *systemService) GetSystemConfigDebug() []string {
|
func (s *systemService) GetSystemConfigDebug() []string {
|
||||||
return command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetSysInfo")
|
return command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetSysInfo")
|
||||||
}
|
}
|
||||||
@@ -39,7 +62,18 @@ func (s *systemService) UpSystemConfig(str string, widget string) {
|
|||||||
}
|
}
|
||||||
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||||
}
|
}
|
||||||
|
func (s *systemService) UpdateUSBAutoMount(state string) {
|
||||||
|
config.ServerInfo.USBAutoMount = state
|
||||||
|
config.Cfg.Section("system").Key("USBAutoMount").SetValue(state)
|
||||||
|
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||||
|
}
|
||||||
|
func (s *systemService) UpSystemPort(port string) {
|
||||||
|
if len(port) > 0 && port != config.ServerInfo.HttpPort {
|
||||||
|
config.Cfg.Section("server").Key("HttpPort").SetValue(port)
|
||||||
|
config.ServerInfo.HttpPort = port
|
||||||
|
}
|
||||||
|
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||||
|
}
|
||||||
func (s *systemService) GetCasaOSLogs(lineNumber int) string {
|
func (s *systemService) GetCasaOSLogs(lineNumber int) string {
|
||||||
file, err := os.Open(s.log.Path())
|
file, err := os.Open(s.log.Path())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -54,6 +88,21 @@ func (s *systemService) GetCasaOSLogs(lineNumber int) string {
|
|||||||
return string(content)
|
return string(content)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetDeviceAllIP() []string {
|
||||||
|
var address []string
|
||||||
|
addrs, err := net.InterfaceAddrs()
|
||||||
|
if err != nil {
|
||||||
|
return address
|
||||||
|
}
|
||||||
|
for _, a := range addrs {
|
||||||
|
if ipNet, ok := a.(*net.IPNet); ok && !ipNet.IP.IsLoopback() {
|
||||||
|
if ipNet.IP.To16() != nil {
|
||||||
|
address = append(address, ipNet.IP.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return address
|
||||||
|
}
|
||||||
func NewSystemService(log loger.OLog) SystemService {
|
func NewSystemService(log loger.OLog) SystemService {
|
||||||
return &systemService{log: log}
|
return &systemService{log: log}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
json2 "encoding/json"
|
json2 "encoding/json"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
||||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||||
@@ -9,7 +11,6 @@ import (
|
|||||||
"github.com/IceWhaleTech/CasaOS/types"
|
"github.com/IceWhaleTech/CasaOS/types"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type TaskService interface {
|
type TaskService interface {
|
||||||
|
|||||||
370
service/udpconn.go
Normal file
370
service/udpconn.go
Normal file
@@ -0,0 +1,370 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/md5"
|
||||||
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
path2 "path"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/quic_helper"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/types"
|
||||||
|
"github.com/lucas-clemente/quic-go"
|
||||||
|
uuid "github.com/satori/go.uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
var UDPConn *net.UDPConn
|
||||||
|
var PeopleMap map[string]quic.Stream
|
||||||
|
var Message chan model.MessageModel
|
||||||
|
var UDPAddressMap map[string]string
|
||||||
|
|
||||||
|
func Dial(msg model.MessageModel, server bool) (m model.MessageModel, err error) {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
Message = make(chan model.MessageModel)
|
||||||
|
_, port, err := net.SplitHostPort(UDPConn.LocalAddr().String())
|
||||||
|
if config.ServerInfo.UDPPort != port {
|
||||||
|
config.ServerInfo.UDPPort = port
|
||||||
|
config.Cfg.Section("server").Key("UDPPort").SetValue(port)
|
||||||
|
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||||
|
}
|
||||||
|
p, err := strconv.Atoi(port)
|
||||||
|
srcAddr := &net.UDPAddr{
|
||||||
|
IP: net.IPv4zero, Port: p} //注意端口必须固定
|
||||||
|
addr := UDPAddressMap[msg.To]
|
||||||
|
ticket := msg.To
|
||||||
|
if server {
|
||||||
|
addr = config.ServerInfo.Handshake + ":9527"
|
||||||
|
ticket = "bench"
|
||||||
|
}
|
||||||
|
dstAddr, err := net.ResolveUDPAddr("udp", addr)
|
||||||
|
|
||||||
|
//DialTCP在网络协议net上连接本地地址laddr和远端地址raddr。net必须是"udp"、"udp4"、"udp6";如果laddr不是nil,将使用它作为本地地址,否则自动选择一个本地地址。
|
||||||
|
//(conn)UDPConn代表一个UDP网络连接,实现了Conn和PacketConn接口
|
||||||
|
|
||||||
|
session, err := quic.DialContext(ctx, UDPConn, dstAddr, srcAddr.String(), quic_helper.GetClientTlsConfig(ticket), quic_helper.GetQUICConfig())
|
||||||
|
if err != nil {
|
||||||
|
if msg.Type == types.PERSONDOWNLOAD {
|
||||||
|
task := MyService.Download().GetDownloadById(msg.UUId)
|
||||||
|
task.Error = err.Error()
|
||||||
|
task.State = types.DOWNLOADERROR
|
||||||
|
MyService.Download().SetDownloadError(task)
|
||||||
|
}
|
||||||
|
if config.SystemConfigInfo.Analyse != "False" {
|
||||||
|
go MyService.Casa().PushConnectionStatus(msg.UUId, err.Error(), msg.From, msg.To, msg.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
return m, err
|
||||||
|
}
|
||||||
|
|
||||||
|
stream, err := session.OpenStreamSync(ctx)
|
||||||
|
if err != nil {
|
||||||
|
if msg.Type == types.PERSONDOWNLOAD {
|
||||||
|
task := MyService.Download().GetDownloadById(msg.UUId)
|
||||||
|
task.Error = err.Error()
|
||||||
|
task.State = types.DOWNLOADERROR
|
||||||
|
MyService.Download().SetDownloadError(task)
|
||||||
|
}
|
||||||
|
if config.SystemConfigInfo.Analyse != "False" {
|
||||||
|
go MyService.Casa().PushConnectionStatus(msg.UUId, err.Error(), msg.From, msg.To, msg.Type)
|
||||||
|
}
|
||||||
|
session.CloseWithError(1, err.Error())
|
||||||
|
return m, err
|
||||||
|
}
|
||||||
|
|
||||||
|
SayHello(stream, msg.To)
|
||||||
|
|
||||||
|
SendData(stream, msg)
|
||||||
|
|
||||||
|
go ReadContent(stream)
|
||||||
|
result := <-Message
|
||||||
|
stream.Close()
|
||||||
|
if config.SystemConfigInfo.Analyse != "False" {
|
||||||
|
go MyService.Casa().PushConnectionStatus(msg.UUId, "OK", msg.From, msg.To, msg.Type)
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SayHello(stream quic.Stream, to string) {
|
||||||
|
msg := model.MessageModel{}
|
||||||
|
msg.Type = types.PERSONHELLO
|
||||||
|
msg.Data = "hello"
|
||||||
|
msg.To = to
|
||||||
|
msg.From = config.ServerInfo.Token
|
||||||
|
msg.UUId = uuid.NewV4().String()
|
||||||
|
SendData(stream, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
//发送数据
|
||||||
|
func SendData(stream quic.Stream, m model.MessageModel) {
|
||||||
|
b, _ := json.Marshal(m)
|
||||||
|
prefixLength := file.PrefixLength(len(b))
|
||||||
|
data := append(prefixLength, b...)
|
||||||
|
stream.Write(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
//读取数据
|
||||||
|
func ReadContent(stream quic.Stream) {
|
||||||
|
for {
|
||||||
|
prefixByte := make([]byte, 6)
|
||||||
|
_, err := io.ReadFull(stream, prefixByte)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
time.Sleep(time.Second * 1)
|
||||||
|
for k, v := range CancelList {
|
||||||
|
tempPath := config.AppInfo.RootPath + "/temp" + "/" + v
|
||||||
|
fmt.Println(file.RMDir(tempPath))
|
||||||
|
delete(CancelList, k)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
prefixLength, err := strconv.Atoi(string(prefixByte))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
messageByte := make([]byte, prefixLength)
|
||||||
|
_, err = io.ReadFull(stream, messageByte)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
m := model.MessageModel{}
|
||||||
|
err = json.Unmarshal(messageByte, &m)
|
||||||
|
fmt.Println("客户端", m)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.Type == types.PERSONDOWNLOAD {
|
||||||
|
|
||||||
|
dataModelByte, _ := json.Marshal(m.Data)
|
||||||
|
dataModel := model.TranFileModel{}
|
||||||
|
err := json.Unmarshal(dataModelByte, &dataModel)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
dataLengthByte := make([]byte, 8)
|
||||||
|
_, err = io.ReadFull(stream, dataLengthByte)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
dataLength, err := strconv.Atoi(string(dataLengthByte))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
dataByte := make([]byte, dataLength)
|
||||||
|
_, err = io.ReadFull(stream, dataByte)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
sum := md5.Sum(dataByte)
|
||||||
|
hash := hex.EncodeToString(sum[:])
|
||||||
|
if dataModel.Hash != hash {
|
||||||
|
fmt.Println("hash不匹配", hash, dataModel.Hash)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
tempPath := config.AppInfo.RootPath + "/temp" + "/" + m.UUId
|
||||||
|
file.IsNotExistMkDir(tempPath)
|
||||||
|
filepath := tempPath + "/" + strconv.Itoa(dataModel.Index)
|
||||||
|
_, err = os.Stat(filepath)
|
||||||
|
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
err = ioutil.WriteFile(filepath, dataByte, 0644)
|
||||||
|
task := model2.PersonDownloadDBModel{}
|
||||||
|
task.UUID = m.UUId
|
||||||
|
if err != nil {
|
||||||
|
task.Error = err.Error()
|
||||||
|
task.State = types.DOWNLOADERROR
|
||||||
|
MyService.Download().SetDownloadError(task)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if file.GetHashByPath(filepath) != dataModel.Hash {
|
||||||
|
os.Remove(filepath)
|
||||||
|
err = ioutil.WriteFile(filepath, dataByte, 0644)
|
||||||
|
task := model2.PersonDownloadDBModel{}
|
||||||
|
task.UUID = m.UUId
|
||||||
|
if err != nil {
|
||||||
|
task.Error = err.Error()
|
||||||
|
task.State = types.DOWNLOADERROR
|
||||||
|
MyService.Download().SetDownloadError(task)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
files, err := ioutil.ReadDir(tempPath)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if len(files) >= dataModel.Length {
|
||||||
|
summary := MyService.Download().GetDownloadById(m.UUId)
|
||||||
|
summary.State = types.DOWNLOADFINISH
|
||||||
|
MyService.Download().EditDownloadState(summary)
|
||||||
|
fullPath := file.GetNoDuplicateFileName(path2.Join(summary.LocalPath, summary.Name))
|
||||||
|
file.SpliceFiles(tempPath, fullPath, dataModel.Length, 0)
|
||||||
|
if file.GetHashByPath(fullPath) == summary.Hash {
|
||||||
|
file.RMDir(tempPath)
|
||||||
|
summary.State = types.DOWNLOADFINISHED
|
||||||
|
MyService.Download().EditDownloadState(summary)
|
||||||
|
} else {
|
||||||
|
os.Remove(config.FileSettingInfo.DownloadDir + "/" + summary.Name)
|
||||||
|
|
||||||
|
summary.State = types.DOWNLOADERROR
|
||||||
|
summary.Error = "hash mismatch"
|
||||||
|
MyService.Download().SetDownloadError(summary)
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} else if m.Type == types.PERSONSUMMARY {
|
||||||
|
|
||||||
|
dataModel := model.FileSummaryModel{}
|
||||||
|
dataModelByte, _ := json.Marshal(m.Data)
|
||||||
|
err := json.Unmarshal(dataModelByte, &dataModel)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
task := MyService.Download().GetDownloadById(m.UUId)
|
||||||
|
fullPath := path2.Join(task.LocalPath, task.Name)
|
||||||
|
task.State = types.DOWNLOADING
|
||||||
|
if len(dataModel.Message) > 0 {
|
||||||
|
task.State = types.DOWNLOADERROR
|
||||||
|
task.Error = dataModel.Message
|
||||||
|
}
|
||||||
|
if file.Exists(fullPath) && file.GetHashByPath(fullPath) == dataModel.Hash {
|
||||||
|
task.State = types.DOWNLOADFINISHED
|
||||||
|
go func(from, uuid string) {
|
||||||
|
m := model.MessageModel{}
|
||||||
|
m.Data = ""
|
||||||
|
m.From = config.ServerInfo.Token
|
||||||
|
m.To = from
|
||||||
|
m.Type = types.PERSONCANCEL
|
||||||
|
m.UUId = uuid
|
||||||
|
CancelList[uuid] = uuid
|
||||||
|
Dial(m, false)
|
||||||
|
}(task.From, task.UUID)
|
||||||
|
|
||||||
|
}
|
||||||
|
task.UUID = m.UUId
|
||||||
|
task.Name = dataModel.Name
|
||||||
|
task.Length = dataModel.Length
|
||||||
|
task.Size = dataModel.Size
|
||||||
|
task.BlockSize = dataModel.BlockSize
|
||||||
|
task.Hash = dataModel.Hash
|
||||||
|
task.Type = 0
|
||||||
|
task.From = m.From
|
||||||
|
MyService.Download().SaveDownload(task)
|
||||||
|
|
||||||
|
} else if m.Type == types.PERSONCONNECTION {
|
||||||
|
if len(m.Data.(string)) > 0 {
|
||||||
|
UDPAddressMap[m.From] = m.Data.(string)
|
||||||
|
} else {
|
||||||
|
delete(UDPAddressMap, m.From)
|
||||||
|
}
|
||||||
|
// mi := model2.FriendModel{}
|
||||||
|
// mi.Avatar = config.UserInfo.Avatar
|
||||||
|
// mi.Profile = config.UserInfo.Description
|
||||||
|
// mi.NickName = config.UserInfo.NickName
|
||||||
|
// mi.Token = config.ServerInfo.Token
|
||||||
|
msg := model.MessageModel{}
|
||||||
|
msg.Type = types.PERSONHELLO
|
||||||
|
msg.Data = ""
|
||||||
|
msg.To = m.From
|
||||||
|
msg.From = config.ServerInfo.Token
|
||||||
|
msg.UUId = m.UUId
|
||||||
|
go Dial(msg, false)
|
||||||
|
Message <- m
|
||||||
|
break
|
||||||
|
} else if m.Type == "get_ip" {
|
||||||
|
notify := model2.AppNotify{}
|
||||||
|
notify.CustomId = m.From
|
||||||
|
if len(m.Data.(string)) == 0 {
|
||||||
|
if _, ok := UDPAddressMap[m.From]; ok {
|
||||||
|
notify.Type = types.NOTIFY_TYPE_PERSION_FIRNED_LEAVE
|
||||||
|
go MyService.Notify().SendText(notify)
|
||||||
|
}
|
||||||
|
delete(UDPAddressMap, m.From)
|
||||||
|
Message <- m
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if _, ok := UDPAddressMap[m.From]; !ok {
|
||||||
|
notify.Type = types.NOTIFY_TYPE_PERSION_FIRNED_LIVE
|
||||||
|
go MyService.Notify().SendText(notify)
|
||||||
|
}
|
||||||
|
UDPAddressMap[m.From] = m.Data.(string)
|
||||||
|
Message <- m
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
Message <- m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Message <- model.MessageModel{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SendIPToServer() {
|
||||||
|
msg := model.MessageModel{}
|
||||||
|
msg.Type = types.PERSONHELLO
|
||||||
|
msg.Data = ""
|
||||||
|
msg.From = config.ServerInfo.Token
|
||||||
|
msg.To = config.ServerInfo.Token
|
||||||
|
msg.UUId = uuid.NewV4().String()
|
||||||
|
|
||||||
|
Dial(msg, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoopFriend() {
|
||||||
|
list := MyService.Friend().GetFriendList()
|
||||||
|
for i := 0; i < len(list); i++ {
|
||||||
|
msg := model.MessageModel{}
|
||||||
|
msg.Type = "get_ip"
|
||||||
|
msg.Data = ""
|
||||||
|
msg.From = config.ServerInfo.Token
|
||||||
|
msg.To = list[i].Token
|
||||||
|
msg.UUId = uuid.NewV4().String()
|
||||||
|
|
||||||
|
Dial(msg, true)
|
||||||
|
|
||||||
|
msg.Type = types.PERSONHELLO
|
||||||
|
msg.Data = ""
|
||||||
|
msg.From = config.ServerInfo.Token
|
||||||
|
msg.To = list[i].Token
|
||||||
|
msg.UUId = uuid.NewV4().String()
|
||||||
|
if _, ok := UDPAddressMap[list[i].Token]; ok {
|
||||||
|
go Dial(msg, false)
|
||||||
|
}
|
||||||
|
go func(shareId string) {
|
||||||
|
user := MyService.Casa().GetUserInfoByShareId(shareId)
|
||||||
|
m := model2.FriendModel{}
|
||||||
|
m.Token = shareId
|
||||||
|
friend := MyService.Friend().GetFriendById(m)
|
||||||
|
if friend.Version != user.Version {
|
||||||
|
friend.Avatar = user.Avatar
|
||||||
|
friend.NickName = user.NickName
|
||||||
|
friend.Profile = user.Desc
|
||||||
|
friend.Version = user.Version
|
||||||
|
MyService.Friend().UpdateOrCreate(friend)
|
||||||
|
}
|
||||||
|
}(list[i].Token)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type UserService interface {
|
type UserService interface {
|
||||||
SetUser(username, pwd, token, email, desc string) error
|
SetUser(username, pwd, token, email, desc, nickName string) error
|
||||||
UpLoadFile(file multipart.File, name string) error
|
UpLoadFile(file multipart.File, name string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ type user struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//设置用户名密码
|
//设置用户名密码
|
||||||
func (c *user) SetUser(username, pwd, token, email, desc string) error {
|
func (c *user) SetUser(username, pwd, token, email, desc, nickName string) error {
|
||||||
if len(username) > 0 {
|
if len(username) > 0 {
|
||||||
config.Cfg.Section("user").Key("UserName").SetValue(username)
|
config.Cfg.Section("user").Key("UserName").SetValue(username)
|
||||||
config.UserInfo.UserName = username
|
config.UserInfo.UserName = username
|
||||||
@@ -28,10 +28,6 @@ func (c *user) SetUser(username, pwd, token, email, desc string) error {
|
|||||||
config.Cfg.Section("user").Key("PWD").SetValue(pwd)
|
config.Cfg.Section("user").Key("PWD").SetValue(pwd)
|
||||||
config.UserInfo.PWD = pwd
|
config.UserInfo.PWD = pwd
|
||||||
}
|
}
|
||||||
if len(token) > 0 {
|
|
||||||
config.Cfg.Section("user").Key("Token").SetValue(token)
|
|
||||||
config.UserInfo.Token = token
|
|
||||||
}
|
|
||||||
if len(email) > 0 {
|
if len(email) > 0 {
|
||||||
config.Cfg.Section("user").Key("Email").SetValue(email)
|
config.Cfg.Section("user").Key("Email").SetValue(email)
|
||||||
config.UserInfo.Email = email
|
config.UserInfo.Email = email
|
||||||
@@ -40,6 +36,10 @@ func (c *user) SetUser(username, pwd, token, email, desc string) error {
|
|||||||
config.Cfg.Section("user").Key("Description").SetValue(desc)
|
config.Cfg.Section("user").Key("Description").SetValue(desc)
|
||||||
config.UserInfo.Description = desc
|
config.UserInfo.Description = desc
|
||||||
}
|
}
|
||||||
|
if len(nickName) > 0 {
|
||||||
|
config.Cfg.Section("user").Key("NickName").SetValue(nickName)
|
||||||
|
config.UserInfo.NickName = nickName
|
||||||
|
}
|
||||||
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,343 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
|
||||||
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
|
||||||
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/zerotier"
|
|
||||||
"github.com/PuerkitoBio/goquery"
|
|
||||||
"github.com/tidwall/gjson"
|
|
||||||
"io/ioutil"
|
|
||||||
"math/rand"
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ZeroTierService interface {
|
|
||||||
GetToken(username, pwd string) string
|
|
||||||
ZeroTierRegister(email, lastName, firstName, password string) string
|
|
||||||
ZeroTierNetworkList(token string) (interface{}, []string)
|
|
||||||
ZeroTierJoinNetwork(networkId string)
|
|
||||||
ZeroTierLeaveNetwork(networkId string)
|
|
||||||
ZeroTierGetInfo(token, id string) (interface{}, []string)
|
|
||||||
ZeroTierGetStatus(token string) interface{}
|
|
||||||
EditNetwork(token string, data string, id string) interface{}
|
|
||||||
CreateNetwork(token string) interface{}
|
|
||||||
MemberList(token string, id string) interface{}
|
|
||||||
EditNetworkMember(token string, data string, id, mId string) interface{}
|
|
||||||
DeleteMember(token string, id, mId string) interface{}
|
|
||||||
DeleteNetwork(token, id string) interface{}
|
|
||||||
GetJoinNetworks() string
|
|
||||||
}
|
|
||||||
type zerotierstruct struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
var client http.Client
|
|
||||||
|
|
||||||
func (c *zerotierstruct) ZeroTierJoinNetwork(networkId string) {
|
|
||||||
command2.OnlyExec(`zerotier-cli join ` + networkId)
|
|
||||||
}
|
|
||||||
func (c *zerotierstruct) ZeroTierLeaveNetwork(networkId string) {
|
|
||||||
command2.OnlyExec(`zerotier-cli leave ` + networkId)
|
|
||||||
}
|
|
||||||
|
|
||||||
//登录并获取token
|
|
||||||
func (c *zerotierstruct) GetToken(username, pwd string) string {
|
|
||||||
if len(config.ZeroTierInfo.Token) > 0 {
|
|
||||||
return config.ZeroTierInfo.Token
|
|
||||||
} else {
|
|
||||||
return LoginGetToken(username, pwd)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *zerotierstruct) ZeroTierRegister(email, lastName, firstName, password string) string {
|
|
||||||
|
|
||||||
url := "https://accounts.zerotier.com/auth/realms/zerotier/protocol/openid-connect/registrations?client_id=zt-central&redirect_uri=https%3A%2F%2Fmy.zerotier.com%2Fapi%2F_auth%2Foidc%2Fcallback&response_type=code&scope=openid+profile+email+offline_access&state=state"
|
|
||||||
|
|
||||||
action, cookies, _ := ZeroTierGet(url, nil, 4)
|
|
||||||
var buff bytes.Buffer
|
|
||||||
buff.WriteString("email=")
|
|
||||||
buff.WriteString(email)
|
|
||||||
buff.WriteString("&password=")
|
|
||||||
buff.WriteString(password)
|
|
||||||
buff.WriteString("&password-confirm=")
|
|
||||||
buff.WriteString(password)
|
|
||||||
buff.WriteString("&user.attributes.marketingOptIn=true")
|
|
||||||
buff.WriteString("&firstName")
|
|
||||||
buff.WriteString(firstName)
|
|
||||||
buff.WriteString("&lastName")
|
|
||||||
buff.WriteString(lastName)
|
|
||||||
|
|
||||||
action, errInfo, _ := ZeroTierPost(buff, action, cookies, false)
|
|
||||||
if len(errInfo) > 0 {
|
|
||||||
return errInfo
|
|
||||||
}
|
|
||||||
action, _, _ = ZeroTierGet(action, cookies, 5)
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
//固定请求head
|
|
||||||
func GetHead() map[string]string {
|
|
||||||
var head = make(map[string]string, 4)
|
|
||||||
head["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"
|
|
||||||
head["Accept-Language"] = "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3"
|
|
||||||
head["Connection"] = "keep-alive"
|
|
||||||
head["User-Agent"] = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"
|
|
||||||
return head
|
|
||||||
}
|
|
||||||
|
|
||||||
//登录并获取token,会出现账号密码错误,和邮箱未验证情况,目前未出现其他情况
|
|
||||||
func LoginGetToken(username, pwd string) string {
|
|
||||||
//拿到登录的action
|
|
||||||
var loginUrl = "https://accounts.zerotier.com/auth/realms/zerotier/protocol/openid-connect/auth?client_id=zt-central&redirect_uri=https%3A%2F%2Fmy.zerotier.com%2Fapi%2F_auth%2Foidc%2Fcallback&response_type=code&scope=openid+profile+email+offline_access&state=states"
|
|
||||||
action, cookies, _ := ZeroTierGet(loginUrl, nil, 1)
|
|
||||||
if len(action) == 0 {
|
|
||||||
//没有拿到action,页面结构变了
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
//登录
|
|
||||||
var str bytes.Buffer
|
|
||||||
str.WriteString("username=")
|
|
||||||
str.WriteString(username)
|
|
||||||
str.WriteString("&password=")
|
|
||||||
str.WriteString(pwd)
|
|
||||||
str.WriteString("&credentialId=&login=Log+In")
|
|
||||||
url, logingErrInfo, _ := ZeroTierPost(str, action, cookies, true)
|
|
||||||
|
|
||||||
action, cookies, isLoginOk := ZeroTierGet(url, cookies, 2)
|
|
||||||
|
|
||||||
if isLoginOk {
|
|
||||||
//登录成功,可以继续调用api
|
|
||||||
randomTokenUrl := "https://my.zerotier.com/api/randomToken"
|
|
||||||
json, _, _ := ZeroTierGet(randomTokenUrl, cookies, 3)
|
|
||||||
//获取一个随机token
|
|
||||||
token := gjson.Get(json, "token")
|
|
||||||
|
|
||||||
userInfoUrl := "https://my.zerotier.com/api/status"
|
|
||||||
json, _, _ = ZeroTierGet(userInfoUrl, cookies, 3)
|
|
||||||
//拿到用户id
|
|
||||||
userId := gjson.Get(json, "user.id")
|
|
||||||
|
|
||||||
//设置新token
|
|
||||||
addTokenUrl := "https://my.zerotier.com/api/user/" + userId.String() + "/token"
|
|
||||||
data := make(map[string]string)
|
|
||||||
rand.Seed(time.Now().UnixNano())
|
|
||||||
data["tokenName"] = "oasis-token-" + strconv.Itoa(rand.Intn(1000))
|
|
||||||
data["token"] = token.String()
|
|
||||||
head := make(map[string]string)
|
|
||||||
head["Content-Type"] = "application/json"
|
|
||||||
_, statusCode := httper2.ZeroTierPost(addTokenUrl, data, head, cookies)
|
|
||||||
if statusCode == http.StatusOK {
|
|
||||||
config.Cfg.Section("zerotier").Key("Token").SetValue(token.String())
|
|
||||||
config.Cfg.SaveTo("conf/conf.ini")
|
|
||||||
config.ZeroTierInfo.Token = token.String()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//登录错误信息
|
|
||||||
if len(logingErrInfo) > 0 {
|
|
||||||
return logingErrInfo
|
|
||||||
} else {
|
|
||||||
//验证邮箱
|
|
||||||
action, _, _ = ZeroTierGet(url, cookies, 5)
|
|
||||||
return "You need to verify your email address to activate your account."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// t 1:获取action,2:登录成功后拿session(可能需要验证有了或登录失败) 3:随机生成token 4:注册页面拿action 5:注册成功后拿验证邮箱的地址
|
|
||||||
func ZeroTierGet(url string, cookies []*http.Cookie, t uint8) (action string, c []*http.Cookie, isExistSession bool) {
|
|
||||||
isExistSession = false
|
|
||||||
action = ""
|
|
||||||
c = []*http.Cookie{}
|
|
||||||
request, _ := http.NewRequest(http.MethodGet, url, nil)
|
|
||||||
for k, v := range GetHead() {
|
|
||||||
request.Header.Add(k, v)
|
|
||||||
}
|
|
||||||
for _, cookie := range cookies {
|
|
||||||
request.AddCookie(cookie)
|
|
||||||
}
|
|
||||||
resp, err := client.Do(request)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
c = resp.Cookies()
|
|
||||||
if t == 1 {
|
|
||||||
doc, err := goquery.NewDocumentFromReader(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
action, _ = doc.Find("#kc-form-login").Attr("action")
|
|
||||||
return
|
|
||||||
} else if t == 2 {
|
|
||||||
for _, cookie := range resp.Cookies() {
|
|
||||||
if cookie.Name == "pgx-session" {
|
|
||||||
isExistSession = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//判断是否登录成功,如果需要验证邮箱,则返回验证邮箱的地址。
|
|
||||||
if resp.StatusCode == http.StatusFound && len(resp.Header.Get("Location")) > 0 {
|
|
||||||
action = resp.Header.Get("Location")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
} else if t == 3 {
|
|
||||||
//返回获取到的字符串
|
|
||||||
byteArr, _ := ioutil.ReadAll(resp.Body)
|
|
||||||
action = string(byteArr)
|
|
||||||
} else if t == 4 {
|
|
||||||
doc, err := goquery.NewDocumentFromReader(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
action, _ = doc.Find("#kc-register-form").Attr("action")
|
|
||||||
return
|
|
||||||
|
|
||||||
} else if t == 5 {
|
|
||||||
doc, _ := goquery.NewDocumentFromReader(resp.Body)
|
|
||||||
fmt.Println(doc.Html())
|
|
||||||
action, _ = doc.Find("#kc-info-wrapper a").Attr("href")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//模拟提交表单
|
|
||||||
func ZeroTierPost(str bytes.Buffer, action string, cookes []*http.Cookie, isLogin bool) (url, errInfo string, err error) {
|
|
||||||
req, err := http.NewRequest(http.MethodPost, action, strings.NewReader(str.String()))
|
|
||||||
if err != nil {
|
|
||||||
return "", "", errors.New("newrequest error")
|
|
||||||
}
|
|
||||||
for k, v := range GetHead() {
|
|
||||||
req.Header.Set(k, v)
|
|
||||||
}
|
|
||||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
|
||||||
for _, cookie := range cookes {
|
|
||||||
req.AddCookie(cookie)
|
|
||||||
}
|
|
||||||
res, err := client.Do(req)
|
|
||||||
defer res.Body.Close()
|
|
||||||
if err != nil {
|
|
||||||
return "", "", errors.New("request error")
|
|
||||||
}
|
|
||||||
if !isLogin {
|
|
||||||
//注册成功
|
|
||||||
if res.StatusCode == http.StatusFound && len(res.Header.Get("Location")) > 0 {
|
|
||||||
return res.Header.Get("Location"), "", nil
|
|
||||||
} else {
|
|
||||||
register, _ := goquery.NewDocumentFromReader(res.Body)
|
|
||||||
firstErr := strings.TrimSpace(register.Find("#input-error-firstname").Text())
|
|
||||||
lastErr := strings.TrimSpace(register.Find("#input-error-lastname").Text())
|
|
||||||
emailErr := strings.TrimSpace(register.Find("#input-error-email").Text())
|
|
||||||
pwdErr := strings.TrimSpace(register.Find("#input-error-password").Text())
|
|
||||||
var errD strings.Builder
|
|
||||||
if len(firstErr) > 0 {
|
|
||||||
errD.WriteString(firstErr + ",")
|
|
||||||
}
|
|
||||||
if len(lastErr) > 0 {
|
|
||||||
errD.WriteString(lastErr + ",")
|
|
||||||
}
|
|
||||||
if len(emailErr) > 0 {
|
|
||||||
errD.WriteString(emailErr + ",")
|
|
||||||
}
|
|
||||||
if len(pwdErr) > 0 {
|
|
||||||
errD.WriteString(pwdErr + ",")
|
|
||||||
}
|
|
||||||
return "", errD.String(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if res.StatusCode == http.StatusFound && len(res.Header.Get("Location")) > 0 {
|
|
||||||
return res.Header.Get("Location"), "", nil
|
|
||||||
}
|
|
||||||
doc, err := goquery.NewDocumentFromReader(res.Body)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", errors.New("request error")
|
|
||||||
}
|
|
||||||
|
|
||||||
errDesc := doc.Find("#input-error").Text()
|
|
||||||
if len(errDesc) > 0 {
|
|
||||||
return "", strings.TrimSpace(errDesc), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//获取zerotile网络列表和本地用户已加入的网络
|
|
||||||
func (c *zerotierstruct) ZeroTierNetworkList(token string) (interface{}, []string) {
|
|
||||||
url := "https://my.zerotier.com/api/network"
|
|
||||||
return zerotier.GetData(url, token), command2.ExecResultStrArray(`zerotier-cli listnetworks | awk 'NR>1 {print $3} {line=$0}'`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// get network info
|
|
||||||
func (c *zerotierstruct) ZeroTierGetInfo(token, id string) (interface{}, []string) {
|
|
||||||
url := "https://my.zerotier.com/api/network/" + id
|
|
||||||
info := zerotier.GetData(url, token)
|
|
||||||
return info, command2.ExecResultStrArray(`zerotier-cli listnetworks | awk 'NR>1 {print $3} {line=$0}'`)
|
|
||||||
}
|
|
||||||
|
|
||||||
//get status
|
|
||||||
func (c *zerotierstruct) ZeroTierGetStatus(token string) interface{} {
|
|
||||||
url := "https://my.zerotier.com/api/v1/status"
|
|
||||||
info := zerotier.GetData(url, token)
|
|
||||||
return info
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *zerotierstruct) EditNetwork(token string, data string, id string) interface{} {
|
|
||||||
url := "https://my.zerotier.com/api/v1/network/" + id
|
|
||||||
info := zerotier.PostData(url, token, data)
|
|
||||||
return info
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *zerotierstruct) EditNetworkMember(token string, data string, id, mId string) interface{} {
|
|
||||||
url := "https://my.zerotier.com/api/v1/network/" + id + "/member/" + mId
|
|
||||||
info := zerotier.PostData(url, token, data)
|
|
||||||
return info
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *zerotierstruct) MemberList(token string, id string) interface{} {
|
|
||||||
url := "https://my.zerotier.com/api/v1/network/" + id + "/member"
|
|
||||||
info := zerotier.GetData(url, token)
|
|
||||||
return info
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *zerotierstruct) DeleteMember(token string, id, mId string) interface{} {
|
|
||||||
url := "https://my.zerotier.com/api/v1/network/" + id + "/member/" + mId
|
|
||||||
info := zerotier.DeleteMember(url, token)
|
|
||||||
return info
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *zerotierstruct) DeleteNetwork(token, id string) interface{} {
|
|
||||||
url := "https://my.zerotier.com/api/v1/network/" + id
|
|
||||||
info := zerotier.DeleteMember(url, token)
|
|
||||||
return info
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *zerotierstruct) CreateNetwork(token string) interface{} {
|
|
||||||
url := "https://my.zerotier.com/api/v1/network"
|
|
||||||
info := zerotier.PostData(url, token, "{}")
|
|
||||||
return info
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *zerotierstruct) GetJoinNetworks() string {
|
|
||||||
json := command2.ExecResultStr("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetLocalJoinNetworks")
|
|
||||||
return json
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewZeroTierService() ZeroTierService {
|
|
||||||
//初始化client
|
|
||||||
client = http.Client{Timeout: 30 * time.Second, CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
|
||||||
return http.ErrUseLastResponse //禁止重定向
|
|
||||||
},
|
|
||||||
}
|
|
||||||
return &zerotierstruct{}
|
|
||||||
}
|
|
||||||
@@ -4,9 +4,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
@@ -31,12 +34,15 @@ type ZiMaService interface {
|
|||||||
GetNetState(name string) string
|
GetNetState(name string) string
|
||||||
GetSysInfo() host.InfoStat
|
GetSysInfo() host.InfoStat
|
||||||
GetDirPath(path string) []model.Path
|
GetDirPath(path string) []model.Path
|
||||||
|
GetDirPathOne(path string) (m model.Path)
|
||||||
MkdirAll(path string) (int, error)
|
MkdirAll(path string) (int, error)
|
||||||
CreateFile(path string) (int, error)
|
CreateFile(path string) (int, error)
|
||||||
RenameFile(oldF, newF string) (int, error)
|
RenameFile(oldF, newF string) (int, error)
|
||||||
GetCpuInfo() []cpu.InfoStat
|
GetCpuInfo() []cpu.InfoStat
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var NetArray [][]model.IOCountersStat
|
||||||
|
|
||||||
type zima struct {
|
type zima struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,17 +89,41 @@ func (c *zima) GetDirPath(path string) []model.Path {
|
|||||||
|
|
||||||
ls, _ := ioutil.ReadDir(path)
|
ls, _ := ioutil.ReadDir(path)
|
||||||
dirs := []model.Path{}
|
dirs := []model.Path{}
|
||||||
|
if len(path) > 0 {
|
||||||
if strings.Count(path, "/") > 0 {
|
|
||||||
for _, l := range ls {
|
for _, l := range ls {
|
||||||
dirs = append(dirs, model.Path{Name: l.Name(), Path: path + "/" + l.Name(), IsDir: l.IsDir()})
|
filePath := filepath.Join(path, l.Name())
|
||||||
|
link, err := filepath.EvalSymlinks(filePath)
|
||||||
|
if err != nil {
|
||||||
|
link = filePath
|
||||||
|
}
|
||||||
|
temp := model.Path{Name: l.Name(), Path: filePath, IsDir: l.IsDir(), Date: l.ModTime(), Size: l.Size()}
|
||||||
|
if filePath != link {
|
||||||
|
file, _ := os.Stat(link)
|
||||||
|
temp.IsDir = file.IsDir()
|
||||||
|
}
|
||||||
|
dirs = append(dirs, temp)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dirs = append(dirs, model.Path{Name: "DATA", Path: "/DATA/", IsDir: true})
|
dirs = append(dirs, model.Path{Name: "DATA", Path: "/DATA/", IsDir: true, Date: time.Now()})
|
||||||
}
|
}
|
||||||
return dirs
|
return dirs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *zima) GetDirPathOne(path string) (m model.Path) {
|
||||||
|
|
||||||
|
f, err := os.Stat(path)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
m.IsDir = f.IsDir()
|
||||||
|
m.Name = f.Name()
|
||||||
|
m.Path = path
|
||||||
|
m.Size = f.Size()
|
||||||
|
m.Date = f.ModTime()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
//获取系统信息
|
//获取系统信息
|
||||||
func (c *zima) GetSysInfo() host.InfoStat {
|
func (c *zima) GetSysInfo() host.InfoStat {
|
||||||
info, _ := host.Info()
|
info, _ := host.Info()
|
||||||
@@ -116,7 +146,6 @@ func (c *zima) GetNetState(name string) string {
|
|||||||
|
|
||||||
//网络信息
|
//网络信息
|
||||||
func (c *zima) GetNetInfo() []net.IOCountersStat {
|
func (c *zima) GetNetInfo() []net.IOCountersStat {
|
||||||
//loger.Error("输出个内容试试")
|
|
||||||
parts, _ := net.IOCounters(true)
|
parts, _ := net.IOCounters(true)
|
||||||
//fmt.Println(net.ConntrackStatsWithContext(true))
|
//fmt.Println(net.ConntrackStatsWithContext(true))
|
||||||
return parts
|
return parts
|
||||||
@@ -174,3 +203,41 @@ func (c *zima) RenameFile(oldF, newF string) (int, error) {
|
|||||||
func NewZiMaService() ZiMaService {
|
func NewZiMaService() ZiMaService {
|
||||||
return &zima{}
|
return &zima{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LoopNet() {
|
||||||
|
netList := MyService.ZiMa().GetNetInfo()
|
||||||
|
|
||||||
|
nets := MyService.ZiMa().GetNet(true)
|
||||||
|
num := 0
|
||||||
|
for i := 0; i < len(netList); i++ {
|
||||||
|
|
||||||
|
for _, netCardName := range nets {
|
||||||
|
|
||||||
|
if netList[i].Name == netCardName {
|
||||||
|
var netArray []model.IOCountersStat
|
||||||
|
if len(NetArray) < (num + 1) {
|
||||||
|
netArray = []model.IOCountersStat{}
|
||||||
|
} else {
|
||||||
|
netArray = NetArray[num]
|
||||||
|
}
|
||||||
|
item := *(*model.IOCountersStat)(unsafe.Pointer(&netList[i]))
|
||||||
|
item.State = strings.TrimSpace(MyService.ZiMa().GetNetState(netList[i].Name))
|
||||||
|
item.Time = time.Now().Unix()
|
||||||
|
|
||||||
|
if len(netArray) >= 60 {
|
||||||
|
netArray = netArray[1:]
|
||||||
|
}
|
||||||
|
netArray = append(netArray, item)
|
||||||
|
if len(NetArray) < (num + 1) {
|
||||||
|
NetArray = append(NetArray, []model.IOCountersStat{})
|
||||||
|
}
|
||||||
|
|
||||||
|
NetArray[num] = netArray
|
||||||
|
|
||||||
|
num++
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
35
shell/assist.sh
Normal file
35
shell/assist.sh
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# add in v0.2.5
|
||||||
|
|
||||||
|
readonly CASA_DEPANDS="curl smartmontools parted fdisk ntfs-3g"
|
||||||
|
|
||||||
|
version_0_2_5() {
|
||||||
|
install_depends "$CASA_DEPANDS"
|
||||||
|
}
|
||||||
|
version_0_2_11() {
|
||||||
|
sysctl -w net.core.rmem_max=2500000
|
||||||
|
}
|
||||||
|
|
||||||
|
#Install Depends
|
||||||
|
install_depends() {
|
||||||
|
((EUID)) && sudo_cmd="sudo"
|
||||||
|
if [[ ! -x "$(command -v '$1')" ]]; then
|
||||||
|
packagesNeeded=$1
|
||||||
|
if [ -x "$(command -v apk)" ]; then
|
||||||
|
$sudo_cmd apk add --no-cache $packagesNeeded
|
||||||
|
elif [ -x "$(command -v apt-get)" ]; then
|
||||||
|
$sudo_cmd apt-get -y -q install $packagesNeeded
|
||||||
|
elif [ -x "$(command -v dnf)" ]; then
|
||||||
|
$sudo_cmd dnf install $packagesNeeded
|
||||||
|
elif [ -x "$(command -v zypper)" ]; then
|
||||||
|
$sudo_cmd zypper install $packagesNeeded
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
version_0_2_5
|
||||||
|
|
||||||
|
version_0_2_11
|
||||||
223
shell/helper.sh
223
shell/helper.sh
@@ -30,6 +30,11 @@ GetNetCard() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GetTimeZone(){
|
||||||
|
timedatectl | grep "Time zone" | awk '{print $3}'
|
||||||
|
}
|
||||||
|
|
||||||
#查看网卡状态
|
#查看网卡状态
|
||||||
#param 网卡名称
|
#param 网卡名称
|
||||||
CatNetCardState() {
|
CatNetCardState() {
|
||||||
@@ -68,10 +73,8 @@ UMountPorintAndRemoveDir() {
|
|||||||
if [[ -z ${MOUNT_POINT} ]]; then
|
if [[ -z ${MOUNT_POINT} ]]; then
|
||||||
${log} "Warning: ${DEVICE} is not mounted"
|
${log} "Warning: ${DEVICE} is not mounted"
|
||||||
else
|
else
|
||||||
umount -l ${DEVICE}
|
umount -lf ${DEVICE}
|
||||||
${log} "Unmounted ${DEVICE} from ${MOUNT_POINT}"
|
|
||||||
/bin/rmdir "${MOUNT_POINT}"
|
/bin/rmdir "${MOUNT_POINT}"
|
||||||
sed -i.bak "\@${MOUNT_POINT}@d" /var/log/usb-mount.track
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,11 +87,11 @@ FormatDisk() {
|
|||||||
elif [ "$2" == "ntfs" ]; then
|
elif [ "$2" == "ntfs" ]; then
|
||||||
mkfs.ntfs $1
|
mkfs.ntfs $1
|
||||||
elif [ "$2" == "ext4" ]; then
|
elif [ "$2" == "ext4" ]; then
|
||||||
mkfs.ext4 -F $1
|
mkfs.ext4 -m 1 -F $1
|
||||||
elif [ "$2" == "exfat" ]; then
|
elif [ "$2" == "exfat" ]; then
|
||||||
mkfs.exfat $1
|
mkfs.exfat $1
|
||||||
else
|
else
|
||||||
mkfs.ext4 -F $1
|
mkfs.ext4 -m 1 -F $1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,20 +106,20 @@ DelPartition() {
|
|||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
#添加分区
|
#添加分区只有一个分区
|
||||||
#param 路径 /dev/sdb
|
#param 路径 /dev/sdb
|
||||||
#param 磁盘号 最大128
|
#param 要挂载的目录
|
||||||
#param 磁盘大小 字节 512*2048=1024kb=1M
|
|
||||||
AddPartition() {
|
AddPartition() {
|
||||||
# fdisk $1 <<EOF
|
|
||||||
# n
|
|
||||||
# $2
|
|
||||||
# $3
|
|
||||||
# $4
|
|
||||||
# wq
|
|
||||||
#EOF
|
|
||||||
|
|
||||||
parted $1 mkpart primary ext4 s3 s4
|
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
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#磁盘类型
|
#磁盘类型
|
||||||
@@ -141,17 +144,201 @@ GetDiskHealthState() {
|
|||||||
#result bytes
|
#result bytes
|
||||||
#result sectors
|
#result sectors
|
||||||
GetDiskSizeAndSectors() {
|
GetDiskSizeAndSectors() {
|
||||||
fdisk $1 -l | grep "/dev/sda:" | awk -F, 'BEGIN {OFS="\n"}{print $2,$3}' | awk '{print $1}'
|
fdisk $1 -l | grep "$1:" | awk -F, 'BEGIN {OFS="\n"}{print $2,$3}' | awk '{print $1}'
|
||||||
}
|
}
|
||||||
|
|
||||||
#获取磁盘分区数据扇区
|
#获取磁盘分区数据扇区
|
||||||
#param 磁盘路径 /dev/sda
|
#param 磁盘路径 /dev/sda
|
||||||
#result start,end,sectors
|
#result start,end,sectors
|
||||||
GetPartitionSectors() {
|
GetPartitionSectors() {
|
||||||
fdisk $1 -l | grep "/dev/sda[1-9]" | awk 'BEGIN{OFS=","}{print $1,$2,$3,$4}'
|
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服务
|
#重载samba服务
|
||||||
ReloadSamba() {
|
ReloadSamba() {
|
||||||
/etc/init.d/smbd reload
|
/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_Move_File() {
|
||||||
|
((EUID)) && sudo_cmd="sudo"
|
||||||
|
$sudo_cmd cp -rf /casaOS/server/shell/11-usb-mount.rules /etc/udev/rules.d/
|
||||||
|
$sudo_cmd chmod +x /casaOS/server/shell/usb-mount.sh
|
||||||
|
$sudo_cmd cp -rf /casaOS/server/shell/usb-mount@.service /etc/systemd/system/
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_Remove_File() {
|
||||||
|
((EUID)) && sudo_cmd="sudo"
|
||||||
|
$sudo_cmd rm -fr /etc/udev/rules.d/11-usb-mount.rules
|
||||||
|
$sudo_cmd rm -fr /etc/systemd/system/usb-mount@.service
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user