mirror of
https://github.com/IceWhaleTech/CasaOS.git
synced 2025-12-23 04:54:41 +00:00
Compare commits
160 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
2ed372b3cd | ||
|
|
8bca76b78b | ||
|
|
595e0f28af | ||
|
|
4939fe10aa | ||
|
|
d2962a8e70 | ||
|
|
d7d53d639b | ||
|
|
d2ff1b0506 | ||
|
|
7191735737 | ||
|
|
21f3fd85d9 | ||
|
|
ba77e07e36 | ||
|
|
0d6e7ca339 | ||
|
|
b1d5d9858b | ||
|
|
4f06be0e45 | ||
|
|
812ffd56a8 | ||
|
|
6ba845eec5 | ||
|
|
4fa72289ed | ||
|
|
5cdd842a3e | ||
|
|
cc5504c0a9 | ||
|
|
b3aa22605d | ||
|
|
32e00b17b1 | ||
|
|
16108f03ac | ||
|
|
e7f990b224 | ||
|
|
c5d824c4ba | ||
|
|
39ccbe251f | ||
|
|
e69d2e587b | ||
|
|
8a28d3c589 | ||
|
|
8fe0e4aa73 | ||
|
|
30a23a93a2 |
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
|
||||
# ln -sf /workdir/casa $GITHUB_WORKSPACE/casa
|
||||
# ls
|
||||
|
||||
|
||||
|
||||
- name: Set enviroment for github-release
|
||||
run: |
|
||||
@@ -76,7 +76,7 @@ jobs:
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
|
||||
|
||||
- name: Build frontend with nodejs and yarn
|
||||
run: |
|
||||
cd UI
|
||||
@@ -90,7 +90,7 @@ jobs:
|
||||
- name: Build with xgo
|
||||
uses: crazy-max/ghaction-xgo@v1
|
||||
with:
|
||||
xgo_version: latest
|
||||
xgo_version: v0.7.5
|
||||
go_version: ${{ matrix.go_version }}
|
||||
dest: build
|
||||
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 }}
|
||||
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -30,3 +30,6 @@ gen
|
||||
/db/
|
||||
/docs/
|
||||
/conf/conf.ini
|
||||
__debug_bin
|
||||
main
|
||||
CasaOS
|
||||
|
||||
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.
|
||||
86
README.md
86
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,55 @@
|
||||
[](https://github.com/IceWhaleTech/CasaOS/pulls)
|
||||
[](https://github.com/IceWhaleTech/CasaOS/issues)
|
||||
[](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.
|
||||
|
||||

|
||||

|
||||
|
||||
## 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)
|
||||
- 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
|
||||
|
||||
- UI designed for home scenarios - simple, elegant, and easy-to-use
|
||||
- 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 🚧
|
||||
- Smart home manager 🚧
|
||||
|
||||
@@ -34,48 +71,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.
|
||||
|
||||
> 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
|
||||
- Jerry Liu
|
||||
|
||||
2
UI
2
UI
Submodule UI updated: f2a5429db5...106902c76a
BIN
__debug_bin
BIN
__debug_bin
Binary file not shown.
@@ -15,13 +15,16 @@ ProjectPath = /casaOS/server
|
||||
HttpPort = 8089
|
||||
RunMode = release
|
||||
ServerApi = https://api.casaos.zimaboard.com
|
||||
Handshake =
|
||||
Token =
|
||||
|
||||
|
||||
[user]
|
||||
UserName = admin
|
||||
PWD = zimaboard
|
||||
Email = user@gmail.com
|
||||
Description = description
|
||||
Token = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImVyZXJlIiwicGFzc3dvcmQiOiJhZHNmZGYiLCJleHAiOjE2MjQwMDU0ODEsImlzcyI6Imdpbi1ibG9nIn0.JNsCccZuFCwlSMLJg62iOIB2xymk_k7xGa11xhZ07bc
|
||||
Initialized = false
|
||||
|
||||
[zerotier]
|
||||
UserName = user
|
||||
|
||||
40
go.mod
40
go.mod
@@ -7,29 +7,23 @@ require (
|
||||
github.com/Microsoft/hcsshim v0.8.22 // indirect
|
||||
github.com/PuerkitoBio/goquery v1.7.0
|
||||
github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
|
||||
github.com/aquasecurity/libbpfgo v0.2.1-libbpf-0.4.0 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.2.1 // indirect
|
||||
github.com/containerd/containerd v1.5.7
|
||||
github.com/containerd/continuity v0.2.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
|
||||
github.com/docker/distribution v2.8.0+incompatible // indirect
|
||||
github.com/docker/docker v20.10.7+incompatible
|
||||
github.com/docker/go-connections v0.4.0
|
||||
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/go-delve/delve v1.7.2 // indirect
|
||||
github.com/go-ini/ini v1.62.0
|
||||
github.com/go-ole/go-ole v1.2.5 // indirect
|
||||
github.com/go-openapi/jsonreference v0.19.6 // indirect
|
||||
github.com/go-openapi/spec v0.20.3 // indirect
|
||||
github.com/go-openapi/swag v0.19.15 // indirect
|
||||
github.com/go-openapi/spec v0.20.4 // indirect
|
||||
github.com/go-playground/validator/v10 v10.6.1 // indirect
|
||||
github.com/gogo/googleapis v1.4.1 // indirect
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/gomodule/redigo v1.8.5
|
||||
github.com/google/go-dap v0.6.0 // indirect
|
||||
github.com/google/go-github/v36 v36.0.0
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/gorilla/mux v1.8.0 // indirect
|
||||
@@ -39,13 +33,13 @@ require (
|
||||
github.com/klauspost/compress v1.13.6 // indirect
|
||||
github.com/leodido/go-urn v1.2.1 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.11 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.13 // 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/morikuni/aec v1.0.0 // indirect
|
||||
github.com/opencontainers/runc v1.0.2 // indirect
|
||||
github.com/opencontainers/image-spec v1.0.2 // indirect
|
||||
github.com/opencontainers/selinux v1.8.5 // indirect
|
||||
github.com/peterh/liner v1.2.1 // indirect
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prestonTao/upnp v0.0.0-20150206124352-f4370df5e109
|
||||
github.com/prometheus/procfs v0.7.3 // indirect
|
||||
@@ -55,32 +49,26 @@ require (
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/smartystreets/assertions v1.2.0 // indirect
|
||||
github.com/smartystreets/goconvey v1.6.4 // indirect
|
||||
github.com/spf13/cobra v1.2.1 // indirect
|
||||
github.com/swaggo/gin-swagger v1.3.0
|
||||
github.com/swaggo/swag v1.7.0
|
||||
github.com/tidwall/gjson v1.8.0
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/swaggo/swag v1.7.3
|
||||
github.com/tidwall/gjson v1.10.2
|
||||
github.com/tklauser/go-sysconf v0.3.6 // indirect
|
||||
github.com/ugorji/go v1.2.6 // indirect
|
||||
go.opencensus.io v0.23.0 // indirect
|
||||
go.starlark.net v0.0.0-20210901212718-87f333178d59 // indirect
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
|
||||
golang.org/x/mod v0.5.0 // indirect
|
||||
golang.org/x/net v0.0.0-20210924151903-3ad01bbaa167 // indirect
|
||||
golang.org/x/net v0.0.0-20211020060615-d418f374d309 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac // indirect
|
||||
golang.org/x/sys v0.0.0-20211020174200-9d6173849985 // indirect
|
||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
||||
golang.org/x/tools v0.1.5 // indirect
|
||||
golang.org/x/tools v0.1.7 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0 // indirect
|
||||
google.golang.org/grpc v1.41.0 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
gorm.io/driver/sqlite v1.1.5
|
||||
gorm.io/gorm v1.21.15
|
||||
src.techknowlogick.com/xgo v1.4.1-0.20211007230901-4fb1c2d7b2ab // indirect
|
||||
gorm.io/driver/sqlite v1.2.6
|
||||
gorm.io/gorm v1.22.5
|
||||
)
|
||||
|
||||
235
go.sum
235
go.sum
@@ -15,11 +15,6 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV
|
||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
|
||||
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
|
||||
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
|
||||
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
|
||||
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
@@ -28,7 +23,6 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g
|
||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||
@@ -74,7 +68,6 @@ github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg3
|
||||
github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg=
|
||||
github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00=
|
||||
github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600=
|
||||
github.com/Microsoft/hcsshim v0.8.18/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
|
||||
github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
|
||||
github.com/Microsoft/hcsshim v0.8.22 h1:CulZ3GW8sNJExknToo+RWD+U+6ZM5kkNfuxywSDPd08=
|
||||
github.com/Microsoft/hcsshim v0.8.22/go.mod h1:91uVCVzvX2QD16sMCenoxxXo6L1wJnLMX2PSufFMtF0=
|
||||
@@ -102,13 +95,7 @@ github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:C
|
||||
github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
|
||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/aquasecurity/libbpfgo v0.1.2-0.20210708203834-4928d36fafac/go.mod h1:/+clceXE103FaXvVTIY2HAkQjxNtkra4DRWvZYr2SKw=
|
||||
github.com/aquasecurity/libbpfgo v0.2.1-libbpf-0.4.0 h1:WekP69tdNlVfWdlXUqxGEwbeLCMfNcURBsq0uS5dPSI=
|
||||
github.com/aquasecurity/libbpfgo v0.2.1-libbpf-0.4.0/go.mod h1:/+clceXE103FaXvVTIY2HAkQjxNtkra4DRWvZYr2SKw=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||
github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
|
||||
github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
@@ -120,8 +107,6 @@ github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngE
|
||||
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
||||
github.com/bits-and-blooms/bitset v1.2.1 h1:M+/hrU9xlMp7t4TyTDQW97d3tRPVuKFC6zBEK16QnXY=
|
||||
github.com/bits-and-blooms/bitset v1.2.1/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
|
||||
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/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||
@@ -145,7 +130,6 @@ github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJ
|
||||
github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
@@ -184,8 +168,6 @@ github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo
|
||||
github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI=
|
||||
github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s=
|
||||
github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g=
|
||||
github.com/containerd/containerd v1.5.5 h1:q1gxsZsGZ8ddVe98yO6pR21b5xQSMiR61lD0W96pgQo=
|
||||
github.com/containerd/containerd v1.5.5/go.mod h1:oSTh0QpT1w6jYcGmbiSbxv9OSQYaa88mPyWIuU79zyo=
|
||||
github.com/containerd/containerd v1.5.7 h1:rQyoYtj4KddB3bxG6SAqd4+08gePNyJjRqvOIfV3rkM=
|
||||
github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c=
|
||||
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
@@ -244,7 +226,6 @@ github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgU
|
||||
github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
|
||||
github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
|
||||
github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
|
||||
@@ -258,12 +239,8 @@ github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+
|
||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cosiner/argv v0.1.0 h1:BVDiEL32lwHukgJKP87btEPenzrrHUjajs/8yzaqcXg=
|
||||
github.com/cosiner/argv v0.1.0/go.mod h1:EusR6TucWKX+zFgtdUsKT2Cvg45K5rtpCcWz4hK06d8=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
@@ -276,8 +253,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0=
|
||||
github.com/derekparker/trie v0.0.0-20200317170641-1fdf38b7b0e9 h1:G765iDCq7bP5opdrPkXk+4V3yfkgV9iGFuheWZ/X/zY=
|
||||
github.com/derekparker/trie v0.0.0-20200317170641-1fdf38b7b0e9/go.mod h1:D6ICZm05D9VN1n/8iOtBxLpXtoGp6HDFUJ1RNVieOSE=
|
||||
github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
@@ -286,6 +261,8 @@ github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TT
|
||||
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.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/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
@@ -308,9 +285,7 @@ github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
@@ -338,8 +313,6 @@ 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.7.2 h1:Tg03T9yM2xa8j6I3Z3oqLaQRSmKvxPd6g/2HJ6zICFA=
|
||||
github.com/gin-gonic/gin v1.7.2/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
|
||||
github.com/go-delve/delve v1.7.2 h1:QTDJlgx9OwUVYVm7xthyf2XHKrZcTQu3wkRbovktidM=
|
||||
github.com/go-delve/delve v1.7.2/go.mod h1:CHdOd8kuHlQxtBJr1HmJX5h+KmmWd/7Lk5d+D1zHn4E=
|
||||
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-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
@@ -364,19 +337,17 @@ github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3Hfo
|
||||
github.com/go-openapi/jsonreference v0.19.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
|
||||
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
|
||||
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
|
||||
github.com/go-openapi/jsonreference v0.19.4/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
|
||||
github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
|
||||
github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs=
|
||||
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
|
||||
github.com/go-openapi/spec v0.19.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
|
||||
github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
|
||||
github.com/go-openapi/spec v0.19.14/go.mod h1:gwrgJS15eCUgjLpMjBJmbZezCsw88LmgeEip0M63doA=
|
||||
github.com/go-openapi/spec v0.20.3 h1:uH9RQ6vdyPSs2pSy9fL8QPspDF2AMIMPtmK5coSSjtQ=
|
||||
github.com/go-openapi/spec v0.20.3/go.mod h1:gG4F8wdEDN+YPBMVnzE85Rbhf+Th2DTvA9nFPQ5AYEg=
|
||||
github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M=
|
||||
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
|
||||
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
|
||||
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.11/go.mod h1:Uc0gKkdR+ojzsEpjh39QChyu92vPgIr72POcgHMAgSY=
|
||||
github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
|
||||
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
@@ -396,6 +367,7 @@ github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblf
|
||||
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
|
||||
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
|
||||
github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
|
||||
github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0=
|
||||
@@ -424,7 +396,6 @@ 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.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.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
|
||||
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.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
@@ -440,7 +411,6 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/gomodule/redigo v1.8.5 h1:nRAxCa+SVsyjSBrtZmG/cqb6VbTmuRzpg/PoTFlpumc=
|
||||
@@ -460,9 +430,6 @@ 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.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-dap v0.5.1-0.20210713061233-c91b005e3987/go.mod h1:5q8aYQFnHOAZEMP+6vmq25HKYAEwE+LF5yh7JKrrhSQ=
|
||||
github.com/google/go-dap v0.6.0 h1:Y1RHGUtv3R8y6sXq2dtGRMYrFB2hSqyFVws7jucrzX4=
|
||||
github.com/google/go-dap v0.6.0/go.mod h1:5q8aYQFnHOAZEMP+6vmq25HKYAEwE+LF5yh7JKrrhSQ=
|
||||
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-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||
@@ -471,7 +438,6 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
|
||||
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
@@ -479,10 +445,6 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf
|
||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
@@ -510,39 +472,20 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf
|
||||
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.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/imdario/mergo v0.3.11/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 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
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/jinzhu/copier v0.3.2 h1:QdBOCbaouLDYaIPFfi1bKv5F5tPpeTwXe4sD0jqtz5w=
|
||||
@@ -551,6 +494,8 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
|
||||
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.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-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
@@ -579,7 +524,6 @@ github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47e
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
@@ -594,8 +538,6 @@ github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgx
|
||||
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/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/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=
|
||||
@@ -605,38 +547,25 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0
|
||||
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/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs=
|
||||
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-isatty v0.0.3/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.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
|
||||
github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
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.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
|
||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
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.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mattn/go-sqlite3 v1.14.9/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.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
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/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
|
||||
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
|
||||
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||
@@ -686,12 +615,13 @@ github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3I
|
||||
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.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.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-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
|
||||
github.com/opencontainers/runc v1.0.1/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
||||
github.com/opencontainers/runc v1.0.2 h1:opHZMaswlyxz1OuGpBE53Dwe4/xF7EZTY0A2L/FpCOg=
|
||||
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
||||
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
@@ -707,23 +637,18 @@ 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.5 h1:OkT6bMHOQ1JQQO4ihjQ49sj0+wciDcjziSVTRn8VeTA=
|
||||
github.com/opencontainers/selinux v1.8.5/go.mod h1:HTvjPFoGMbpQsG886e3lQwnsRWtE4TC1OF3OUvG9FAo=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
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/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
github.com/peterh/liner v0.0.0-20170317030525-88609521dc4b/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
|
||||
github.com/peterh/liner v1.2.1 h1:O4BlKaq/LWu6VRWmol4ByWfzx6MfXc5Op5HETyIy5yg=
|
||||
github.com/peterh/liner v1.2.1/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
|
||||
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=
|
||||
@@ -758,25 +683,19 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
|
||||
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
|
||||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
|
||||
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
|
||||
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/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
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/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
|
||||
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/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
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=
|
||||
@@ -797,26 +716,17 @@ github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4k
|
||||
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.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.3.1/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.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
||||
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
|
||||
github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw=
|
||||
github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
|
||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
|
||||
github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
@@ -830,22 +740,20 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14/go.mod h1:gxQT6pBGRuIGunNf/+tSOB5OHvguWi8Tbt82WOkf35E=
|
||||
github.com/swaggo/gin-swagger v1.3.0 h1:eOmp7r57oUgZPw2dJOjcGNMse9cvXcI4tTqBcnZtPsI=
|
||||
github.com/swaggo/gin-swagger v1.3.0/go.mod h1:oy1BRA6WvgtCp848lhxce7BnWH4C8Bxa0m5SkWx+cS0=
|
||||
github.com/swaggo/swag v1.5.1/go.mod h1:1Bl9F/ZBpVWh22nY0zmYyASPO1lI/zIwRDrpZU+tv8Y=
|
||||
github.com/swaggo/swag v1.7.0 h1:5bCA/MTLQoIqDXXyHfOpMeDvL9j68OY/udlK4pQoo4E=
|
||||
github.com/swaggo/swag v1.7.0/go.mod h1:BdPIL73gvS9NBsdi7M1JOxLvlbfvNRaBP8m6WT6Aajo=
|
||||
github.com/swaggo/swag v1.7.3 h1:ucB7irEdRrhjmW+Z1Ss4GjO68oPKQFjSgOR8BCAvcbU=
|
||||
github.com/swaggo/swag v1.7.3/go.mod h1:zD8h6h4SPv7t3l+4BKdRquqW1ASWjKZgT6Qv9z3kNqI=
|
||||
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-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
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.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
|
||||
github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE=
|
||||
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/tidwall/gjson v1.10.2 h1:APbLGOM0rrEkd8WBw9C24nllro4ajFuJu0Sc9hRz8Bo=
|
||||
github.com/tidwall/gjson v1.10.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tklauser/go-sysconf v0.3.4/go.mod h1:Cl2c8ZRWfHD5IrfHo9VN+FX9kCFjIOyVklgXycLB6ek=
|
||||
@@ -889,7 +797,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.32/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/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/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
|
||||
@@ -897,42 +805,27 @@ go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
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/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg=
|
||||
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
|
||||
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
|
||||
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
|
||||
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.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
|
||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
go.starlark.net v0.0.0-20200821142938-949cc6f4b097/go.mod h1:f0znQkUKRrkk36XxWbGjMqQM8wGv/xHBVE2qc3B5oFU=
|
||||
go.starlark.net v0.0.0-20210901212718-87f333178d59 h1:F8ArBy9n1l7HE1JjzOIYqweEqoUlywy5+L3bR0tIa9g=
|
||||
go.starlark.net v0.0.0-20210901212718-87f333178d59/go.mod h1:t3mmBBPzAVvK0L0n1drDmrQsJ8FoIx4INCqVMTr/Zo0=
|
||||
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.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||
golang.org/x/arch v0.0.0-20190927153633-4e8777c89be4/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
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-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/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-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-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-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
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=
|
||||
@@ -962,8 +855,6 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
|
||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
@@ -972,8 +863,6 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.5.0 h1:UG21uOlmZabA4fW5i7ZX6bjw1xELEGg/ZLgZq9auk/Q=
|
||||
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
@@ -983,9 +872,7 @@ 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-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-20181023162649-9b4f9f5ad519/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-20181201002055-351d144fa1fc/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-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -1020,29 +907,20 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
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-20210924151903-3ad01bbaa167 h1:eDd+TJqbgfXruGQ5sJRU7tEtp/58OAx4+Ayjxg4SM+4=
|
||||
golang.org/x/net v0.0.0-20210924151903-3ad01bbaa167/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/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-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-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-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
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/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -1057,11 +935,9 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/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-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/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-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -1114,11 +990,9 @@ golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
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-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -1128,31 +1002,22 @@ 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-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-20210104204734-6f8348627aad/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-20210217105451-b926d437f341/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927052749-1cf2251ac284 h1:lBPNCmq8u4zFP3huKCmUQ2Fx8kcY4X+O12UgGnyKsrg=
|
||||
golang.org/x/sys v0.0.0-20210927052749-1cf2251ac284/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac h1:oN6lz7iLW/YC7un8pq+9bOLyXrprv2+DKfkJY+2LJJw=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211020174200-9d6173849985 h1:LOlKVhfDyahgmqa97awczplwkjzNaELFg3zRIJ13RYo=
|
||||
golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE=
|
||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
@@ -1195,12 +1060,10 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191127201027-ecd32218bd7f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
@@ -1223,17 +1086,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-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-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201120155355-20be4ac4bd6e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/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.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
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/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -1256,12 +1112,6 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M
|
||||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
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.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
||||
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
||||
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
||||
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
|
||||
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
|
||||
google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
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=
|
||||
@@ -1303,18 +1153,7 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc
|
||||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
|
||||
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||
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/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
@@ -1333,14 +1172,9 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||
google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E=
|
||||
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
|
||||
@@ -1374,7 +1208,6 @@ gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKW
|
||||
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
|
||||
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
|
||||
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||
@@ -1399,8 +1232,13 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v
|
||||
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.1.5/go.mod h1:NpaYMcVKEh6vLJ47VP6T7Weieu4H1Drs3dGD/K6GrGc=
|
||||
gorm.io/driver/sqlite v1.2.6 h1:SStaH/b+280M7C8vXeZLz/zo9cLQmIGwwj3cSj7p6l4=
|
||||
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.21.15/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
|
||||
gorm.io/gorm v1.22.3/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/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||
@@ -1439,7 +1277,6 @@ k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAG
|
||||
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
|
||||
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
|
||||
@@ -1448,5 +1285,3 @@ 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/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
src.techknowlogick.com/xgo v1.4.1-0.20211007230901-4fb1c2d7b2ab h1:JB9ZA1DJczGU93I2LHsSiut2XO+CyepZBwYicEMt/hg=
|
||||
src.techknowlogick.com/xgo v1.4.1-0.20211007230901-4fb1c2d7b2ab/go.mod h1:31CE1YKtDOrKTk9PSnjTpe6YbO6W/0LTYZ1VskL09oU=
|
||||
|
||||
28
main.go
28
main.go
@@ -6,21 +6,23 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/cache"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/sqlite"
|
||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
"github.com/IceWhaleTech/CasaOS/route"
|
||||
"github.com/IceWhaleTech/CasaOS/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/robfig/cron"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var sqliteDB *gorm.DB
|
||||
|
||||
var swagHandler gin.HandlerFunc
|
||||
var configFlag = flag.String("c", "", "config address")
|
||||
|
||||
var showUserInfo = flag.Bool("show-user-info", false, "show user info")
|
||||
|
||||
func init() {
|
||||
flag.Parse()
|
||||
config.InitSetup(*configFlag)
|
||||
@@ -29,27 +31,36 @@ func init() {
|
||||
sqliteDB = sqlite.GetDb(config.AppInfo.ProjectPath)
|
||||
//gredis.GetRedisConn(config.RedisInfo),
|
||||
service.MyService = service.NewService(sqliteDB, loger2.NewOLoger())
|
||||
service.Cache = cache.Init()
|
||||
route.InitFunction()
|
||||
}
|
||||
|
||||
// @title Oasis API
|
||||
// @title casaOS API
|
||||
// @version 1.0.0
|
||||
// @contact.name lauren.pan
|
||||
// @contact.url https://www.zimaboard.com
|
||||
// @contact.email lauren.pan@icewhale.org
|
||||
// @description Oasis v1版本api
|
||||
// @host 192.168.2.114:8089
|
||||
// @description casaOS v1版本api
|
||||
// @host 192.168.2.217:8089
|
||||
// @securityDefinitions.apikey ApiKeyAuth
|
||||
// @in header
|
||||
// @name Authorization
|
||||
// @BasePath /v1
|
||||
func main() {
|
||||
if *showUserInfo {
|
||||
fmt.Println("CasaOS User Info")
|
||||
fmt.Println("UserName:" + config.UserInfo.UserName)
|
||||
fmt.Println("Password:" + config.UserInfo.PWD)
|
||||
return
|
||||
}
|
||||
//model.Setup()
|
||||
//gredis.Setup()
|
||||
r := route.InitRouter(swagHandler)
|
||||
r := route.InitRouter()
|
||||
//service.SyncTask(sqliteDB)
|
||||
cron2 := cron.New() //创建一个cron实例
|
||||
//执行定时任务(每5秒执行一次)
|
||||
err := cron2.AddFunc("0 0 0 1/1 * *", func() {
|
||||
//every day execution
|
||||
err := cron2.AddFunc("0 0/1 * * * *", func() {
|
||||
//service.PushIpInfo(*&config.ServerInfo.Token)
|
||||
//service.UpdataDDNSList(mysqldb)
|
||||
//service.SyncTask(sqliteDB)
|
||||
})
|
||||
@@ -67,6 +78,7 @@ func main() {
|
||||
WriteTimeout: 60 * time.Second,
|
||||
MaxHeaderBytes: 1 << 20,
|
||||
}
|
||||
|
||||
s.ListenAndServe()
|
||||
|
||||
}
|
||||
|
||||
@@ -2,8 +2,9 @@ package middleware
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
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-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")
|
||||
//设置缓存时间
|
||||
|
||||
62
model/app.go
62
model/app.go
@@ -7,32 +7,42 @@ import (
|
||||
)
|
||||
|
||||
type ServerAppList struct {
|
||||
Id uint `gorm:"column:id;primary_key" json:"id"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Tagline string `json:"tagline"`
|
||||
Tags Strings `gorm:"type:json" json:"tags"`
|
||||
Icon string `json:"icon"`
|
||||
ScreenshotLink Strings `gorm:"type:json" json:"screenshot_link"`
|
||||
Category string `json:"category"`
|
||||
TcpPort uint `json:"tcp_port"`
|
||||
PortMap uint `json:"port_map"`
|
||||
ImageVersion string `json:"image_version"`
|
||||
Tip string `json:"tip"`
|
||||
Configures configures `gorm:"type:json" json:"configures"`
|
||||
NetworkModel string `json:"network_mode"`
|
||||
Image string `json:"image"`
|
||||
Index string `json:"index"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
State string `json:"state"`
|
||||
Author string `json:"author"`
|
||||
MinMemory int `json:"min_memory"`
|
||||
MinDisk int `json:"min_disk"`
|
||||
MaxMemory uint64 `json:"max_memory"`
|
||||
Thumbnail string `json:"thumbnail"`
|
||||
Healthy string `json:"healthy"`
|
||||
Plugins Strings `json:"plugins"`
|
||||
Id uint `gorm:"column:id;primary_key" json:"id"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Tagline string `json:"tagline"`
|
||||
Tags Strings `gorm:"type:json" json:"tags"`
|
||||
Icon string `json:"icon"`
|
||||
ScreenshotLink Strings `gorm:"type:json" json:"screenshot_link"`
|
||||
Category string `json:"category"`
|
||||
CategoryFont string `json:"category_font"`
|
||||
PortMap string `json:"port_map"`
|
||||
ImageVersion string `json:"image_version"`
|
||||
Tip string `json:"tip"`
|
||||
Envs EnvArray `json:"envs"`
|
||||
Ports PortArray `json:"ports"`
|
||||
Volumes PathArray `json:"volumes"`
|
||||
Devices PathArray `json:"devices"`
|
||||
NetworkModel string `json:"network_model"`
|
||||
Image string `json:"image"`
|
||||
Index string `json:"index"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
State string `json:"state"`
|
||||
Author string `json:"author"`
|
||||
MinMemory int `json:"min_memory"`
|
||||
MinDisk int `json:"min_disk"`
|
||||
MaxMemory uint64 `json:"max_memory"`
|
||||
Thumbnail string `json:"thumbnail"`
|
||||
Healthy string `json:"healthy"`
|
||||
Plugins Strings `json:"plugins"`
|
||||
Origin string `json:"origin"`
|
||||
Type 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 {
|
||||
|
||||
@@ -5,6 +5,7 @@ type ServerCategoryList struct {
|
||||
//CreatedAt time.Time `json:"created_at"`
|
||||
//
|
||||
//UpdatedAt time.Time `json:"updated_at"`
|
||||
Font string `json:"font"`
|
||||
Name string `json:"name"`
|
||||
Count uint `json:"count"`
|
||||
}
|
||||
|
||||
@@ -20,12 +20,57 @@ type LSBLKModel struct {
|
||||
Format string `json:"format"`
|
||||
Health string `json:"health"`
|
||||
HotPlug bool `json:"hotplug"`
|
||||
UUID string `json:"uuid"`
|
||||
FSUsed string `json:"fsused"`
|
||||
Temperature int `json:"temperature"`
|
||||
Tran string `json:"tran"`
|
||||
MinIO uint64 `json:"min-io"`
|
||||
UsedPercent float64 `json:"used_percent"`
|
||||
Serial string `json:"serial"`
|
||||
Children []LSBLKModel `json:"children"`
|
||||
SubSystems string `json:"subsystems"`
|
||||
//详情特有
|
||||
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"`
|
||||
}
|
||||
|
||||
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************************************/
|
||||
|
||||
type PortMap struct {
|
||||
ContainerPort string `json:"container,omitempty"`
|
||||
CommendPort string `json:"host,omitempty"`
|
||||
ContainerPort string `json:"container"`
|
||||
CommendPort string `json:"host"`
|
||||
Protocol string `json:"protocol"`
|
||||
Desc string `json:"desc"`
|
||||
Type int `json:"type"`
|
||||
}
|
||||
|
||||
type PortArrey []PortMap
|
||||
type PortArray []PortMap
|
||||
|
||||
// Value 实现方法
|
||||
func (p PortArrey) Value() (driver.Value, error) {
|
||||
func (p PortArray) Value() (driver.Value, error) {
|
||||
return json.Marshal(p)
|
||||
}
|
||||
|
||||
// Scan 实现方法
|
||||
func (p *PortArrey) Scan(input interface{}) error {
|
||||
func (p *PortArray) Scan(input interface{}) error {
|
||||
return json.Unmarshal(input.([]byte), p)
|
||||
}
|
||||
|
||||
@@ -41,20 +43,22 @@ func (p *PortArrey) Scan(input interface{}) error {
|
||||
type Env struct {
|
||||
Name string `json:"container"`
|
||||
Value string `json:"host"`
|
||||
Desc string `json:"desc"`
|
||||
Type int `json:"type"`
|
||||
}
|
||||
|
||||
type JSON json.RawMessage
|
||||
|
||||
type EnvArrey []Env
|
||||
type EnvArray []Env
|
||||
|
||||
// Value 实现方法
|
||||
func (p EnvArrey) Value() (driver.Value, error) {
|
||||
func (p EnvArray) Value() (driver.Value, error) {
|
||||
return json.Marshal(p)
|
||||
//return .MarshalJSON()
|
||||
}
|
||||
|
||||
// Scan 实现方法
|
||||
func (p *EnvArrey) Scan(input interface{}) error {
|
||||
func (p *EnvArray) Scan(input interface{}) error {
|
||||
return json.Unmarshal(input.([]byte), p)
|
||||
}
|
||||
|
||||
@@ -65,17 +69,19 @@ func (p *EnvArrey) Scan(input interface{}) error {
|
||||
type PathMap struct {
|
||||
ContainerPath string `json:"container"`
|
||||
Path string `json:"host"`
|
||||
Type int `json:"type"`
|
||||
Desc string `json:"desc"`
|
||||
}
|
||||
|
||||
type PathArrey []PathMap
|
||||
type PathArray []PathMap
|
||||
|
||||
// Value 实现方法
|
||||
func (p PathArrey) Value() (driver.Value, error) {
|
||||
func (p PathArray) Value() (driver.Value, error) {
|
||||
return json.Marshal(p)
|
||||
}
|
||||
|
||||
// Scan 实现方法
|
||||
func (p *PathArrey) Scan(input interface{}) error {
|
||||
func (p *PathArray) Scan(input interface{}) error {
|
||||
return json.Unmarshal(input.([]byte), p)
|
||||
}
|
||||
|
||||
@@ -103,17 +109,21 @@ type CustomizationPostData struct {
|
||||
Index string `json:"index"`
|
||||
Icon string `json:"icon"`
|
||||
Image string `json:"image"`
|
||||
Envs EnvArrey `json:"envs"`
|
||||
Ports PortArrey `json:"ports"`
|
||||
Volumes PathArrey `json:"volumes"`
|
||||
Devices PathArrey `json:"devices"`
|
||||
Envs EnvArray `json:"envs"`
|
||||
Ports PortArray `json:"ports"`
|
||||
Volumes PathArray `json:"volumes"`
|
||||
Devices PathArray `json:"devices"`
|
||||
//Port string `json:"port,omitempty"`
|
||||
PortMap string `json:"port_map"`
|
||||
CpuShares int64 `json:"cpu_shares"`
|
||||
Memory int64 `json:"memory"`
|
||||
Restart string `json:"restart"`
|
||||
EnableUPNP bool `json:"enable_upnp"`
|
||||
Label string `json:"label"`
|
||||
Description string `json:"description"`
|
||||
Position bool `json:"position"`
|
||||
PortMap string `json:"port_map"`
|
||||
CpuShares int64 `json:"cpu_shares"`
|
||||
Memory int64 `json:"memory"`
|
||||
Restart string `json:"restart"`
|
||||
EnableUPNP bool `json:"enable_upnp"`
|
||||
Label string `json:"label"`
|
||||
Description string `json:"description"`
|
||||
Position bool `json:"position"`
|
||||
HostName string `json:"host_name"`
|
||||
Privileged bool `json:"privileged"`
|
||||
CapAdd []string `json:"cap_add"`
|
||||
Cmd []string `json:"cmd"`
|
||||
}
|
||||
|
||||
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"`
|
||||
}
|
||||
19
model/person.go
Normal file
19
model/person.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
type PersionModel struct {
|
||||
Token string `json:"token"`
|
||||
Ips []string `json:"ips"`
|
||||
CreatedAt time.Time `gorm:"<-:create;autoCreateTime" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"autoUpdateTime" 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"` //对接标识
|
||||
}
|
||||
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"`
|
||||
}
|
||||
@@ -15,13 +15,17 @@ type UserModel struct {
|
||||
Head string
|
||||
Email string
|
||||
Description string
|
||||
Initialized bool
|
||||
}
|
||||
|
||||
//服务配置
|
||||
type ServerModel struct {
|
||||
HttpPort string
|
||||
RunMode string
|
||||
ServerApi string
|
||||
HttpPort string
|
||||
RunMode string
|
||||
ServerApi string
|
||||
LockAccount bool
|
||||
Handshake string
|
||||
Token string
|
||||
}
|
||||
|
||||
//服务配置
|
||||
@@ -62,4 +66,11 @@ type RedisModel struct {
|
||||
type SystemConfig struct {
|
||||
ConfigStr string `json:"config_str"`
|
||||
WidgetList string `json:"widget_list"`
|
||||
ConfigPath string `json:"config_path"`
|
||||
SyncPort string `json:"sync_port"`
|
||||
SyncKey string `json:"sync_key"`
|
||||
}
|
||||
|
||||
type CasaOSGlobalVariables struct {
|
||||
AppChange bool
|
||||
}
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
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"`
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
type Path struct {
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
IsDir bool `json:"is_dir"`
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
IsDir bool `json:"is_dir"`
|
||||
Date time.Time `json:"date"`
|
||||
}
|
||||
|
||||
11
pkg/cache/cache.go
vendored
Normal file
11
pkg/cache/cache.go
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/patrickmn/go-cache"
|
||||
)
|
||||
|
||||
func Init() *cache.Cache {
|
||||
return cache.New(5*time.Minute, 60*time.Second)
|
||||
}
|
||||
@@ -2,14 +2,15 @@ package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/go-ini/ini"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/go-ini/ini"
|
||||
)
|
||||
|
||||
//系统配置
|
||||
@@ -32,6 +33,8 @@ var ServerInfo = &model.ServerModel{}
|
||||
|
||||
var SystemConfigInfo = &model.SystemConfig{}
|
||||
|
||||
var CasaOSGlobalVariables = &model.CasaOSGlobalVariables{}
|
||||
|
||||
var Cfg *ini.File
|
||||
|
||||
//初始化设置,获取系统的部分信息。
|
||||
@@ -55,6 +58,7 @@ func InitSetup(config string) {
|
||||
mapTo("redis", RedisInfo)
|
||||
mapTo("server", ServerInfo)
|
||||
mapTo("system", SystemConfigInfo)
|
||||
SystemConfigInfo.ConfigPath = configDir
|
||||
// AppInfo.ProjectPath = getCurrentDirectory() //os.Getwd()
|
||||
|
||||
}
|
||||
|
||||
@@ -4,30 +4,35 @@ import (
|
||||
"bytes"
|
||||
json2 "encoding/json"
|
||||
"fmt"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/crypto/ssh"
|
||||
"io"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
func NewSshClient() (*ssh.Client, error) {
|
||||
func NewSshClient(user, password string) (*ssh.Client, error) {
|
||||
|
||||
// connet to ssh
|
||||
// addr = fmt.Sprintf("%s:%d", host, port)
|
||||
|
||||
config := &ssh.ClientConfig{
|
||||
Timeout: time.Second * 5,
|
||||
User: "root",
|
||||
User: user,
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
//HostKeyCallback: ,
|
||||
//HostKeyCallback: hostKeyCallBackFunc(h.Host),
|
||||
}
|
||||
//if h.Type == "password" {
|
||||
config.Auth = []ssh.AuthMethod{ssh.Password("123456")}
|
||||
config.Auth = []ssh.AuthMethod{ssh.Password(password)}
|
||||
//} else {
|
||||
// config.Auth = []ssh.AuthMethod{publicKeyAuthFunc(h.Key)}
|
||||
//}
|
||||
addr := fmt.Sprintf("%s:%d", "192.168.2.142", 22)
|
||||
addr := fmt.Sprintf("%s:%d", "127.0.0.1", 22)
|
||||
c, err := ssh.Dial("tcp", addr, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -98,6 +103,98 @@ const (
|
||||
wsMsgResize = "resize"
|
||||
)
|
||||
|
||||
//ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin
|
||||
func ReceiveWsMsgUser(wsConn *websocket.Conn, logBuff *bytes.Buffer) string {
|
||||
//tells other go routine quit
|
||||
username := ""
|
||||
for {
|
||||
|
||||
//read websocket msg
|
||||
_, wsData, err := wsConn.ReadMessage()
|
||||
if err != nil {
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
msgObj := wsMsg{}
|
||||
if err := json2.Unmarshal(wsData, &msgObj); err != nil {
|
||||
msgObj.Type = "cmd"
|
||||
msgObj.Cmd = string(wsData)
|
||||
}
|
||||
//if err := json.Unmarshal(wsData, &msgObj); err != nil {
|
||||
// logrus.WithError(err).WithField("wsData", string(wsData)).Error("unmarshal websocket message failed")
|
||||
//}
|
||||
switch msgObj.Type {
|
||||
case wsMsgCmd:
|
||||
//handle xterm.js stdin
|
||||
//decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
|
||||
decodeBytes := []byte(msgObj.Cmd)
|
||||
if msgObj.Cmd == "\u007f" {
|
||||
if len(username) == 0 {
|
||||
continue
|
||||
}
|
||||
wsConn.WriteMessage(websocket.TextMessage, []byte("\b\x1b[K"))
|
||||
username = username[:len(username)-1]
|
||||
continue
|
||||
}
|
||||
if msgObj.Cmd == "\r" {
|
||||
return username
|
||||
}
|
||||
username += msgObj.Cmd
|
||||
|
||||
if err := wsConn.WriteMessage(websocket.TextMessage, decodeBytes); err != nil {
|
||||
logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed")
|
||||
}
|
||||
//write input cmd to log buffer
|
||||
if _, err := logBuff.Write(decodeBytes); err != nil {
|
||||
logrus.WithError(err).Error("write received cmd into log buffer failed")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func ReceiveWsMsgPassword(wsConn *websocket.Conn, logBuff *bytes.Buffer) string {
|
||||
//tells other go routine quit
|
||||
password := ""
|
||||
for {
|
||||
|
||||
//read websocket msg
|
||||
_, wsData, err := wsConn.ReadMessage()
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("reading webSocket message failed")
|
||||
return ""
|
||||
}
|
||||
|
||||
msgObj := wsMsg{}
|
||||
if err := json2.Unmarshal(wsData, &msgObj); err != nil {
|
||||
msgObj.Type = "cmd"
|
||||
msgObj.Cmd = string(wsData)
|
||||
}
|
||||
//if err := json.Unmarshal(wsData, &msgObj); err != nil {
|
||||
// logrus.WithError(err).WithField("wsData", string(wsData)).Error("unmarshal websocket message failed")
|
||||
//}
|
||||
switch msgObj.Type {
|
||||
case wsMsgCmd:
|
||||
//handle xterm.js stdin
|
||||
//decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
|
||||
if msgObj.Cmd == "\r" {
|
||||
return password
|
||||
}
|
||||
|
||||
if msgObj.Cmd == "\u007f" {
|
||||
if len(password) == 0 {
|
||||
continue
|
||||
}
|
||||
password = password[:len(password)-1]
|
||||
continue
|
||||
}
|
||||
password += msgObj.Cmd
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin
|
||||
func (ssConn *SshConn) ReceiveWsMsg(wsConn *websocket.Conn, logBuff *bytes.Buffer, exitCh chan bool) {
|
||||
//tells other go routine quit
|
||||
@@ -187,6 +284,64 @@ func flushComboOutput(w *wsBufferWriter, wsConn *websocket.Conn) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin
|
||||
func (ssConn *SshConn) Login(wsConn *websocket.Conn, logBuff *bytes.Buffer, exitCh chan bool) {
|
||||
//tells other go routine quit
|
||||
defer setQuit(exitCh)
|
||||
for {
|
||||
select {
|
||||
case <-exitCh:
|
||||
return
|
||||
default:
|
||||
//read websocket msg
|
||||
_, wsData, err := wsConn.ReadMessage()
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("reading webSocket message failed")
|
||||
return
|
||||
}
|
||||
//unmashal bytes into struct
|
||||
//msgObj := wsMsg{
|
||||
// Type: "cmd",
|
||||
// Cmd: "",
|
||||
// Rows: 50,
|
||||
// Cols: 180,
|
||||
//}
|
||||
msgObj := wsMsg{}
|
||||
if err := json2.Unmarshal(wsData, &msgObj); err != nil {
|
||||
msgObj.Type = "cmd"
|
||||
msgObj.Cmd = string(wsData)
|
||||
}
|
||||
//if err := json.Unmarshal(wsData, &msgObj); err != nil {
|
||||
// logrus.WithError(err).WithField("wsData", string(wsData)).Error("unmarshal websocket message failed")
|
||||
//}
|
||||
switch msgObj.Type {
|
||||
|
||||
case wsMsgResize:
|
||||
//handle xterm.js size change
|
||||
if msgObj.Cols > 0 && msgObj.Rows > 0 {
|
||||
if err := ssConn.Session.WindowChange(msgObj.Rows, msgObj.Cols); err != nil {
|
||||
logrus.WithError(err).Error("ssh pty change windows size failed")
|
||||
}
|
||||
}
|
||||
case wsMsgCmd:
|
||||
//handle xterm.js stdin
|
||||
//decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
|
||||
decodeBytes := []byte(msgObj.Cmd)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("websock cmd string base64 decoding failed")
|
||||
}
|
||||
if _, err := ssConn.StdinPipe.Write(decodeBytes); err != nil {
|
||||
logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed")
|
||||
}
|
||||
//write input cmd to log buffer
|
||||
if _, err := logBuff.Write(decodeBytes); err != nil {
|
||||
logrus.WithError(err).Error("write received cmd into log buffer failed")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
func (ssConn *SshConn) SessionWait(quitChan chan bool) {
|
||||
if err := ssConn.Session.Wait(); err != nil {
|
||||
logrus.WithError(err).Error("ssh session wait failed")
|
||||
@@ -241,7 +396,7 @@ func WsReaderCopy(reader *websocket.Conn, writer io.Writer) {
|
||||
if err = json2.Unmarshal(p, &msgObj); err != nil {
|
||||
writer.Write(p)
|
||||
} else if msgObj.Type == wsMsgResize {
|
||||
writer.Write([]byte("stty rows " + strconv.Itoa(msgObj.Rows) + " && stty cols " + strconv.Itoa(msgObj.Cols) + " \r" ))
|
||||
writer.Write([]byte("stty rows " + strconv.Itoa(msgObj.Rows) + " && stty cols " + strconv.Itoa(msgObj.Cols) + " \r"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
package docker
|
||||
|
||||
import "strings"
|
||||
|
||||
func GetDir(id, envName string) string {
|
||||
var path string
|
||||
switch envName {
|
||||
case "/config":
|
||||
path = "/oasis/app_data/" + id + "/"
|
||||
default:
|
||||
//path = "/media"
|
||||
|
||||
if strings.Contains(envName, "$AppID") && len(id) > 0 {
|
||||
return strings.ReplaceAll(envName, "$AppID", id)
|
||||
}
|
||||
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"
|
||||
)
|
||||
|
||||
|
||||
func GetGithubClient() *github.Client {
|
||||
ctx := context.Background()
|
||||
ts := oauth2.StaticTokenSource(
|
||||
|
||||
@@ -2,11 +2,12 @@ package sqlite
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
var gdb *gorm.DB
|
||||
@@ -30,7 +31,7 @@ func GetDb(projectPath string) *gorm.DB {
|
||||
return nil
|
||||
}
|
||||
gdb = db
|
||||
err = db.AutoMigrate(&model2.TaskDBModel{}, &model2.AppNotify{}, &model2.AppListDBModel{})
|
||||
err = db.AutoMigrate(&model2.TaskDBModel{}, &model2.AppNotify{}, &model2.AppListDBModel{}, &model2.SerialDisk{})
|
||||
if err != nil {
|
||||
fmt.Println("检查和创建数据库出错", err)
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func GetCtrlUrl(host,device string) string {
|
||||
func GetCtrlUrl(host, device string) string {
|
||||
request := ctrlUrlRequest(host, device)
|
||||
response, _ := http.DefaultClient.Do(request)
|
||||
resultBody, _ := ioutil.ReadAll(response.Body)
|
||||
@@ -86,4 +86,4 @@ func resolve(resultStr string) string {
|
||||
}
|
||||
}
|
||||
return controlURL
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,21 +22,21 @@ func send() (string, error) {
|
||||
"ST: urn:schemas-upnp-org:service:WANIPConnection:1\r\n" +
|
||||
"MAN: \"ssdp:discover\"\r\n" + "MX: 3\r\n\r\n"
|
||||
var conn *net.UDPConn
|
||||
remotAddr, err := net.ResolveUDPAddr("udp", "239.255.255.250:1900")
|
||||
remoteAddr, err := net.ResolveUDPAddr("udp", "239.255.255.250:1900")
|
||||
if err != nil {
|
||||
return "", errors.New("组播地址格式不正确")
|
||||
}
|
||||
locaAddr, err := net.ResolveUDPAddr("udp", ip_helper2.GetLoclIp()+":")
|
||||
localAddr, err := net.ResolveUDPAddr("udp", ip_helper2.GetLoclIp()+":")
|
||||
|
||||
if err != nil {
|
||||
return "", errors.New("本地ip地址格式不正确")
|
||||
}
|
||||
conn, err = net.ListenUDP("udp", locaAddr)
|
||||
conn, err = net.ListenUDP("udp", localAddr)
|
||||
defer conn.Close()
|
||||
if err != nil {
|
||||
return "", errors.New("监听udp出错")
|
||||
}
|
||||
_, err = conn.WriteToUDP([]byte(str), remotAddr)
|
||||
_, err = conn.WriteToUDP([]byte(str), remoteAddr)
|
||||
if err != nil {
|
||||
return "", errors.New("发送msg到组播地址出错")
|
||||
}
|
||||
|
||||
@@ -5,4 +5,4 @@ import "testing"
|
||||
func TestGateway(t *testing.T) {
|
||||
|
||||
Gateway()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,40 +2,37 @@ package upnp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/pkg/errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
//
|
||||
////添加一个端口映射
|
||||
func (n *Upnp)AddPortMapping(localPort, remotePort int, protocol string) (err error) {
|
||||
defer func(err error) {
|
||||
func (n *Upnp) AddPortMapping(localPort, remotePort int, protocol string) (err error) {
|
||||
defer func() {
|
||||
if errTemp := recover(); errTemp != nil {
|
||||
//log.Println("upnp模块报错了", errTemp)
|
||||
err = errTemp.(error)
|
||||
loger2.NewOLoger().Error("upnp模块报错了", errTemp)
|
||||
}
|
||||
}(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
|
||||
} else {
|
||||
return errors.New("添加一个端口映射失败")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func addSend(localPort, remotePort int, protocol, host, ctrUrl,localHost string) bool {
|
||||
request := addRequest(localPort, remotePort, protocol, host, ctrUrl,localHost)
|
||||
func addSend(localPort, remotePort int, protocol, host, ctrUrl, localHost string) bool {
|
||||
request := addRequest(localPort, remotePort, protocol, host, ctrUrl, localHost)
|
||||
response, _ := http.DefaultClient.Do(request)
|
||||
defer response.Body.Close()
|
||||
//resultBody, _ := ioutil.ReadAll(response.Body)
|
||||
//fmt.Println(string(resultBody))
|
||||
if response.StatusCode == 200 {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
return response.StatusCode == 200
|
||||
}
|
||||
|
||||
type Node struct {
|
||||
@@ -45,7 +42,7 @@ type Node struct {
|
||||
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.Set("Accept", "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2")
|
||||
@@ -109,27 +106,25 @@ func (n *Node) BuildXML() string {
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func (n *Upnp)DelPortMapping(remotePort int, protocol string) bool {
|
||||
issuccess := delSendSend(remotePort, protocol,n.GatewayHost,n.CtrlUrl)
|
||||
if issuccess {
|
||||
func (n *Upnp) DelPortMapping(remotePort int, protocol string) bool {
|
||||
isSuccess := delSendSend(remotePort, protocol, n.GatewayHost, n.CtrlUrl)
|
||||
if isSuccess {
|
||||
//this.MappingPort.delMapping(remotePort, protocol)
|
||||
//fmt.Println("删除了一个端口映射: remote:", remotePort)
|
||||
}
|
||||
return issuccess
|
||||
return isSuccess
|
||||
}
|
||||
|
||||
func delSendSend(remotePort int, protocol,host,ctlUrl string) bool {
|
||||
delrequest := delbuildRequest(remotePort, protocol,host,ctlUrl)
|
||||
func delSendSend(remotePort int, protocol, host, ctlUrl string) bool {
|
||||
delrequest := delbuildRequest(remotePort, protocol, host, ctlUrl)
|
||||
response, _ := http.DefaultClient.Do(delrequest)
|
||||
//resultBody, _ := ioutil.ReadAll(response.Body)
|
||||
defer response.Body.Close()
|
||||
if response.StatusCode == 200 {
|
||||
// log.Println(string(resultBody))
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
return response.StatusCode == 200
|
||||
}
|
||||
func delbuildRequest(remotePort int, protocol,host,ctlUrl string) *http.Request {
|
||||
|
||||
func delbuildRequest(remotePort int, protocol, host, ctlUrl string) *http.Request {
|
||||
//请求头
|
||||
header := http.Header{}
|
||||
header.Set("Accept", "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2")
|
||||
@@ -160,4 +155,4 @@ func delbuildRequest(remotePort int, protocol,host,ctlUrl string) *http.Request
|
||||
request.Header = header
|
||||
request.Header.Set("Content-Length", strconv.Itoa(len([]byte(bodyStr))))
|
||||
return request
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,10 +7,10 @@ import (
|
||||
|
||||
type Upnp struct {
|
||||
LocalHost string `json:"local_host"`
|
||||
GatewayName string `json:"gateway_name"` //网关名称
|
||||
GatewayHost string `json:"gateway_host"` //网关ip和端口
|
||||
GatewayName string `json:"gateway_name"` //网关名称
|
||||
GatewayHost string `json:"gateway_host"` //网关ip和端口
|
||||
DeviceDescUrl string `json:"device_desc_url"` //设备描述url
|
||||
CtrlUrl string `json:"ctrl_url"` //控制请求url
|
||||
CtrlUrl string `json:"ctrl_url"` //控制请求url
|
||||
}
|
||||
|
||||
func Testaaa() {
|
||||
@@ -23,4 +23,3 @@ func Testaaa() {
|
||||
fmt.Println("gateway ip address: ", upnpMan.Gateway.Host)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,4 +6,4 @@ import (
|
||||
|
||||
func TestTestaaa(t *testing.T) {
|
||||
(Testaaa())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@ package command
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os/exec"
|
||||
"time"
|
||||
)
|
||||
|
||||
func OnlyExec(cmdStr string) {
|
||||
@@ -75,6 +77,7 @@ func ExecResultStr(cmdStr string) string {
|
||||
func ExecLSBLK() []byte {
|
||||
output, err := exec.Command("lsblk", "-O", "-J", "-b").Output()
|
||||
if err != nil {
|
||||
fmt.Println("lsblk", err)
|
||||
return nil
|
||||
}
|
||||
return output
|
||||
@@ -84,7 +87,26 @@ func ExecLSBLK() []byte {
|
||||
func ExecLSBLKByPath(path string) []byte {
|
||||
output, err := exec.Command("lsblk", path, "-O", "-J", "-b").Output()
|
||||
if err != nil {
|
||||
fmt.Println("lsblk", err)
|
||||
return nil
|
||||
}
|
||||
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", ""))
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package file
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"mime/multipart"
|
||||
"os"
|
||||
@@ -50,6 +51,7 @@ func MkDir(src string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
os.Chmod(src, 0777)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -145,3 +147,81 @@ func IsNotExistCreateFile(src string) error {
|
||||
|
||||
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
|
||||
|
||||
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())
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
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 := 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
|
||||
}
|
||||
|
||||
176
pkg/utils/file/reader.go
Normal file
176
pkg/utils/file/reader.go
Normal file
@@ -0,0 +1,176 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
var (
|
||||
buffSize = 1 << 20
|
||||
)
|
||||
|
||||
// ReadLineFromEnd --
|
||||
type ReadLineFromEnd struct {
|
||||
f *os.File
|
||||
|
||||
fileSize int
|
||||
bwr *bytes.Buffer
|
||||
lineBuff []byte
|
||||
swapBuff []byte
|
||||
|
||||
isFirst bool
|
||||
}
|
||||
|
||||
// NewReadLineFromEnd --
|
||||
func NewReadLineFromEnd(name string) (rd *ReadLineFromEnd, err error) {
|
||||
f, err := os.Open(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
info, err := f.Stat()
|
||||
if info.IsDir() {
|
||||
return nil, fmt.Errorf("not file")
|
||||
}
|
||||
fileSize := int(info.Size())
|
||||
rd = &ReadLineFromEnd{
|
||||
f: f,
|
||||
fileSize: fileSize,
|
||||
bwr: bytes.NewBuffer([]byte{}),
|
||||
lineBuff: make([]byte, 0),
|
||||
swapBuff: make([]byte, buffSize),
|
||||
isFirst: true,
|
||||
}
|
||||
return rd, nil
|
||||
}
|
||||
|
||||
// ReadLine 结尾包含'\n'
|
||||
func (c *ReadLineFromEnd) ReadLine() (line []byte, err error) {
|
||||
var ok bool
|
||||
for {
|
||||
ok, err = c.buff()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ok {
|
||||
break
|
||||
}
|
||||
}
|
||||
line, err = c.bwr.ReadBytes('\n')
|
||||
if err == io.EOF && c.fileSize > 0 {
|
||||
err = nil
|
||||
}
|
||||
return line, err
|
||||
}
|
||||
|
||||
// Close --
|
||||
func (c *ReadLineFromEnd) Close() (err error) {
|
||||
return c.f.Close()
|
||||
}
|
||||
|
||||
func (c *ReadLineFromEnd) buff() (ok bool, err error) {
|
||||
if c.fileSize == 0 {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
if c.bwr.Len() >= buffSize {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
offset := 0
|
||||
if c.fileSize > buffSize {
|
||||
offset = c.fileSize - buffSize
|
||||
}
|
||||
_, err = c.f.Seek(int64(offset), 0)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
n, err := c.f.Read(c.swapBuff)
|
||||
if err != nil && err != io.EOF {
|
||||
return false, err
|
||||
}
|
||||
if c.fileSize < n {
|
||||
n = c.fileSize
|
||||
}
|
||||
if n == 0 {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
for {
|
||||
m := bytes.LastIndex(c.swapBuff[:n], []byte{'\n'})
|
||||
if m == -1 {
|
||||
break
|
||||
}
|
||||
if m < n-1 {
|
||||
err = c.writeLine(c.swapBuff[m+1 : n])
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
ok = true
|
||||
} else if m == n-1 && !c.isFirst {
|
||||
err = c.writeLine(nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
ok = true
|
||||
}
|
||||
n = m
|
||||
if n == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if n > 0 {
|
||||
reverseBytes(c.swapBuff[:n])
|
||||
c.lineBuff = append(c.lineBuff, c.swapBuff[:n]...)
|
||||
}
|
||||
if offset == 0 {
|
||||
err = c.writeLine(nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
ok = true
|
||||
}
|
||||
c.fileSize = offset
|
||||
if c.isFirst {
|
||||
c.isFirst = false
|
||||
}
|
||||
return ok, nil
|
||||
}
|
||||
|
||||
func (c *ReadLineFromEnd) writeLine(b []byte) (err error) {
|
||||
if len(b) > 0 {
|
||||
_, err = c.bwr.Write(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(c.lineBuff) > 0 {
|
||||
reverseBytes(c.lineBuff)
|
||||
_, err = c.bwr.Write(c.lineBuff)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.lineBuff = c.lineBuff[:0]
|
||||
}
|
||||
_, err = c.bwr.Write([]byte{'\n'})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func reverseBytes(b []byte) {
|
||||
n := len(b)
|
||||
if n <= 1 {
|
||||
return
|
||||
}
|
||||
for i := 0; i < n; i++ {
|
||||
k := n - 1
|
||||
if k != i {
|
||||
b[i], b[k] = b[k], b[i]
|
||||
}
|
||||
n--
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,13 @@ package httper
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
"github.com/tidwall/gjson"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
//发送GET请求
|
||||
@@ -52,10 +53,13 @@ func Get(url string, head map[string]string) (response string) {
|
||||
//发送POST请求
|
||||
//url:请求地址,data:POST请求提交的数据,contentType:请求体格式,如:application/json
|
||||
//content:请求放回的内容
|
||||
func Post(url string, data interface{}, contentType string) (content string) {
|
||||
jsonStr, _ := json.Marshal(data)
|
||||
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
|
||||
func Post(url string, data []byte, contentType string, head map[string]string) (content string) {
|
||||
|
||||
req, err := http.NewRequest("POST", url, bytes.NewBuffer(data))
|
||||
req.Header.Add("content-type", contentType)
|
||||
for k, v := range head {
|
||||
req.Header.Add(k, v)
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -2,11 +2,12 @@ package jwt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func JWT(swagHandler gin.HandlerFunc) gin.HandlerFunc {
|
||||
|
||||
@@ -2,13 +2,13 @@ package loger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
file2 "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
file2 "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||
)
|
||||
|
||||
//定义一个int的别名
|
||||
@@ -20,6 +20,7 @@ type OLog interface {
|
||||
Warn(v ...interface{})
|
||||
Error(v ...interface{})
|
||||
Fatal(v ...interface{})
|
||||
Path() string
|
||||
}
|
||||
|
||||
type oLog struct {
|
||||
@@ -47,9 +48,8 @@ const (
|
||||
func LogSetup() {
|
||||
var err error
|
||||
filePath := fmt.Sprintf("%s", config.AppInfo.LogSavePath)
|
||||
fileName := fmt.Sprintf("%s%s.%s",
|
||||
fileName := fmt.Sprintf("%s.%s",
|
||||
config.AppInfo.LogSaveName,
|
||||
time.Now().Format(config.AppInfo.DateStrFormat),
|
||||
config.AppInfo.LogFileExt,
|
||||
)
|
||||
F, err = file2.MustOpen(fileName, filePath)
|
||||
@@ -60,7 +60,14 @@ func LogSetup() {
|
||||
logger = log.New(F, DefaultPrefix, log.LstdFlags)
|
||||
|
||||
}
|
||||
|
||||
func (o *oLog) Path() string {
|
||||
filePath := fmt.Sprintf("%s", config.AppInfo.LogSavePath)
|
||||
fileName := fmt.Sprintf("%s.%s",
|
||||
config.AppInfo.LogSaveName,
|
||||
config.AppInfo.LogFileExt,
|
||||
)
|
||||
return filePath + fileName
|
||||
}
|
||||
func (o *oLog) Debug(v ...interface{}) {
|
||||
setPrefix(DEBUG)
|
||||
logger.Println(v)
|
||||
|
||||
@@ -7,14 +7,27 @@ const (
|
||||
ERROR_AUTH_TOKEN = 401
|
||||
|
||||
//user
|
||||
PWD_INVALID = 10001
|
||||
PWD_INVALID = 10001
|
||||
PWD_IS_EMPTY = 10002
|
||||
|
||||
PWD_INVALID_OLD = 10003
|
||||
ACCOUNT_LOCK = 10004
|
||||
//system
|
||||
DIR_ALREADY_EXISTS = 20001
|
||||
DIR_ALREADY_EXISTS = 20001
|
||||
FILE_ALREADY_EXISTS = 20002
|
||||
FILE_OR_DIR_EXISTS = 20003
|
||||
PORT_IS_OCCUPIED = 20004
|
||||
|
||||
//zerotier
|
||||
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
|
||||
UNINSTALL_APP_ERROR = 50001
|
||||
PULL_IMAGE_ERROR = 50002
|
||||
@@ -23,6 +36,7 @@ const (
|
||||
//file
|
||||
FILE_DOES_NOT_EXIST = 60001
|
||||
FILE_READ_ERROR = 60002
|
||||
FILE_DELETE_ERROR = 60003
|
||||
|
||||
//shortcuts
|
||||
SHORTCUTS_URL_ERROR = 70001
|
||||
@@ -31,29 +45,42 @@ const (
|
||||
var MsgFlags = map[int]string{
|
||||
SUCCESS: "ok",
|
||||
ERROR: "fail",
|
||||
INVALID_PARAMS: "Invalid params",
|
||||
ERROR_AUTH_TOKEN: "error auth token",
|
||||
INVALID_PARAMS: "Parameters Error",
|
||||
ERROR_AUTH_TOKEN: "Error auth token",
|
||||
|
||||
//user
|
||||
PWD_INVALID: "Password invalid",
|
||||
PWD_INVALID: "Invalid password",
|
||||
PWD_IS_EMPTY: "Password is empty",
|
||||
PWD_INVALID_OLD: "Invalid old password",
|
||||
ACCOUNT_LOCK: "Account is locked",
|
||||
|
||||
//system
|
||||
DIR_ALREADY_EXISTS: "Directory already exists",
|
||||
|
||||
DIR_ALREADY_EXISTS: "Folder already exists",
|
||||
FILE_ALREADY_EXISTS: "File already exists",
|
||||
FILE_OR_DIR_EXISTS: "File or folder already exists",
|
||||
PORT_IS_OCCUPIED: "Port is occupied",
|
||||
|
||||
//zerotier
|
||||
GET_TOKEN_ERROR: "Get token error,Please log in to zerotier's official website to confirm whether the account is available",
|
||||
|
||||
//app
|
||||
UNINSTALL_APP_ERROR: "uninstall app error",
|
||||
PULL_IMAGE_ERROR: "pull image error",
|
||||
DEVICE_NOT_EXIST: "device not exist",
|
||||
UNINSTALL_APP_ERROR: "Error uninstalling app",
|
||||
PULL_IMAGE_ERROR: "Error pulling image",
|
||||
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",
|
||||
SHORTCUTS_URL_ERROR: "url error",
|
||||
FILE_READ_ERROR: "File read error",
|
||||
FILE_DELETE_ERROR: "Delete error",
|
||||
SHORTCUTS_URL_ERROR: "URL error",
|
||||
}
|
||||
|
||||
//获取错误信息
|
||||
|
||||
@@ -47,6 +47,7 @@ func IsPortAvailable(port int, t string) bool {
|
||||
uc, err := net.ListenUDP("udp", sadd)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
return false
|
||||
} else {
|
||||
defer uc.Close()
|
||||
|
||||
@@ -6,5 +6,5 @@ import (
|
||||
)
|
||||
|
||||
func TestRandomString(t *testing.T) {
|
||||
fmt.Println(RandomString(6,true))
|
||||
}
|
||||
fmt.Println(RandomString(6, true))
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package sort
|
||||
|
||||
import (
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"sort"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
)
|
||||
|
||||
// 数据集类型, 与上一篇排序文章(多字段单独排序)比较, less字段的数据类型不再是 func(p1, p2 *Change) bool
|
||||
|
||||
@@ -2,13 +2,14 @@ package version
|
||||
|
||||
import (
|
||||
json2 "encoding/json"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
||||
"github.com/IceWhaleTech/CasaOS/types"
|
||||
"github.com/tidwall/gjson"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func IsNeedUpdate() (bool, model.Version) {
|
||||
@@ -35,3 +36,23 @@ func IsNeedUpdate() (bool, model.Version) {
|
||||
}
|
||||
return false, version
|
||||
}
|
||||
|
||||
//a版本大于b版本
|
||||
func VersionCompared(a string, b string) bool {
|
||||
v1 := strings.Split(a, ".")
|
||||
v2 := strings.Split(b, ".")
|
||||
for len(v1) < len(v2) {
|
||||
v1 = append(v1, "0")
|
||||
}
|
||||
for len(v2) < len(v1) {
|
||||
v2 = append(v2, "0")
|
||||
}
|
||||
for i := 0; i < len(v1); i++ {
|
||||
a, _ := strconv.Atoi(v1[i])
|
||||
b, _ := strconv.Atoi(v2[i])
|
||||
if a > b {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build doc
|
||||
// +build doc
|
||||
|
||||
package route
|
||||
@@ -5,9 +6,10 @@ package route
|
||||
import (
|
||||
_ "github.com/IceWhaleTech/CasaOS/docs"
|
||||
ginSwagger "github.com/swaggo/gin-swagger"
|
||||
"github.com/swaggo/gin-swagger/swaggerFiles"
|
||||
swaggerFiles "github.com/swaggo/gin-swagger/swaggerFiles"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// swagHandler = ginSwagger.WrapHandler(swaggerFiles.Handler)
|
||||
swagHandler = ginSwagger.WrapHandler(swaggerFiles.Handler)
|
||||
}
|
||||
|
||||
246
route/init.go
Normal file
246
route/init.go
Normal file
@@ -0,0 +1,246 @@
|
||||
package route
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"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_9()
|
||||
|
||||
}
|
||||
|
||||
var syncIsExistence = false
|
||||
|
||||
func installSyncthing(appId string) {
|
||||
|
||||
var appInfo model.ServerAppList
|
||||
m := model.CustomizationPostData{}
|
||||
var dockerImage string
|
||||
var dockerImageVersion string
|
||||
appInfo = service.MyService.OAPI().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_9() {
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -8,15 +8,18 @@ import (
|
||||
jwt2 "github.com/IceWhaleTech/CasaOS/pkg/utils/jwt"
|
||||
v1 "github.com/IceWhaleTech/CasaOS/route/v1"
|
||||
"github.com/IceWhaleTech/CasaOS/web"
|
||||
"github.com/gin-contrib/gzip"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var swagHandler gin.HandlerFunc
|
||||
var OnlineDemo bool = false
|
||||
|
||||
func InitRouter(swagHandler gin.HandlerFunc) *gin.Engine {
|
||||
func InitRouter() *gin.Engine {
|
||||
|
||||
r := gin.Default()
|
||||
r.Use(middleware.Cors())
|
||||
r.Use(gzip.Gzip(gzip.DefaultCompression))
|
||||
gin.SetMode(config.ServerInfo.RunMode)
|
||||
|
||||
r.StaticFS("/ui", http.FS(web.Static))
|
||||
@@ -27,10 +30,16 @@ func InitRouter(swagHandler gin.HandlerFunc) *gin.Engine {
|
||||
if swagHandler != nil {
|
||||
r.GET("/swagger/*any", swagHandler)
|
||||
}
|
||||
//登录
|
||||
|
||||
r.POST("/v1/user/login", v1.Login)
|
||||
|
||||
r.GET("/debug", v1.GetSystemConfigDebug)
|
||||
r.GET("/v1/guide/check", v1.GetGuideCheck)
|
||||
|
||||
r.GET("/v1/debug", v1.GetSystemConfigDebug)
|
||||
//set user
|
||||
r.POST("/v1/user/setusernamepwd", v1.Set_Name_Pwd)
|
||||
//get user info
|
||||
r.GET("/v1/user/info", v1.UserInfo)
|
||||
|
||||
v1Group := r.Group("/v1")
|
||||
|
||||
@@ -39,8 +48,7 @@ func InitRouter(swagHandler gin.HandlerFunc) *gin.Engine {
|
||||
v1UserGroup := v1Group.Group("/user")
|
||||
v1UserGroup.Use()
|
||||
{
|
||||
//设置用户
|
||||
v1UserGroup.POST("/setusernamepwd", v1.Set_Name_Pwd)
|
||||
|
||||
//chang head
|
||||
v1UserGroup.POST("/changhead", v1.Up_Load_Head)
|
||||
//chang user name
|
||||
@@ -49,8 +57,7 @@ func InitRouter(swagHandler gin.HandlerFunc) *gin.Engine {
|
||||
v1UserGroup.PUT("/changuserpwd", v1.Chang_User_Pwd)
|
||||
//edit user info
|
||||
v1UserGroup.POST("/changuserinfo", v1.Chang_User_Info)
|
||||
//get user info
|
||||
v1UserGroup.GET("/info", v1.UserInfo)
|
||||
|
||||
}
|
||||
|
||||
v1ZiMaGroup := v1Group.Group("/zima")
|
||||
@@ -65,8 +72,7 @@ func InitRouter(swagHandler gin.HandlerFunc) *gin.Engine {
|
||||
|
||||
//获取网络信息
|
||||
v1ZiMaGroup.GET("/getnetinfo", v1.NetInfo)
|
||||
//获取网络信息
|
||||
v1ZiMaGroup.GET("/getinfo", v1.Info)
|
||||
|
||||
//获取系统信息
|
||||
v1ZiMaGroup.GET("/sysinfo", v1.SysInfo)
|
||||
}
|
||||
@@ -136,6 +142,8 @@ func InitRouter(swagHandler gin.HandlerFunc) *gin.Engine {
|
||||
{
|
||||
//获取我的已安装的列表
|
||||
v1AppGroup.GET("/mylist", v1.MyAppList)
|
||||
//
|
||||
v1AppGroup.GET("/usage", v1.AppUsageList)
|
||||
//app详情
|
||||
v1AppGroup.GET("/appinfo/:id", v1.AppInfo)
|
||||
//获取未安装的列表
|
||||
@@ -171,7 +179,7 @@ func InitRouter(swagHandler gin.HandlerFunc) *gin.Engine {
|
||||
v1AppGroup.GET("/rely/:id/info", v1.ContainerRelyInfo)
|
||||
v1AppGroup.GET("/install/config", v1.GetDockerInstallConfig)
|
||||
//v1AppGroup.POST("/custom/install", v1.CustomInstallApp)
|
||||
|
||||
v1AppGroup.POST("/share", v1.ShareAppFile)
|
||||
}
|
||||
|
||||
v1SysGroup := v1Group.Group("/sys")
|
||||
@@ -183,9 +191,14 @@ func InitRouter(swagHandler gin.HandlerFunc) *gin.Engine {
|
||||
v1SysGroup.GET("/sys", v1.Sys)
|
||||
v1SysGroup.GET("/wsssh", v1.WsSsh)
|
||||
v1SysGroup.GET("/config", v1.GetSystemConfig)
|
||||
v1SysGroup.GET("/error/logs", v1.GetCasaOSErrorLogs)
|
||||
v1SysGroup.POST("/config", v1.PostSetSystemConfig)
|
||||
v1SysGroup.GET("/widget/config", v1.GetWidgetConfig)
|
||||
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)
|
||||
}
|
||||
v1FileGroup := v1Group.Group("/file")
|
||||
v1FileGroup.Use()
|
||||
@@ -195,33 +208,43 @@ func InitRouter(swagHandler gin.HandlerFunc) *gin.Engine {
|
||||
v1FileGroup.GET("/read", v1.GetFilerContent)
|
||||
v1FileGroup.POST("/upload", v1.PostFileUpload)
|
||||
v1FileGroup.GET("/dirpath", v1.DirPath)
|
||||
//创建目录
|
||||
//create folder
|
||||
v1FileGroup.POST("/mkdir", v1.MkdirAll)
|
||||
v1FileGroup.POST("/create", v1.PostCreateFile)
|
||||
|
||||
v1FileGroup.GET("/download", v1.GetDownloadFile)
|
||||
v1FileGroup.POST("/operate", v1.PostOperateFileOrDir)
|
||||
v1FileGroup.DELETE("delete", v1.DeleteFile)
|
||||
//v1FileGroup.GET("/download", v1.UserFileDownloadCommonService)
|
||||
}
|
||||
v1DiskGroup := v1Group.Group("/disk")
|
||||
v1DiskGroup.Use()
|
||||
{
|
||||
//获取磁盘列表
|
||||
v1DiskGroup.GET("/list", v1.GetPlugInDisk)
|
||||
v1DiskGroup.GET("/check", v1.GetDiskCheck)
|
||||
|
||||
v1DiskGroup.GET("/list", v1.GetDiskList)
|
||||
|
||||
//获取磁盘详情
|
||||
v1DiskGroup.GET("/info", v1.GetDiskInfo)
|
||||
|
||||
//格式化磁盘
|
||||
//format storage
|
||||
v1DiskGroup.POST("/format", v1.FormatDisk)
|
||||
|
||||
//添加分区
|
||||
v1DiskGroup.POST("/addpart", v1.AddPartition)
|
||||
// add storage
|
||||
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.DELETE("/delpart", v1.RemovePartition)
|
||||
v1DiskGroup.GET("/usb", v1.GetUSBList)
|
||||
|
||||
}
|
||||
v1ShareGroup := v1Group.Group("/share")
|
||||
@@ -261,6 +284,14 @@ func InitRouter(swagHandler gin.HandlerFunc) *gin.Engine {
|
||||
{
|
||||
v1SearchGroup.GET("/search", v1.GetSearchList)
|
||||
}
|
||||
v1PersonGroup := v1Group.Group("/persion")
|
||||
v1PersonGroup.Use()
|
||||
{
|
||||
v1PersonGroup.GET("/test", v1.PersonTest)
|
||||
}
|
||||
v1Group.GET("/sync/config", v1.GetSyncConfig)
|
||||
v1Group.Any("/syncthing/*url", v1.SyncToSyncthing)
|
||||
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
166
route/v1/app.go
166
route/v1/app.go
@@ -1,15 +1,17 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||
port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/sort"
|
||||
"github.com/IceWhaleTech/CasaOS/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// @Summary 获取远程列表
|
||||
@@ -29,20 +31,34 @@ func AppList(c *gin.Context) {
|
||||
//service.MyService.Docker().DockerContainerCommit("test2")
|
||||
|
||||
index := c.DefaultQuery("index", "1")
|
||||
size := c.DefaultQuery("size", "10")
|
||||
size := c.DefaultQuery("size", "10000")
|
||||
t := c.DefaultQuery("type", "rank")
|
||||
categoryId := c.DefaultQuery("category_id", "0")
|
||||
key := c.DefaultQuery("key", "")
|
||||
list, count := service.MyService.OAPI().GetServerList(index, size, t, categoryId, key)
|
||||
for i := 0; i < len(list); i++ {
|
||||
ct, _ := service.MyService.Docker().DockerListByImage(list[i].Image, list[i].ImageVersion)
|
||||
if ct != nil {
|
||||
list[i].State = ct.State
|
||||
}
|
||||
}
|
||||
data := make(map[string]interface{}, 2)
|
||||
data["count"] = count
|
||||
data["items"] = list
|
||||
language := c.GetHeader("Language")
|
||||
recommend, list, community := service.MyService.OAPI().GetServerList(index, size, t, categoryId, key, language)
|
||||
// for i := 0; i < len(recommend); i++ {
|
||||
// ct, _ := service.MyService.Docker().DockerListByImage(recommend[i].Image, recommend[i].ImageVersion)
|
||||
// if ct != nil {
|
||||
// recommend[i].State = ct.State
|
||||
// }
|
||||
// }
|
||||
// for i := 0; i < len(list); i++ {
|
||||
// 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})
|
||||
}
|
||||
@@ -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})
|
||||
}
|
||||
|
||||
// @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 应用详情
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
@@ -110,51 +138,71 @@ func MyAppList(c *gin.Context) {
|
||||
func AppInfo(c *gin.Context) {
|
||||
|
||||
id := c.Param("id")
|
||||
info := service.MyService.App().GetServerAppInfo(id)
|
||||
language := c.GetHeader("Language")
|
||||
info := service.MyService.OAPI().GetServerAppInfo(id, "", language)
|
||||
if info.NetworkModel != "host" {
|
||||
port, _ := port2.GetAvailablePort("tcp")
|
||||
info.PortMap = uint(port)
|
||||
for i := 0; i < len(info.Configures.TcpPorts); i++ {
|
||||
info.Configures.TcpPorts[i].CommendPort, _ = port2.GetAvailablePort("tcp")
|
||||
}
|
||||
for i := 0; i < len(info.Configures.UdpPorts); i++ {
|
||||
info.Configures.UdpPorts[i].CommendPort, _ = port2.GetAvailablePort("udp")
|
||||
for i := 0; i < len(info.Ports); i++ {
|
||||
if p, _ := strconv.Atoi(info.Ports[i].ContainerPort); port2.IsPortAvailable(p, info.Ports[i].Protocol) {
|
||||
info.Ports[i].CommendPort = strconv.Itoa(p)
|
||||
} else {
|
||||
if info.Ports[i].Protocol == "tcp" {
|
||||
if p, err := port2.GetAvailablePort("tcp"); err == nil {
|
||||
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 {
|
||||
info.PortMap = info.TcpPort
|
||||
}
|
||||
|
||||
for i := 0; i < len(info.Configures.Devices); i++ {
|
||||
if !file.CheckNotExist(info.Configures.Devices[i].ContainerPath) {
|
||||
info.Configures.Devices[i].Path = info.Configures.Devices[i].ContainerPath
|
||||
for i := 0; i < len(info.Ports); i++ {
|
||||
if info.Ports[i].Type == 0 {
|
||||
info.PortMap = info.Ports[i].ContainerPort
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
portOrder := func(c1, c2 *model.Ports) bool {
|
||||
return c1.Type < c2.Type
|
||||
for i := 0; i < len(info.Devices); i++ {
|
||||
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 {
|
||||
return c1.Type < c2.Type
|
||||
}
|
||||
// portOrder := func(c1, c2 *model.Ports) bool {
|
||||
// return c1.Type < c2.Type
|
||||
// }
|
||||
|
||||
volOrder := func(c1, c2 *model.Volume) bool {
|
||||
return c1.Type < c2.Type
|
||||
}
|
||||
// envOrder := func(c1, c2 *model.Envs) bool {
|
||||
// return c1.Type < c2.Type
|
||||
// }
|
||||
|
||||
devOrder := func(c1, c2 *model.Devices) bool {
|
||||
return c1.Type < c2.Type
|
||||
}
|
||||
// volOrder := func(c1, c2 *model.Volume) bool {
|
||||
// return c1.Type < c2.Type
|
||||
// }
|
||||
|
||||
// devOrder := func(c1, c2 *model.Devices) bool {
|
||||
// return c1.Type < c2.Type
|
||||
// }
|
||||
|
||||
//sort
|
||||
if info.NetworkModel != "host" {
|
||||
sort.PortsSort(portOrder).Sort(info.Configures.TcpPorts)
|
||||
sort.PortsSort(portOrder).Sort(info.Configures.UdpPorts)
|
||||
}
|
||||
// if info.NetworkModel != "host" {
|
||||
// sort.PortsSort(portOrder).Sort(info.Configures.TcpPorts)
|
||||
// sort.PortsSort(portOrder).Sort(info.Configures.UdpPorts)
|
||||
// }
|
||||
|
||||
sort.EnvSort(envOrder).Sort(info.Configures.Envs)
|
||||
sort.VolSort(volOrder).Sort(info.Configures.Volumes)
|
||||
sort.DevSort(devOrder).Sort(info.Configures.Devices)
|
||||
// sort.EnvSort(envOrder).Sort(info.Envs)
|
||||
// sort.VolSort(volOrder).Sort(info.Volumes.([]model.PathMap))
|
||||
// sort.DevSort(devOrder).Sort(info.Devices)
|
||||
|
||||
info.MaxMemory = service.MyService.ZiMa().GetMemInfo().Total >> 20
|
||||
|
||||
@@ -176,7 +224,31 @@ func CategoryList(c *gin.Context) {
|
||||
}
|
||||
|
||||
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...)
|
||||
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.OAPI().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/share [post]
|
||||
func AppListResourceUsage() {
|
||||
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ func DDNSAddConfig(c *gin.Context) {
|
||||
})
|
||||
return
|
||||
}
|
||||
var m model2.DDNSUpdataDBModel
|
||||
var m model2.DDNSUpdateDBModel
|
||||
c.Bind(&m)
|
||||
if err := service.MyService.DDNS().SaveConfig(m); err != nil {
|
||||
c.JSON(http.StatusOK,
|
||||
|
||||
451
route/v1/disk.go
451
route/v1/disk.go
@@ -1,65 +1,163 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"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/service"
|
||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/shirou/gopsutil/v3/disk"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// @Summary 获取磁盘列表
|
||||
var diskMap = make(map[string]string)
|
||||
|
||||
// @Summary disk list
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags disk
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @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()
|
||||
//fmt.Println(ls)
|
||||
//dd, _ := disk.Partitions(true)
|
||||
//fmt.Println(dd)
|
||||
//
|
||||
//dir, err := ioutil.ReadDir("/sys/block")
|
||||
//if err != nil {
|
||||
// panic(err)
|
||||
//}
|
||||
//
|
||||
//files := make([]string, 0)
|
||||
//
|
||||
////fmt.Println(regexp.MatchString("sd[a-z]*[0-9]", "sda"))
|
||||
//
|
||||
//for _, f := range dir {
|
||||
// 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))
|
||||
//}
|
||||
disks := []model.Drive{}
|
||||
storage := []model.Storage{}
|
||||
avail := []model.Drive{}
|
||||
for i := 0; i < len(list); i++ {
|
||||
disk := model.Drive{}
|
||||
if list[i].Rota {
|
||||
disk.DiskType = "HDD"
|
||||
} else {
|
||||
disk.DiskType = "SSD"
|
||||
}
|
||||
disk.Serial = list[i].Serial
|
||||
disk.Name = list[i].Name
|
||||
disk.Size = list[i].Size
|
||||
disk.Path = list[i].Path
|
||||
disk.Model = list[i].Model
|
||||
|
||||
lst := service.MyService.Disk().LSBLK()
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: lst})
|
||||
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 == "/" {
|
||||
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
|
||||
// @Accept application/json
|
||||
// @Tags disk
|
||||
@@ -68,7 +166,7 @@ func GetPlugInDisk(c *gin.Context) {
|
||||
// @Router /disk/lists [get]
|
||||
func GetPlugInDisks(c *gin.Context) {
|
||||
|
||||
list := service.MyService.Disk().LSBLK()
|
||||
list := service.MyService.Disk().LSBLK(true)
|
||||
var result []*disk.UsageStat
|
||||
for _, item := range list {
|
||||
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})
|
||||
}
|
||||
|
||||
// @Summary 磁盘详情
|
||||
// @Summary disk detail
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags disk
|
||||
// @Security ApiKeyAuth
|
||||
// @Param path query string true "要获取的磁盘详情 例如/dev/sda"
|
||||
// @Param path query string true "for example /dev/sda"
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /disk/info [get]
|
||||
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})
|
||||
}
|
||||
|
||||
// @Summary 磁盘详情
|
||||
// @Summary format storage
|
||||
// @Produce application/json
|
||||
// @Accept multipart/form-data
|
||||
// @Tags disk
|
||||
// @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"
|
||||
// @Router /disk/format [post]
|
||||
func FormatDisk(c *gin.Context) {
|
||||
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 {
|
||||
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().FormatDisk(path, t)
|
||||
|
||||
//重新挂载
|
||||
|
||||
format := service.MyService.Disk().FormatDisk(path, t)
|
||||
if len(format) == 0 {
|
||||
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)})
|
||||
}
|
||||
|
||||
@@ -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)})
|
||||
}
|
||||
|
||||
// @Summary 添加分区
|
||||
// @Summary add storage
|
||||
// @Produce application/json
|
||||
// @Accept multipart/form-data
|
||||
// @Tags disk
|
||||
// @Security ApiKeyAuth
|
||||
// @Param path formData string true "磁盘路径 例如/dev/sda"
|
||||
// @Param size formData string true "需要分区容量大小(MB)"
|
||||
// @Param num formData string true "磁盘符号"
|
||||
// @Param path formData string true "disk path e.g. /dev/sda"
|
||||
// @Param serial formData string true "serial"
|
||||
// @Param name formData string true "name"
|
||||
// @Param format formData bool true "need format(true)"
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /disk/addpart [post]
|
||||
// @Router /disk/storage [post]
|
||||
func AddPartition(c *gin.Context) {
|
||||
name := c.PostForm("name")
|
||||
path := c.PostForm("path")
|
||||
size, _ := strconv.Atoi(c.DefaultPostForm("size", "0"))
|
||||
num := c.DefaultPostForm("num", "9")
|
||||
if len(path) == 0 {
|
||||
format, _ := strconv.ParseBool(c.PostForm("format"))
|
||||
if len(name) == 0 || len(path) == 0 {
|
||||
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
|
||||
service.MyService.Disk().AddPartition(path, num, uint64(size*1024*2))
|
||||
formatBool := true
|
||||
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)})
|
||||
}
|
||||
|
||||
// @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,8 +2,16 @@ package v1
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
json2 "encoding/json"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/docker"
|
||||
upnp2 "github.com/IceWhaleTech/CasaOS/pkg/upnp"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||
@@ -19,11 +27,8 @@ import (
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/jinzhu/copier"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"github.com/tidwall/gjson"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
var upgrader = websocket.Upgrader{
|
||||
@@ -64,19 +69,46 @@ func DockerTerminal(c *gin.Context) {
|
||||
//打开本机的ssh接口
|
||||
func WsSsh(c *gin.Context) {
|
||||
wsConn, _ := upgrader.Upgrade(c.Writer, c.Request, nil)
|
||||
defer wsConn.Close()
|
||||
cols, _ := strconv.Atoi(c.DefaultQuery("cols", "200"))
|
||||
rows, _ := strconv.Atoi(c.DefaultQuery("rows", "32"))
|
||||
client, _ := docker.NewSshClient()
|
||||
defer client.Close()
|
||||
ssConn, _ := docker.NewSshConn(cols, rows, client)
|
||||
defer ssConn.Close()
|
||||
quitChan := make(chan bool, 3)
|
||||
|
||||
var logBuff = new(bytes.Buffer)
|
||||
quitChan := make(chan bool, 3)
|
||||
user := ""
|
||||
password := ""
|
||||
var login int = 1
|
||||
cols, _ := strconv.Atoi(c.DefaultQuery("cols", "200"))
|
||||
rows, _ := strconv.Atoi(c.DefaultQuery("rows", "32"))
|
||||
var client *ssh.Client
|
||||
for login != 0 {
|
||||
|
||||
var err error
|
||||
|
||||
wsConn.WriteMessage(websocket.TextMessage, []byte("login:"))
|
||||
user = docker.ReceiveWsMsgUser(wsConn, logBuff)
|
||||
wsConn.WriteMessage(websocket.TextMessage, []byte("\r\n\x1b[0m"))
|
||||
wsConn.WriteMessage(websocket.TextMessage, []byte("password:"))
|
||||
password = docker.ReceiveWsMsgPassword(wsConn, logBuff)
|
||||
wsConn.WriteMessage(websocket.TextMessage, []byte("\r\n\x1b[0m"))
|
||||
client, err = docker.NewSshClient(user, password)
|
||||
|
||||
if err != nil && client == nil {
|
||||
wsConn.WriteMessage(websocket.TextMessage, []byte(err.Error()))
|
||||
wsConn.WriteMessage(websocket.TextMessage, []byte("\r\n\x1b[0m"))
|
||||
} else {
|
||||
login = 0
|
||||
}
|
||||
|
||||
}
|
||||
if client != nil {
|
||||
defer client.Close()
|
||||
}
|
||||
|
||||
ssConn, _ := docker.NewSshConn(cols, rows, client)
|
||||
defer ssConn.Close()
|
||||
|
||||
go ssConn.ReceiveWsMsg(wsConn, logBuff, quitChan)
|
||||
go ssConn.SendComboOutput(wsConn, quitChan)
|
||||
go ssConn.SessionWait(quitChan)
|
||||
|
||||
<-quitChan
|
||||
|
||||
}
|
||||
@@ -114,6 +146,7 @@ func SpeedPush(c *gin.Context) {
|
||||
// @Router /app/install/{id} [post]
|
||||
func InstallApp(c *gin.Context) {
|
||||
appId := c.Param("id")
|
||||
language := c.GetHeader("Language")
|
||||
var appInfo model.ServerAppList
|
||||
m := model.CustomizationPostData{}
|
||||
c.BindJSON(&m)
|
||||
@@ -143,7 +176,7 @@ func InstallApp(c *gin.Context) {
|
||||
dockerImageVersion = "latest"
|
||||
}
|
||||
if m.Origin != "custom" {
|
||||
appInfo = service.MyService.App().GetServerAppInfo(appId)
|
||||
appInfo = service.MyService.OAPI().GetServerAppInfo(appId, "", language)
|
||||
|
||||
} else {
|
||||
|
||||
@@ -187,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:仅当容器退出代码非零时重新启动
|
||||
//if len(restart) > 0 {
|
||||
//
|
||||
@@ -209,13 +252,14 @@ func InstallApp(c *gin.Context) {
|
||||
var relyMap = make(map[string]string)
|
||||
go func() {
|
||||
installLog := model2.AppNotify{}
|
||||
installLog.CustomId = id
|
||||
installLog.State = 0
|
||||
installLog.CustomId = id
|
||||
installLog.Message = "installing rely"
|
||||
installLog.Speed = 10
|
||||
installLog.Class = types.NOTIFY_APP
|
||||
installLog.Type = types.NOTIFY_TYPE_UNIMPORTANT
|
||||
installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
||||
installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
||||
installLog.Id = uuid.NewV4().String()
|
||||
service.MyService.Notify().AddLog(installLog)
|
||||
if m.Origin != "custom" {
|
||||
for _, plugin := range appInfo.Plugins {
|
||||
@@ -238,11 +282,11 @@ func InstallApp(c *gin.Context) {
|
||||
rely.ContainerId = mysqlContainerId
|
||||
rely.CustomId = mid
|
||||
rely.ContainerCustomId = id
|
||||
var msqlConfig model2.MysqlConfigs
|
||||
var mysqlConfig model2.MysqlConfigs
|
||||
|
||||
//结构体转换
|
||||
copier.Copy(&msqlConfig, &mc)
|
||||
rely.Config = msqlConfig
|
||||
copier.Copy(&mysqlConfig, &mc)
|
||||
rely.Config = mysqlConfig
|
||||
service.MyService.Rely().Create(rely)
|
||||
|
||||
relyMap["mysql"] = mid
|
||||
@@ -250,16 +294,13 @@ func InstallApp(c *gin.Context) {
|
||||
} else {
|
||||
docker_base.MysqlDelete(mysqlContainerId)
|
||||
installLog.State = 0
|
||||
installLog.Speed = 30
|
||||
installLog.Message = err.Error()
|
||||
service.MyService.Notify().UpdateLog(installLog)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
installLog.Speed = 50
|
||||
installLog.Message = "pulling"
|
||||
service.MyService.Notify().UpdateLog(installLog)
|
||||
|
||||
@@ -267,7 +308,6 @@ func InstallApp(c *gin.Context) {
|
||||
err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, installLog)
|
||||
if err != nil {
|
||||
installLog.State = 0
|
||||
installLog.Speed = 70
|
||||
installLog.Message = err.Error()
|
||||
installLog.Type = types.NOTIFY_TYPE_ERROR
|
||||
service.MyService.Notify().UpdateLog(installLog)
|
||||
@@ -283,36 +323,45 @@ func InstallApp(c *gin.Context) {
|
||||
//}
|
||||
|
||||
//step:创建容器
|
||||
// networkName, err := service.MyService.Docker().GetNetWorkNameByNetWorkID(appInfo.NetworkModel)
|
||||
// if err != nil {
|
||||
// //service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":80}", 100)
|
||||
// installLog.State = 0
|
||||
// installLog.Speed = 75
|
||||
// installLog.Type = types.NOTIFY_TYPE_ERROR
|
||||
// installLog.Message = err.Error()
|
||||
// service.MyService.Notify().UpdateLog(installLog)
|
||||
// return
|
||||
// }
|
||||
containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, id, m, appInfo.NetworkModel)
|
||||
installLog.ContainerId = containerId
|
||||
installLog.Name = appInfo.Title
|
||||
installLog.Icon = appInfo.Icon
|
||||
if err != nil {
|
||||
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":80}", 100)
|
||||
installLog.State = 0
|
||||
installLog.Speed = 80
|
||||
installLog.Type = types.NOTIFY_TYPE_ERROR
|
||||
installLog.Message = err.Error()
|
||||
service.MyService.Notify().UpdateLog(installLog)
|
||||
return
|
||||
} else {
|
||||
//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"starting\",\"speed\":80}", 100)
|
||||
installLog.Speed = 80
|
||||
installLog.Message = "starting"
|
||||
service.MyService.Notify().UpdateLog(installLog)
|
||||
}
|
||||
|
||||
// echo -e "hellow\nworld" >>
|
||||
|
||||
//step:启动容器
|
||||
err = service.MyService.Docker().DockerContainerStart(id)
|
||||
if err != nil {
|
||||
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":90}", 100)
|
||||
installLog.State = 0
|
||||
installLog.Type = types.NOTIFY_TYPE_ERROR
|
||||
installLog.Speed = 90
|
||||
installLog.Message = err.Error()
|
||||
service.MyService.Notify().UpdateLog(installLog)
|
||||
return
|
||||
} else {
|
||||
//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"setting upnp\",\"speed\":90}", 100)
|
||||
installLog.Speed = 90
|
||||
if m.Origin != CUSTOM {
|
||||
installLog.Message = "setting upnp"
|
||||
} else {
|
||||
@@ -357,13 +406,11 @@ func InstallApp(c *gin.Context) {
|
||||
if err != nil {
|
||||
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":95}", 100)
|
||||
installLog.State = 0
|
||||
installLog.Speed = 95
|
||||
installLog.Type = types.NOTIFY_TYPE_ERROR
|
||||
installLog.Message = err.Error()
|
||||
service.MyService.Notify().UpdateLog(installLog)
|
||||
} else {
|
||||
//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"checking\",\"speed\":95}", 100)
|
||||
installLog.Speed = 95
|
||||
installLog.Message = "checking"
|
||||
service.MyService.Notify().UpdateLog(installLog)
|
||||
}
|
||||
@@ -375,14 +422,12 @@ func InstallApp(c *gin.Context) {
|
||||
if err != nil && container.ContainerJSONBase.State.Running {
|
||||
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":100}", 100)
|
||||
installLog.State = 0
|
||||
installLog.Speed = 100
|
||||
installLog.Type = types.NOTIFY_TYPE_ERROR
|
||||
installLog.Message = err.Error()
|
||||
service.MyService.Notify().UpdateLog(installLog)
|
||||
return
|
||||
} else {
|
||||
//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"installed\",\"speed\":100}", 100)
|
||||
installLog.Speed = 100
|
||||
installLog.Message = "installed"
|
||||
service.MyService.Notify().UpdateLog(installLog)
|
||||
}
|
||||
@@ -390,10 +435,18 @@ func InstallApp(c *gin.Context) {
|
||||
rely := model.MapStrings{}
|
||||
|
||||
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)
|
||||
envsStr, _ := json2.Marshal(m.Envs)
|
||||
volumesStr, _ := json2.Marshal(m.Volumes)
|
||||
devicesStr, _ := json2.Marshal(m.Devices)
|
||||
cmd, _ := json2.Marshal(m.Cmd)
|
||||
capAdd, _ := json.Marshal(m.CapAdd)
|
||||
//step: 保存数据到数据库
|
||||
md := model2.AppListDBModel{
|
||||
CustomId: id,
|
||||
@@ -421,14 +474,19 @@ func InstallApp(c *gin.Context) {
|
||||
Memory: m.Memory,
|
||||
Devices: string(devicesStr),
|
||||
//Rely: rely,
|
||||
Origin: m.Origin,
|
||||
CreatedAt: strconv.FormatInt(time.Now().Unix(), 10),
|
||||
UpdatedAt: strconv.FormatInt(time.Now().Unix(), 10),
|
||||
Origin: m.Origin,
|
||||
CreatedAt: 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" {
|
||||
// m.PortMap = m.Port
|
||||
//}
|
||||
service.MyService.App().SaveContainer(md)
|
||||
config.CasaOSGlobalVariables.AppChange = true
|
||||
|
||||
}()
|
||||
|
||||
@@ -643,7 +701,7 @@ func UnInstallApp(c *gin.Context) {
|
||||
}
|
||||
|
||||
//step:删除容器
|
||||
err = service.MyService.Docker().DockerContainerRemove(appId)
|
||||
err = service.MyService.Docker().DockerContainerRemove(appId, false)
|
||||
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()})
|
||||
return
|
||||
@@ -658,10 +716,15 @@ func UnInstallApp(c *gin.Context) {
|
||||
if info.Origin != "custom" {
|
||||
|
||||
//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
|
||||
service.MyService.Notify().DelLog(appId)
|
||||
//service.MyService.Notify().DelLog(appId)
|
||||
|
||||
// for k, v := range info.Rely {
|
||||
//
|
||||
@@ -700,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)})
|
||||
|
||||
@@ -763,7 +833,6 @@ func ContainerLog(c *gin.Context) {
|
||||
func GetInstallSpeed(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
b := service.MyService.Notify().GetLog(id)
|
||||
b.Id = b.CustomId
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: b})
|
||||
}
|
||||
|
||||
@@ -873,19 +942,26 @@ func UpdateSetting(c *gin.Context) {
|
||||
envsStr, _ := json2.Marshal(m.Envs)
|
||||
volumesStr, _ := json2.Marshal(m.Volumes)
|
||||
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 {
|
||||
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 err error
|
||||
|
||||
containerId, err = service.MyService.Docker().DockerContainerCreate(appInfo.Image+":"+appInfo.Version, newUUid, cpd, appInfo.NetModel)
|
||||
// networkName, err := service.MyService.Docker().GetNetWorkNameByNetWorkID(appInfo.NetModel)
|
||||
// if err != nil {
|
||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
|
||||
// return
|
||||
// }
|
||||
containerId, err = service.MyService.Docker().DockerContainerCreate(appInfo.Image+":"+appInfo.Version, newUUid, cpd, m.NetworkModel)
|
||||
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
|
||||
return
|
||||
}
|
||||
|
||||
err = service.MyService.Docker().DockerContainerRemove(id)
|
||||
err = service.MyService.Docker().DockerContainerRemove(id, true)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
|
||||
return
|
||||
@@ -980,11 +1056,16 @@ func UpdateSetting(c *gin.Context) {
|
||||
appInfo.Icon = m.Icon
|
||||
appInfo.Volumes = string(volumesStr)
|
||||
appInfo.Devices = string(devicesStr)
|
||||
appInfo.NetModel = m.NetworkModel
|
||||
appInfo.Position = m.Position
|
||||
appInfo.EnableUPNP = m.EnableUPNP
|
||||
appInfo.Restart = m.Restart
|
||||
appInfo.Memory = m.Memory
|
||||
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)
|
||||
service.MyService.App().UpdateApp(appInfo)
|
||||
|
||||
@@ -1080,25 +1161,32 @@ func ContainerRelyInfo(c *gin.Context) {
|
||||
func ContainerUpdateInfo(c *gin.Context) {
|
||||
appId := c.Param("id")
|
||||
appInfo := service.MyService.App().GetAppDBInfo(appId)
|
||||
|
||||
info, err := service.MyService.Docker().DockerContainerInfo(appId)
|
||||
if err != nil {
|
||||
//todo 需要自定义错误
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: err.Error()})
|
||||
return
|
||||
}
|
||||
var port model.PortArrey
|
||||
var port model.PortArray
|
||||
json2.Unmarshal([]byte(appInfo.Ports), &port)
|
||||
|
||||
var envs model.EnvArrey
|
||||
var envs model.EnvArray
|
||||
json2.Unmarshal([]byte(appInfo.Envs), &envs)
|
||||
|
||||
var vol model.PathArrey
|
||||
var vol model.PathArray
|
||||
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)
|
||||
|
||||
var cmd []string
|
||||
json2.Unmarshal([]byte(appInfo.Cmd), &cmd)
|
||||
var capAdd []string
|
||||
json2.Unmarshal([]byte(appInfo.CapAdd), &capAdd)
|
||||
//volumesStr, _ := json2.Marshal(m.Volumes)
|
||||
//devicesStr, _ := json2.Marshal(m.Devices)
|
||||
m := model.CustomizationPostData{}
|
||||
@@ -1120,6 +1208,11 @@ func ContainerUpdateInfo(c *gin.Context) {
|
||||
m.EnableUPNP = appInfo.EnableUPNP
|
||||
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})
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||
@@ -125,12 +126,12 @@ func GetLocalFile(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// @Summary 下载文件
|
||||
// @Summary download
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags file
|
||||
// @Security ApiKeyAuth
|
||||
// @Param path query string true "路径"
|
||||
// @Param path query string true "path of file"
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /file/download [get]
|
||||
func GetDownloadFile(c *gin.Context) {
|
||||
@@ -163,7 +164,6 @@ func GetDownloadFile(c *gin.Context) {
|
||||
c.Header("Content-Transfer-Encoding", "binary")
|
||||
|
||||
c.File(filePath)
|
||||
return
|
||||
}
|
||||
|
||||
// @Summary 获取目录列表
|
||||
@@ -175,18 +175,18 @@ func GetDownloadFile(c *gin.Context) {
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /file/dirpath [get]
|
||||
func DirPath(c *gin.Context) {
|
||||
path := c.DefaultQuery("path", "/")
|
||||
path := c.DefaultQuery("path", "")
|
||||
info := service.MyService.ZiMa().GetDirPath(path)
|
||||
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
|
||||
// @Accept application/json
|
||||
// @Tags file
|
||||
// @Security ApiKeyAuth
|
||||
// @Param oldpath formData string true "旧的路径"
|
||||
// @Param newpath formData string true "新路径"
|
||||
// @Param oldpath formData string true "path of old"
|
||||
// @Param newpath formData string true "path of new"
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /file/rename [put]
|
||||
func RenamePath(c *gin.Context) {
|
||||
@@ -200,12 +200,12 @@ func RenamePath(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||
}
|
||||
|
||||
// @Summary 创建文件夹
|
||||
// @Summary create folder
|
||||
// @Produce application/json
|
||||
// @Accept multipart/form-data
|
||||
// @Tags file
|
||||
// @Security ApiKeyAuth
|
||||
// @Param path formData string false "路径"
|
||||
// @Param path formData string true "path of folder"
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /file/mkdir [post]
|
||||
func MkdirAll(c *gin.Context) {
|
||||
@@ -238,21 +238,85 @@ func PostCreateFile(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, model.Result{Success: code, Message: oasis_err2.GetMsg(code)})
|
||||
}
|
||||
|
||||
// @Summary 上传文件
|
||||
// @Summary upload file
|
||||
// @Produce application/json
|
||||
// @Accept multipart/form-data
|
||||
// @Tags file
|
||||
// @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"
|
||||
// @Router /file/mkdir [post]
|
||||
// @Router /file/upload [post]
|
||||
func PostFileUpload(c *gin.Context) {
|
||||
file, _, _ := c.Request.FormFile("file")
|
||||
//file.Read()
|
||||
f, _, _ := c.Request.FormFile("file")
|
||||
path := c.Query("path")
|
||||
//上传文件
|
||||
if len(path) == 0 {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||
return
|
||||
}
|
||||
if !file.CheckNotExist(path) {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_ALREADY_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.FILE_ALREADY_EXISTS)})
|
||||
return
|
||||
}
|
||||
out, _ := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0644)
|
||||
defer out.Close()
|
||||
io.Copy(out, file)
|
||||
_, err := io.Copy(out, f)
|
||||
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)})
|
||||
}
|
||||
|
||||
// @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 t 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)})
|
||||
}
|
||||
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)})
|
||||
}
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
json2 "encoding/json"
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/service"
|
||||
"github.com/IceWhaleTech/CasaOS/types"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gorilla/websocket"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
var upGrader = websocket.Upgrader{
|
||||
@@ -33,24 +31,17 @@ func NotifyWS(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
defer ws.Close()
|
||||
service.WebSocketConns = append(service.WebSocketConns, ws)
|
||||
|
||||
if !service.SocketRun {
|
||||
service.SocketRun = true
|
||||
service.SendMeg()
|
||||
}
|
||||
for {
|
||||
mt, message, err := ws.ReadMessage()
|
||||
if err != nil {
|
||||
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)
|
||||
}
|
||||
fmt.Println(mt, message, err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// @Summary 标记notify已读
|
||||
@@ -62,9 +53,10 @@ func NotifyWS(c *gin.Context) {
|
||||
// @Router /notify/read/{id} [put]
|
||||
func PutNotifyRead(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
if len(id) == 0 {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
|
||||
return
|
||||
}
|
||||
// if len(id) == 0 {
|
||||
// c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
|
||||
// return
|
||||
// }
|
||||
fmt.Println(id)
|
||||
service.MyService.Notify().MarkRead(id, types.NOTIFY_READ)
|
||||
}
|
||||
|
||||
25
route/v1/persion.go
Normal file
25
route/v1/persion.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
"github.com/IceWhaleTech/CasaOS/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
func PersonTest(c *gin.Context) {
|
||||
|
||||
//service.MyService.Person().GetPersionInfo("fb2333a1-72b2-4cb4-9e31-61ccaffa55b9")
|
||||
|
||||
m := model.ConnectState{}
|
||||
m.CreatedAt = time.Now()
|
||||
m.From = config.ServerInfo.Token
|
||||
m.To = "fb2333a1-72b2-4cb4-9e31-61ccaffa55b9"
|
||||
m.Type = ""
|
||||
m.UUId = uuid.NewV4().String()
|
||||
|
||||
service.MyService.Person().Handshake(m)
|
||||
}
|
||||
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"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
"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/service"
|
||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||
@@ -28,13 +34,12 @@ func CheckVersion(c *gin.Context) {
|
||||
need, version := version.IsNeedUpdate()
|
||||
if need {
|
||||
installLog := model2.AppNotify{}
|
||||
installLog.CustomId = ""
|
||||
installLog.State = 0
|
||||
installLog.Message = "New version " + version.Version + " is ready, ready to upgrade"
|
||||
installLog.Speed = 100
|
||||
installLog.Type = types.NOTIFY_TYPE_NEED_CONFIRM
|
||||
installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
||||
installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
||||
installLog.Name = "CasaOS System"
|
||||
service.MyService.Notify().AddLog(installLog)
|
||||
}
|
||||
data := make(map[string]interface{}, 1)
|
||||
@@ -53,10 +58,8 @@ func CheckVersion(c *gin.Context) {
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /sys/update [post]
|
||||
func SystemUpdate(c *gin.Context) {
|
||||
fmt.Println("开始更新")
|
||||
need, version := version.IsNeedUpdate()
|
||||
if need {
|
||||
fmt.Println("进入更新")
|
||||
service.MyService.System().UpdateSystemVersion(version.Version)
|
||||
}
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
||||
@@ -67,14 +70,26 @@ func GetSystemConfig(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: json.RawMessage(config.SystemConfigInfo.ConfigStr)})
|
||||
}
|
||||
|
||||
// @Summary get logs
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags sys
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /sys/error/logs [get]
|
||||
func GetCasaOSErrorLogs(c *gin.Context) {
|
||||
line, _ := strconv.Atoi(c.DefaultQuery("line", "100"))
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: service.MyService.System().GetCasaOSLogs(line)})
|
||||
}
|
||||
|
||||
// @Summary 修改配置文件
|
||||
// @Produce application/json
|
||||
// @Accept multipart/form-data
|
||||
// @Tags user
|
||||
// @Param file formData file true "用户头像"
|
||||
// @Tags sys
|
||||
// @Param config formData string true "config json string"
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /user/changhead [post]
|
||||
// @Router /sys/changhead [post]
|
||||
func PostSetSystemConfig(c *gin.Context) {
|
||||
buf := make([]byte, 1024)
|
||||
n, _ := c.Request.Body.Read(buf)
|
||||
@@ -93,9 +108,33 @@ func GetSystemConfigDebug(c *gin.Context) {
|
||||
|
||||
array := service.MyService.System().GetSystemConfigDebug()
|
||||
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) {
|
||||
service.DockerPull()
|
||||
@@ -112,12 +151,13 @@ func GetWidgetConfig(c *gin.Context) {
|
||||
// @Tags sys
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /sys/widget/config[post]
|
||||
// @Router /sys/widget/config [post]
|
||||
func PostSetWidgetConfig(c *gin.Context) {
|
||||
buf := make([]byte, 1024)
|
||||
n, _ := c.Request.Body.Read(buf)
|
||||
|
||||
fmt.Println("错误", strconv.Itoa(n))
|
||||
service.MyService.System().UpSystemConfig("", string(buf[0:n]))
|
||||
fmt.Println("错误1", string(buf[0:n]))
|
||||
c.JSON(http.StatusOK,
|
||||
model.Result{
|
||||
Success: oasis_err.SUCCESS,
|
||||
@@ -125,3 +165,223 @@ func PostSetWidgetConfig(c *gin.Context) {
|
||||
Data: json.RawMessage(config.SystemConfigInfo.WidgetList),
|
||||
})
|
||||
}
|
||||
|
||||
// @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 检查是否进入引导状态
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
// @Tags sys
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /guide/check [get]
|
||||
func GetGuideCheck(c *gin.Context) {
|
||||
initUser := false
|
||||
if !config.UserInfo.Initialized {
|
||||
initUser = true
|
||||
}
|
||||
data := make(map[string]interface{}, 1)
|
||||
data["need_init_user"] = initUser
|
||||
c.JSON(http.StatusOK,
|
||||
model.Result{
|
||||
Success: oasis_err.SUCCESS,
|
||||
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
|
||||
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 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.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})
|
||||
}
|
||||
|
||||
@@ -2,13 +2,15 @@ package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
jwt2 "github.com/IceWhaleTech/CasaOS/pkg/utils/jwt"
|
||||
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||
"github.com/IceWhaleTech/CasaOS/service"
|
||||
"github.com/IceWhaleTech/CasaOS/types"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
var user_service service.UserService
|
||||
@@ -32,7 +34,7 @@ func Set_Name_Pwd(c *gin.Context) {
|
||||
username := c.PostForm("username")
|
||||
pwd := c.PostForm("pwd")
|
||||
//老用户名是否存在即新用户名和密码的验证
|
||||
if len(config.UserInfo.UserName) > 0 || len(username) == 0 || len(pwd) == 0 {
|
||||
if config.UserInfo.Initialized || len(username) == 0 || len(pwd) == 0 {
|
||||
c.JSON(http.StatusOK,
|
||||
model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||
return
|
||||
@@ -69,15 +71,18 @@ func Login(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
//if config.UserInfo.UserName == username && config.UserInfo.PWD == pwd {
|
||||
if username == "admin" && pwd == "admin" {
|
||||
token := jwt2.GetToken(username, pwd)
|
||||
if config.UserInfo.UserName == username && config.UserInfo.PWD == pwd {
|
||||
//if username == "admin" && pwd == "admin" {
|
||||
|
||||
data := make(map[string]string, 2)
|
||||
data["token"] = jwt2.GetToken(username, pwd)
|
||||
data["version"] = types.CURRENTVERSION
|
||||
//user_service.SetUser("", "", token, "", "")
|
||||
c.JSON(http.StatusOK,
|
||||
model.Result{
|
||||
Success: oasis_err2.SUCCESS,
|
||||
Message: oasis_err2.GetMsg(oasis_err2.SUCCESS),
|
||||
Data: token,
|
||||
Data: data,
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -106,7 +111,6 @@ func Up_Load_Head(c *gin.Context) {
|
||||
Message: oasis_err2.GetMsg(oasis_err2.SUCCESS),
|
||||
Data: config.UserInfo.Head,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// @Summary 修改用户名
|
||||
@@ -119,6 +123,10 @@ func Up_Load_Head(c *gin.Context) {
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /user/changusername [put]
|
||||
func Chang_User_Name(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")
|
||||
username := c.PostForm("username")
|
||||
if len(username) == 0 || config.UserInfo.UserName != oldname {
|
||||
@@ -127,7 +135,6 @@ func Chang_User_Name(c *gin.Context) {
|
||||
}
|
||||
user_service.SetUser(username, "", "", "", "")
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||
return
|
||||
}
|
||||
|
||||
// @Summary 修改密码
|
||||
@@ -142,13 +149,20 @@ func Chang_User_Name(c *gin.Context) {
|
||||
func Chang_User_Pwd(c *gin.Context) {
|
||||
oldpwd := c.PostForm("oldpwd")
|
||||
pwd := c.PostForm("pwd")
|
||||
if len(pwd) == 0 || config.UserInfo.PWD != oldpwd {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
|
||||
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)})
|
||||
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 {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PWD_IS_EMPTY, Message: oasis_err2.GetMsg(oasis_err2.PWD_IS_EMPTY)})
|
||||
return
|
||||
}
|
||||
user_service.SetUser("", pwd, "", "", "")
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||
return
|
||||
}
|
||||
|
||||
// @Summary 修改用户信息
|
||||
@@ -174,21 +188,23 @@ func Chang_User_Info(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
user_service.SetUser(username, pwd, "", email, description)
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||
return
|
||||
data := make(map[string]string, 2)
|
||||
|
||||
data["token"] = jwt2.GetToken(username, pwd)
|
||||
data["user_name"] = username
|
||||
data["head"] = config.UserInfo.Head
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
|
||||
}
|
||||
|
||||
// @Summary 获取用户详情
|
||||
// @Produce application/json
|
||||
// @Accept mapplication/json
|
||||
// @Tags user
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {string} string "ok"
|
||||
// @Router /user/info [get]
|
||||
func UserInfo(c *gin.Context) {
|
||||
var u = make(map[string]string, 2)
|
||||
u["user_name"] = config.UserInfo.UserName
|
||||
u["token"] = config.UserInfo.Token
|
||||
u["head"] = config.UserInfo.Head
|
||||
u["email"] = config.UserInfo.Email
|
||||
u["description"] = config.UserInfo.Description
|
||||
@@ -198,5 +214,4 @@ func UserInfo(c *gin.Context) {
|
||||
Message: oasis_err2.GetMsg(oasis_err2.SUCCESS),
|
||||
Data: u,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2,12 +2,13 @@ package v1
|
||||
|
||||
import (
|
||||
json2 "encoding/json"
|
||||
"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"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// @Summary 登录zerotier获取token
|
||||
@@ -432,11 +433,17 @@ func ZeroTierDeleteNetwork(c *gin.Context) {
|
||||
// @Router /zerotier/join/{id} [post]
|
||||
func ZeroTierJoinNetwork(c *gin.Context) {
|
||||
networkId := c.Param("id")
|
||||
service.MyService.ZeroTier().ZeroTierJoinNetwork(networkId)
|
||||
if len(networkId) == 0 {
|
||||
if len(networkId) != 16 {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||
return
|
||||
}
|
||||
for _, v := range networkId {
|
||||
if !service.MyService.ZeroTier().NetworkIdFilter(v) {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||
return
|
||||
}
|
||||
}
|
||||
service.MyService.ZeroTier().ZeroTierJoinNetwork(networkId)
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||
}
|
||||
|
||||
@@ -450,10 +457,19 @@ func ZeroTierJoinNetwork(c *gin.Context) {
|
||||
// @Router /zerotier/leave/{id} [post]
|
||||
func ZeroTierLeaveNetwork(c *gin.Context) {
|
||||
networkId := c.Param("id")
|
||||
service.MyService.ZeroTier().ZeroTierLeaveNetwork(networkId)
|
||||
if len(networkId) == 0 {
|
||||
|
||||
if len(networkId) != 16 {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||
return
|
||||
}
|
||||
|
||||
for _, v := range networkId {
|
||||
if !service.MyService.ZeroTier().NetworkIdFilter(v) {
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||
return
|
||||
}
|
||||
}
|
||||
service.MyService.ZeroTier().ZeroTierLeaveNetwork(networkId)
|
||||
|
||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
package v1
|
||||
|
||||
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"
|
||||
"strings"
|
||||
"time"
|
||||
"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信息
|
||||
@@ -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})
|
||||
}
|
||||
|
||||
// @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 获取信息系统信息
|
||||
// @Produce application/json
|
||||
// @Accept application/json
|
||||
|
||||
234
service/app.go
234
service/app.go
@@ -2,35 +2,40 @@ package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
json2 "encoding/json"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/docker"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
client2 "github.com/docker/docker/client"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/tidwall/gjson"
|
||||
"gorm.io/gorm"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type AppService interface {
|
||||
GetMyList(index, size int, position bool) *[]model2.MyAppList
|
||||
SaveContainer(m model2.AppListDBModel)
|
||||
GetServerAppInfo(id string) model.ServerAppList
|
||||
GetUninstallInfo(id string) model2.AppListDBModel
|
||||
RemoveContainerById(id string)
|
||||
GetContainerInfo(name string) (types.Container, error)
|
||||
GetAppDBInfo(id string) model2.AppListDBModel
|
||||
UpdateApp(m model2.AppListDBModel)
|
||||
GetSimpleContainerInfo(name string) (types.Container, error)
|
||||
DelAppConfigDir(id string)
|
||||
DelAppConfigDir(path string)
|
||||
GetSystemAppList() *[]model2.MyAppList
|
||||
GetHardwareUsageSteam()
|
||||
GetHardwareUsage() []model.DockerStatsModel
|
||||
GetAppStats(id string) string
|
||||
}
|
||||
|
||||
type appStruct struct {
|
||||
@@ -41,7 +46,7 @@ type appStruct struct {
|
||||
//获取我的应用列表
|
||||
func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppList {
|
||||
//获取docker应用
|
||||
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||
cli, err := client2.NewClientWithOpts(client2.FromEnv, client2.WithTimeout(time.Second*5))
|
||||
if err != nil {
|
||||
a.log.Error("初始化client失败", "app.getmylist", "line:36", err)
|
||||
}
|
||||
@@ -52,11 +57,10 @@ func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppLis
|
||||
if err != nil {
|
||||
a.log.Error("获取docker容器失败", "app.getmylist", "line:42", err)
|
||||
}
|
||||
|
||||
//获取本地数据库应用
|
||||
|
||||
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{}
|
||||
lMap := make(map[string]interface{})
|
||||
@@ -69,11 +73,70 @@ func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppLis
|
||||
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 {
|
||||
|
||||
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 {
|
||||
m.Label = m.Title
|
||||
}
|
||||
@@ -93,11 +156,12 @@ func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppLis
|
||||
Port: m.PortMap,
|
||||
Index: m.Index,
|
||||
UpTime: tm,
|
||||
Image: m.Image,
|
||||
Slogan: m.Slogan,
|
||||
Volumes: m.Volumes,
|
||||
//Rely: m.Rely,
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return &list
|
||||
@@ -115,7 +179,7 @@ func (a *appStruct) GetContainerInfo(name string) (types.Container, error) {
|
||||
filters.Add("name", name)
|
||||
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: filters})
|
||||
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 {
|
||||
@@ -135,6 +199,10 @@ func (a *appStruct) GetSimpleContainerInfo(name string) (types.Container, error)
|
||||
filters := filters.NewArgs()
|
||||
filters.Add("name", name)
|
||||
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: filters})
|
||||
if err != nil {
|
||||
return types.Container{}, err
|
||||
}
|
||||
|
||||
if len(containers) > 0 {
|
||||
return containers[0], nil
|
||||
}
|
||||
@@ -155,27 +223,6 @@ func (a *appStruct) GetUninstallInfo(id string) model2.AppListDBModel {
|
||||
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) {
|
||||
a.db.Table(model2.CONTAINERTABLENAME).Create(&m)
|
||||
@@ -185,14 +232,125 @@ func (a *appStruct) UpdateApp(m model2.AppListDBModel) {
|
||||
a.db.Table(model2.CONTAINERTABLENAME).Save(&m)
|
||||
}
|
||||
|
||||
func (a *appStruct) DelAppConfigDir(id string) {
|
||||
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;DelAppConfigDir " + docker.GetDir(id, "/config"))
|
||||
func (a *appStruct) DelAppConfigDir(path string) {
|
||||
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;DelAppConfigDir " + path)
|
||||
}
|
||||
|
||||
func (a *appStruct) RemoveContainerById(id string) {
|
||||
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 {
|
||||
return &appStruct{db: db, log: logger}
|
||||
}
|
||||
|
||||
148
service/casa.go
Normal file
148
service/casa.go
Normal file
@@ -0,0 +1,148 @@
|
||||
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)
|
||||
}
|
||||
|
||||
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 NewOasisService() CasaService {
|
||||
return &casaService{}
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
|
||||
ip_helper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
|
||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
"github.com/IceWhaleTech/CasaOS/service/ddns"
|
||||
"github.com/IceWhaleTech/CasaOS/service/model"
|
||||
"gorm.io/gorm"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
type ddnsStruct struct {
|
||||
@@ -20,17 +21,15 @@ type DDNSService interface {
|
||||
GetConfigList() *[]model.DDNSList
|
||||
DeleteConfig(id uint) bool
|
||||
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 {
|
||||
var count int64
|
||||
d.db.Table(model.DDNSLISTTABLENAME).Where("type=? AND domain=? AND host=?", t, domain, host).Count(&count)
|
||||
if count > 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
return count > 0
|
||||
}
|
||||
|
||||
//前台获取已配置的ddns列表
|
||||
@@ -41,7 +40,7 @@ func (d *ddnsStruct) GetConfigList() *[]model.DDNSList {
|
||||
}
|
||||
|
||||
func (d *ddnsStruct) DeleteConfig(id uint) bool {
|
||||
d.db.Delete(&model.DDNSUpdataDBModel{Id: id})
|
||||
d.db.Delete(&model.DDNSUpdateDBModel{Id: id})
|
||||
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
|
||||
}
|
||||
|
||||
//保存配置到数据库
|
||||
func (d *ddnsStruct) SaveConfig(model model.DDNSUpdataDBModel) error {
|
||||
func (d *ddnsStruct) SaveConfig(model model.DDNSUpdateDBModel) 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
|
||||
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 {
|
||||
|
||||
@@ -31,4 +31,3 @@ func SetOauth(request *http.Request, value string) {
|
||||
func SetXFilter(request *http.Request, value string) {
|
||||
request.Header.Set("X-Filter", value)
|
||||
}
|
||||
|
||||
|
||||
186
service/disk.go
186
service/disk.go
@@ -3,28 +3,73 @@ package service
|
||||
import (
|
||||
json2 "encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||
"github.com/shirou/gopsutil/v3/disk"
|
||||
"github.com/tidwall/gjson"
|
||||
"strconv"
|
||||
"strings"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type DiskService interface {
|
||||
GetPlugInDisk() []string
|
||||
LSBLK() []model.LSBLKModel
|
||||
FormatDisk(path, format string) string
|
||||
UmountPointAndRemoveDir(path string) string
|
||||
LSBLK(isUseCache bool) []model.LSBLKModel
|
||||
SmartCTL(path string) model.SmartctlA
|
||||
FormatDisk(path, format string) []string
|
||||
UmountPointAndRemoveDir(path string) []string
|
||||
GetDiskInfo(path string) model.LSBLKModel
|
||||
DelPartition(path, num string) string
|
||||
AddPartition(path, num string, size uint64) string
|
||||
AddPartition(path string) string
|
||||
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 {
|
||||
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)
|
||||
fmt.Println(r)
|
||||
return ""
|
||||
return r
|
||||
}
|
||||
|
||||
//移除挂载点,删除目录
|
||||
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)
|
||||
fmt.Println(r)
|
||||
return ""
|
||||
return r
|
||||
}
|
||||
|
||||
//删除分区
|
||||
@@ -54,46 +96,44 @@ func (d *diskService) DelPartition(path, num string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
//添加分区
|
||||
func (d *diskService) AddPartition(path, num string, size uint64) string {
|
||||
|
||||
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)
|
||||
//part
|
||||
func (d *diskService) AddPartition(path string) string {
|
||||
command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;AddPartition " + path)
|
||||
return ""
|
||||
}
|
||||
|
||||
func (d *diskService) AddAllPartition(path string) {
|
||||
|
||||
}
|
||||
|
||||
//获取硬盘详情
|
||||
func (d *diskService) GetDiskInfoByPath(path string) *disk.UsageStat {
|
||||
diskInfo, err := disk.Usage(path + "1")
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(path)
|
||||
fmt.Println(diskInfo)
|
||||
diskInfo.UsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.UsedPercent), 64)
|
||||
diskInfo.InodesUsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.InodesUsedPercent), 64)
|
||||
return diskInfo
|
||||
}
|
||||
|
||||
//获取磁盘信息
|
||||
func (d *diskService) LSBLK() []model.LSBLKModel {
|
||||
//get disk details
|
||||
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()
|
||||
if str == nil {
|
||||
d.log.Error("lsblk exec error")
|
||||
d.log.Error("lsblk exec error,lsblk")
|
||||
return nil
|
||||
}
|
||||
var m []model.LSBLKModel
|
||||
@@ -102,15 +142,13 @@ func (d *diskService) LSBLK() []model.LSBLKModel {
|
||||
d.log.Error("json ummarshal error", err)
|
||||
}
|
||||
|
||||
var n []model.LSBLKModel
|
||||
|
||||
var c []model.LSBLKModel
|
||||
|
||||
var fsused uint64
|
||||
|
||||
var health = true
|
||||
for _, i := range m {
|
||||
if i.Children != nil {
|
||||
if i.Type != "loop" && !i.RO {
|
||||
fsused = 0
|
||||
for _, child := range i.Children {
|
||||
if child.RM {
|
||||
@@ -133,7 +171,7 @@ func (d *diskService) LSBLK() []model.LSBLKModel {
|
||||
i.Children = c
|
||||
if fsused > 0 {
|
||||
i.UsedPercent, err = strconv.ParseFloat(fmt.Sprintf("%.4f", float64(fsused)/float64(i.Size)), 64)
|
||||
fmt.Println(err)
|
||||
d.log.Fatal("diskservice_lsblk_fsused", err)
|
||||
}
|
||||
n = append(n, i)
|
||||
health = true
|
||||
@@ -141,15 +179,19 @@ func (d *diskService) LSBLK() []model.LSBLKModel {
|
||||
fsused = 0
|
||||
}
|
||||
}
|
||||
if len(n) > 0 {
|
||||
Cache.Add(key, n, time.Second*100)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
|
||||
str := command2.ExecLSBLKByPath(path)
|
||||
if str == nil {
|
||||
d.log.Error("lsblk exec error")
|
||||
d.log.Error("lsblk exec error,str")
|
||||
return model.LSBLKModel{}
|
||||
}
|
||||
|
||||
var ml []model.LSBLKModel
|
||||
err := json2.Unmarshal([]byte(gjson.Get(string(str), "blockdevices").String()), &ml)
|
||||
if err != nil {
|
||||
@@ -157,9 +199,13 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
|
||||
d.log.Error("json ummarshal error", err)
|
||||
return model.LSBLKModel{}
|
||||
}
|
||||
//todo 需要判断长度
|
||||
m := ml[0]
|
||||
//声明数组
|
||||
|
||||
m := model.LSBLKModel{}
|
||||
if len(ml) > 0 {
|
||||
m = ml[0]
|
||||
}
|
||||
return m
|
||||
// 下面为计算是否可以继续分区的部分,暂时不需要
|
||||
chiArr := make(map[string]string)
|
||||
chiList := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetPartitionSectors " + m.Path)
|
||||
if len(chiList) == 0 {
|
||||
@@ -170,7 +216,6 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
|
||||
tempArr := strings.Split(chiList[i], ",")
|
||||
chiArr[tempArr[0]] = chiList[i]
|
||||
}
|
||||
|
||||
var maxSector uint64 = 0
|
||||
for i := 0; i < len(m.Children); i++ {
|
||||
tempArr := strings.Split(chiArr[m.Children[i].Path], ",")
|
||||
@@ -179,13 +224,13 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
|
||||
if m.Children[i].EndSector > maxSector {
|
||||
maxSector = m.Children[i].EndSector
|
||||
}
|
||||
|
||||
}
|
||||
diskEndSector := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetDiskSizeAndSectors " + m.Path)
|
||||
|
||||
if len(diskEndSector) < 2 {
|
||||
d.log.Error("diskEndSector length error")
|
||||
}
|
||||
|
||||
diskEndSectorInt, _ := strconv.ParseUint(diskEndSector[len(diskEndSector)-1], 10, 64)
|
||||
if (diskEndSectorInt-maxSector)*m.MinIO/1024/1024 > 100 {
|
||||
//添加可以分区情况
|
||||
@@ -196,17 +241,38 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
|
||||
return m
|
||||
}
|
||||
|
||||
//func GetDiskInfo(path string) *disk.UsageStat {
|
||||
// diskInfo, _ := disk.Usage(path)
|
||||
// diskInfo.UsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.UsedPercent), 64)
|
||||
// diskInfo.InodesUsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.InodesUsedPercent), 64)
|
||||
// return diskInfo
|
||||
//}
|
||||
|
||||
//func (d *diskService) GetPlugInDisk() []string {
|
||||
// return disk.Partitions(false)
|
||||
//}
|
||||
|
||||
func NewDiskService(log loger2.OLog) DiskService {
|
||||
return &diskService{log: log}
|
||||
func (d *diskService) MountDisk(path, volume string) {
|
||||
r := command2.ExecResultStr("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;do_mount " + path + " " + volume)
|
||||
fmt.Print(r)
|
||||
}
|
||||
|
||||
func (d *diskService) SaveMountPoint(m model2.SerialDisk) {
|
||||
d.db.Where("uuid = ?", m.UUID).Delete(&model2.SerialDisk{})
|
||||
d.db.Create(&m)
|
||||
}
|
||||
|
||||
func (d *diskService) UpdateMountPoint(m model2.SerialDisk) {
|
||||
d.db.Model(&model2.SerialDisk{}).Where("uui = ?", m.UUID).Update("mount_point", m.MountPoint)
|
||||
}
|
||||
|
||||
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,6 +7,7 @@ import (
|
||||
"encoding/binary"
|
||||
json2 "encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"syscall"
|
||||
|
||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||
@@ -19,6 +20,7 @@ import (
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/docker"
|
||||
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/env_helper"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
|
||||
@@ -50,7 +52,7 @@ type DockerService interface {
|
||||
DockerListByImage(image, version string) (*types.Container, error)
|
||||
DockerContainerInfo(name string) (*types.ContainerJSON, error)
|
||||
DockerImageRemove(name string) error
|
||||
DockerContainerRemove(name string) error
|
||||
DockerContainerRemove(name string, update bool) error
|
||||
DockerContainerStop(id string) error
|
||||
DockerContainerUpdateName(name, id string) (err error)
|
||||
DockerContainerUpdate(m model.CustomizationPostData, id string) (err error)
|
||||
@@ -58,6 +60,8 @@ type DockerService interface {
|
||||
DockerContainerCommit(name string)
|
||||
DockerNetworkModelList() []types.NetworkResource
|
||||
DockerImageInfo(image string)
|
||||
GetNetWorkNameByNetWorkID(id string) (string, error)
|
||||
ContainerExecShell(container_id string) string
|
||||
}
|
||||
|
||||
type dockerService struct {
|
||||
@@ -65,15 +69,20 @@ type dockerService struct {
|
||||
log loger2.OLog
|
||||
}
|
||||
|
||||
func DockerPs() {
|
||||
func (ds *dockerService) ContainerExecShell(container_id string) string {
|
||||
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 {
|
||||
os.Exit(5)
|
||||
}
|
||||
for _, container := range containers {
|
||||
fmt.Printf("%s %s\n", container.ID[:10], container.Image)
|
||||
err = cli.ContainerExecStart(context.Background(), exec.ID, types.ExecStartCheck{})
|
||||
if err != nil {
|
||||
fmt.Println("exec script error ", err)
|
||||
}
|
||||
return exec.ID
|
||||
}
|
||||
|
||||
//创建默认网络
|
||||
@@ -91,6 +100,19 @@ func DockerNetwork() {
|
||||
cli.NetworkCreate(context.Background(), docker.NETWORKNAME, types.NetworkCreate{})
|
||||
}
|
||||
|
||||
//根据网络id获取网络名
|
||||
func (ds *dockerService) GetNetWorkNameByNetWorkID(id string) (string, error) {
|
||||
cli, _ := client2.NewClientWithOpts(client2.FromEnv)
|
||||
defer cli.Close()
|
||||
filter := filters.NewArgs()
|
||||
filter.Add("id", id)
|
||||
d, err := cli.NetworkList(context.Background(), types.NetworkListOptions{Filters: filter})
|
||||
if err == nil && len(d) > 0 {
|
||||
return d[0].Name, nil
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
|
||||
//拉取镜像
|
||||
func DockerPull() {
|
||||
|
||||
@@ -135,7 +157,7 @@ func DockerEx() {
|
||||
importResponse.Close()
|
||||
println(string(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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,7 +186,6 @@ func (ds *dockerService) DockerImageInfo(image string) {
|
||||
if err != nil {
|
||||
fmt.Print(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func MsqlExec(container string) error {
|
||||
@@ -243,6 +264,8 @@ func DockerLogs() {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer i.Close()
|
||||
|
||||
hdr := make([]byte, 8)
|
||||
for {
|
||||
_, err := i.Read(hdr)
|
||||
@@ -261,7 +284,6 @@ func DockerLogs() {
|
||||
_, err = i.Read(dat)
|
||||
fmt.Fprint(w, string(dat))
|
||||
}
|
||||
defer i.Close()
|
||||
}
|
||||
|
||||
//正式内容
|
||||
@@ -310,11 +332,13 @@ func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) e
|
||||
}
|
||||
break
|
||||
}
|
||||
m.Type = types2.NOTIFY_TYPE_INSTALL_LOG
|
||||
m.State = 0
|
||||
m.Speed = 70
|
||||
m.Message = string(buf[:n])
|
||||
MyService.Notify().UpdateLog(m)
|
||||
if !reflect.DeepEqual(m, model2.AppNotify{}) {
|
||||
m.Type = types2.NOTIFY_TYPE_INSTALL_LOG
|
||||
m.State = 0
|
||||
m.Message = string(buf[:n])
|
||||
MyService.Notify().UpdateLog(m)
|
||||
}
|
||||
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -327,7 +351,7 @@ func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) e
|
||||
//param udp 容器其他udp端口
|
||||
func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId string, m model.CustomizationPostData, net string) (containerId string, err error) {
|
||||
if len(net) == 0 {
|
||||
net = "oasis"
|
||||
net = "bridge"
|
||||
}
|
||||
|
||||
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||
@@ -341,11 +365,11 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
||||
// if net != "host" {
|
||||
// portMaps[nat.Port(fmt.Sprint(m.Port)+"/tcp")] = []nat.PortBinding{{HostIP: "", HostPort: m.PortMap}}
|
||||
// }
|
||||
port := ""
|
||||
//port := ""
|
||||
for _, portMap := range m.Ports {
|
||||
if portMap.CommendPort == m.PortMap && portMap.Protocol == "tcp" || portMap.Protocol == "both" {
|
||||
port = portMap.ContainerPort
|
||||
}
|
||||
// if portMap.CommendPort == m.PortMap && portMap.Protocol == "tcp" || portMap.Protocol == "both" {
|
||||
// port = portMap.ContainerPort
|
||||
// }
|
||||
if portMap.Protocol == "tcp" {
|
||||
|
||||
tContainer, _ := strconv.Atoi(portMap.ContainerPort)
|
||||
@@ -387,6 +411,10 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
||||
|
||||
var envArr []string
|
||||
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 e.Value == "port_map" {
|
||||
envArr = append(envArr, e.Name+"="+m.PortMap)
|
||||
@@ -405,33 +433,37 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
||||
}
|
||||
for _, p := range m.Devices {
|
||||
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{}
|
||||
// volumes bind
|
||||
volumes := []mount.Mount{}
|
||||
for _, v := range m.Volumes {
|
||||
path := v.Path
|
||||
if len(path) == 0 {
|
||||
path = docker.GetDir(containerDbId, v.ContainerPath)
|
||||
path = docker.GetDir(containerDbId, v.Path)
|
||||
if len(path) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
}
|
||||
if strings.HasSuffix(path, "/") {
|
||||
err = file.IsNotExistMkDir(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
|
||||
}
|
||||
path = strings.ReplaceAll(path, "$AppID", containerDbId)
|
||||
//reg1 := regexp.MustCompile(`([^<>/\\\|:""\*\?]+\.\w+$)`)
|
||||
//result1 := reg1.FindAllStringSubmatch(path, -1)
|
||||
//if len(result1) == 0 {
|
||||
err = file.IsNotExistMkDir(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{
|
||||
Type: mount.TypeBind,
|
||||
@@ -439,6 +471,7 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
||||
Target: v.ContainerPath,
|
||||
})
|
||||
|
||||
hostConfingBind = append(hostConfingBind, v.Path+":"+v.ContainerPath)
|
||||
}
|
||||
|
||||
rp := container.RestartPolicy{}
|
||||
@@ -446,25 +479,29 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
||||
if len(m.Restart) > 0 {
|
||||
rp.Name = m.Restart
|
||||
}
|
||||
//fmt.Print(port)
|
||||
healthTest := []string{}
|
||||
if len(port) > 0 {
|
||||
healthTest = []string{"CMD-SHELL", "curl -f http://localhost:" + port + m.Index + " || exit 1"}
|
||||
}
|
||||
// healthTest := []string{}
|
||||
// if len(port) > 0 {
|
||||
// healthTest = []string{"CMD-SHELL", "curl -f http://localhost:" + port + m.Index + " || exit 1"}
|
||||
// }
|
||||
|
||||
health := &container.HealthConfig{
|
||||
Test: healthTest,
|
||||
//Test: []string{},
|
||||
StartPeriod: 0,
|
||||
Retries: 1000,
|
||||
// health := &container.HealthConfig{
|
||||
// Test: healthTest,
|
||||
// StartPeriod: 0,
|
||||
// Retries: 1000,
|
||||
// }
|
||||
// fmt.Print(health)
|
||||
if len(m.HostName) == 0 {
|
||||
m.HostName = m.Label
|
||||
}
|
||||
config := &container.Config{
|
||||
Image: imageName,
|
||||
Labels: map[string]string{"origin": m.Origin, m.Origin: m.Origin},
|
||||
Env: envArr,
|
||||
Healthcheck: health,
|
||||
Image: imageName,
|
||||
Labels: map[string]string{"origin": m.Origin, m.Origin: m.Origin},
|
||||
Env: envArr,
|
||||
// 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" {
|
||||
config.ExposedPorts = ports
|
||||
hostConfig.PortBindings = portMaps
|
||||
@@ -483,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)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -492,9 +529,11 @@ func (ds *dockerService) DockerContainerRemove(name string) error {
|
||||
err = cli.ContainerRemove(context.Background(), name, types.ContainerRemoveOptions{})
|
||||
|
||||
//路径处理
|
||||
path := docker.GetDir(name, "/config")
|
||||
if !file.CheckNotExist(path) {
|
||||
file.RMDir(path)
|
||||
if !update {
|
||||
path := docker.GetDir(name, "/config")
|
||||
if !file.CheckNotExist(path) {
|
||||
file.RMDir(path)
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@@ -720,7 +759,7 @@ func (ds *dockerService) DockerContainerUpdate(m model.CustomizationPostData, id
|
||||
res.CPUShares = m.CpuShares
|
||||
}
|
||||
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})
|
||||
if err != nil {
|
||||
@@ -755,7 +794,7 @@ func (ds *dockerService) DockerNetworkModelList() []types.NetworkResource {
|
||||
networks, _ := cli.NetworkList(context.Background(), types.NetworkListOptions{})
|
||||
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}
|
||||
}
|
||||
|
||||
@@ -799,7 +838,6 @@ func Containerd() {
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("333")
|
||||
fmt.Println(err)
|
||||
}
|
||||
defer container.Delete(ctx, containerd.WithSnapshotCleanup)
|
||||
@@ -807,7 +845,6 @@ func Containerd() {
|
||||
// create a task from the container
|
||||
task, err := container.NewTask(ctx, cio.NewCreator(cio.WithStdio))
|
||||
if err != nil {
|
||||
fmt.Println("444")
|
||||
fmt.Println(err)
|
||||
}
|
||||
defer task.Delete(ctx)
|
||||
@@ -820,7 +857,6 @@ func Containerd() {
|
||||
|
||||
// call start on the task to execute the redis server
|
||||
if err = task.Start(ctx); err != nil {
|
||||
fmt.Println("555")
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
@@ -830,7 +866,6 @@ func Containerd() {
|
||||
|
||||
// kill the process and get the exit status
|
||||
if err = task.Kill(ctx, syscall.SIGTERM); err != nil {
|
||||
fmt.Println("666")
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
@@ -839,7 +874,6 @@ func Containerd() {
|
||||
status := <-exitStatusC
|
||||
code, _, err := status.Result()
|
||||
if err != nil {
|
||||
fmt.Println("777")
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Printf("redis-server exited with status: %d\n", code)
|
||||
|
||||
@@ -3,7 +3,7 @@ package docker_base
|
||||
import "github.com/IceWhaleTech/CasaOS/model"
|
||||
|
||||
//过滤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++ {
|
||||
switch envs[i].Value {
|
||||
case "$MYSQL_HOST":
|
||||
|
||||
@@ -7,5 +7,3 @@ type MysqlConfig struct {
|
||||
DataBasePassword string `json:"data_base_password"`
|
||||
DataBaseDB string `json:"data_base_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()
|
||||
}
|
||||
@@ -26,14 +26,10 @@ type AppListDBModel struct {
|
||||
PortMap string `json:"port_map"`
|
||||
Label string `json:"label"`
|
||||
EnableUPNP bool `json:"enable_upnp"`
|
||||
//Envs model.EnvArrey `json:"envs" bson:"envs"`
|
||||
//Ports model.PortArrey `json:"ports" bson:"ports"`
|
||||
//Volumes model.PathArrey `json:"volumes" bson:"volumes"`
|
||||
//Devices model.PathArrey `json:"devices" bson:"devices"`
|
||||
Envs string `json:"envs"`
|
||||
Ports string `json:"ports"`
|
||||
Volumes string `json:"volumes"`
|
||||
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"`
|
||||
//Ports []model.PortMap `gorm:"type:json" json:"ports"`
|
||||
//Volumes []model.PathMap `gorm:"type:json" json:"volumes"`
|
||||
@@ -44,7 +40,11 @@ type AppListDBModel struct {
|
||||
Memory int64 `json:"memory"`
|
||||
Restart string `json:"restart"`
|
||||
//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 {
|
||||
@@ -61,4 +61,6 @@ type MyAppList struct {
|
||||
UpTime string `json:"up_time"`
|
||||
Slogan string `json:"slogan"`
|
||||
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"
|
||||
|
||||
func (p *DDNSUpdataDBModel) TableName() string {
|
||||
func (p *DDNSUpdateDBModel) TableName() string {
|
||||
return "o_ddns"
|
||||
}
|
||||
|
||||
type DDNSUpdataDBModel struct {
|
||||
type DDNSUpdateDBModel struct {
|
||||
Id uint `gorm:"column:id;primary_key" json:"id"`
|
||||
Ipv4 string `gorm:"-"`
|
||||
Ipv6 string `gorm:"-"`
|
||||
@@ -17,8 +17,8 @@ type DDNSUpdataDBModel struct {
|
||||
Secret string `json:"secret" form:"secret"`
|
||||
UserName string `json:"user_name" form:"user_name"`
|
||||
Password string `json:"password" form:"password"`
|
||||
CreatedAt time.Time `gorm:"<-:create" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"<-:create;<-:update" json:"updated_at"`
|
||||
CreatedAt time.Time `gorm:"<-:create" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"<-:create;<-:update" json:"updated_at"`
|
||||
}
|
||||
|
||||
const DDNSLISTTABLENAME = "o_ddns"
|
||||
@@ -39,9 +39,9 @@ type DDNSList 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"`
|
||||
Name string `json:"domain" form:"name"`
|
||||
Name string `json:"name" form:"name"`
|
||||
Type uint `json:"type"`
|
||||
Key string `json:"key"`
|
||||
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"
|
||||
}
|
||||
@@ -1,15 +1,16 @@
|
||||
package model
|
||||
|
||||
type AppNotify struct {
|
||||
CustomId string `gorm:"column:custom_id;primary_key" json:"custom_id"`
|
||||
ContainerId string `json:"container_id,omitempty"`
|
||||
State int `json:"state"` //0:一直在变动的未读消息 1:未读 2:已读
|
||||
Message string `json:"message"`
|
||||
CreatedAt string `gorm:"<-:create;autoCreateTime" json:"created_at"`
|
||||
UpdatedAt string `gorm:"<-:create;<-:update;autoUpdateTime" json:"updated_at"`
|
||||
Speed int `json:"speed"`
|
||||
Id string `gorm:"-" json:"id"`
|
||||
Type int `json:"type"` // 1:显示即为已读 2:必须手动点掉 3:error
|
||||
State int `json:"state"` //0:一直在变动的未读消息 1:未读 2:已读
|
||||
Message string `json:"message"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
Id string `json:"id"`
|
||||
Type int `json:"type"`
|
||||
Icon string `json:"icon"`
|
||||
Name string `json:"name"`
|
||||
Class int `json:"class"`
|
||||
CustomId string `gorm:"column:custom_id;primary_key" json:"custom_id"`
|
||||
}
|
||||
|
||||
func (p *AppNotify) TableName() string {
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
json2 "encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/service/model"
|
||||
"github.com/IceWhaleTech/CasaOS/types"
|
||||
"github.com/gorilla/websocket"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
@@ -10,8 +14,9 @@ type NotifyServer interface {
|
||||
GetLog(id string) model.AppNotify
|
||||
AddLog(log model.AppNotify)
|
||||
UpdateLog(log model.AppNotify)
|
||||
UpdateLogByCustomId(log model.AppNotify)
|
||||
DelLog(id string)
|
||||
GetList() (list []model.AppNotify)
|
||||
GetList(c int) (list []model.AppNotify)
|
||||
MarkRead(id string, state int)
|
||||
}
|
||||
|
||||
@@ -19,8 +24,8 @@ type notifyServer struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func (i notifyServer) GetList() (list []model.AppNotify) {
|
||||
i.db.Where("state=? or state=?", types.NOTIFY_DYNAMICE, types.NOTIFY_UNREAD).Find(&list)
|
||||
func (i notifyServer) GetList(c int) (list []model.AppNotify) {
|
||||
i.db.Where("class = ?", c).Where(i.db.Where("state = ?", types.NOTIFY_DYNAMICE).Or("state = ?", types.NOTIFY_UNREAD)).Find(&list)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -31,20 +36,72 @@ func (i *notifyServer) AddLog(log model.AppNotify) {
|
||||
func (i *notifyServer) UpdateLog(log model.AppNotify) {
|
||||
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 {
|
||||
var log model.AppNotify
|
||||
i.db.Where("custom_id = ? ", id).First(&log)
|
||||
return log
|
||||
}
|
||||
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) {
|
||||
var log model.AppNotify
|
||||
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 NewNotifyService(db *gorm.DB) NotifyServer {
|
||||
return ¬ifyServer{db: db}
|
||||
}
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
json2 "encoding/json"
|
||||
"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"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
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)
|
||||
|
||||
t := make(chan string)
|
||||
|
||||
go func() {
|
||||
str := httper2.Get(config.ServerInfo.ServerApi+"/token", nil)
|
||||
|
||||
t <- gjson.Get(str, "data").String()
|
||||
}()
|
||||
head["Authorization"] = <-t
|
||||
|
||||
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)
|
||||
|
||||
t := make(chan string)
|
||||
|
||||
go func() {
|
||||
str := httper2.Get(config.ServerInfo.ServerApi+"/token", nil)
|
||||
|
||||
t <- gjson.Get(str, "data").String()
|
||||
}()
|
||||
head["Authorization"] = <-t
|
||||
|
||||
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)
|
||||
|
||||
t := make(chan string)
|
||||
|
||||
go func() {
|
||||
str := httper2.Get(config.ServerInfo.ServerApi+"/token", nil)
|
||||
|
||||
t <- gjson.Get(str, "data").String()
|
||||
}()
|
||||
head["Authorization"] = <-t
|
||||
|
||||
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 NewOasisService() OasisService {
|
||||
return &oasisService{}
|
||||
}
|
||||
117
service/person.go
Normal file
117
service/person.go
Normal file
@@ -0,0 +1,117 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
||||
)
|
||||
|
||||
type PersonService interface {
|
||||
GetPersionInfo(token string) (m model.PersionModel, err error)
|
||||
Handshake(m model.ConnectState)
|
||||
}
|
||||
|
||||
type personService struct {
|
||||
}
|
||||
|
||||
var IpInfo model.PersionModel
|
||||
|
||||
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 (p *personService) Handshake(m model.ConnectState) {
|
||||
//1先进行udp打通成功
|
||||
|
||||
srcAddr := &net.UDPAddr{
|
||||
IP: net.IPv4zero, Port: 9901} //注意端口必须固定
|
||||
dstAddr := &net.UDPAddr{
|
||||
IP: net.ParseIP(config.ServerInfo.Handshake), Port: 9527}
|
||||
//DialTCP在网络协议net上连接本地地址laddr和远端地址raddr。net必须是"udp"、"udp4"、"udp6";如果laddr不是nil,将使用它作为本地地址,否则自动选择一个本地地址。
|
||||
//(conn)UDPConn代表一个UDP网络连接,实现了Conn和PacketConn接口
|
||||
conn, err := net.DialUDP("udp", srcAddr, dstAddr)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
b, _ := json.Marshal(m)
|
||||
if _, err = conn.Write(b); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
data := make([]byte, 1024)
|
||||
//ReadFromUDP从c读取一个UDP数据包,将有效负载拷贝到b,返回拷贝字节数和数据包来源地址。
|
||||
//ReadFromUDP方***在超过一个固定的时间点之后超时,并返回一个错误。
|
||||
n, _, err := conn.ReadFromUDP(data)
|
||||
if err != nil {
|
||||
fmt.Printf("error during read: %s", err)
|
||||
}
|
||||
conn.Close()
|
||||
toPersion := model.PersionModel{}
|
||||
err = json.Unmarshal(data[:n], &toPersion)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
// bidirectionHole(srcAddr, &anotherPeer)
|
||||
|
||||
//2udp打洞成功向服务器汇报打洞结果
|
||||
//3转udp打洞
|
||||
|
||||
}
|
||||
|
||||
func bidirectionHole(srcAddr *net.UDPAddr, anotherAddr *net.UDPAddr) {
|
||||
|
||||
conn, err := net.DialUDP("udp", srcAddr, anotherAddr)
|
||||
if err != nil {
|
||||
|
||||
fmt.Println("send handshake:", err)
|
||||
}
|
||||
go func() {
|
||||
for {
|
||||
time.Sleep(10 * time.Second)
|
||||
if _, err = conn.Write([]byte("from []")); err != nil {
|
||||
|
||||
log.Println("send msg fail", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
for {
|
||||
|
||||
data := make([]byte, 1024)
|
||||
n, _, err := conn.ReadFromUDP(data)
|
||||
if err != nil {
|
||||
|
||||
log.Printf("error during read:%s\n", err)
|
||||
} else {
|
||||
|
||||
log.Printf("收到数据:%s\n", data[:n])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func NewPersonService() PersonService {
|
||||
return &personService{}
|
||||
}
|
||||
@@ -2,11 +2,19 @@ package service
|
||||
|
||||
import (
|
||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/patrickmn/go-cache"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var Cache *cache.Cache
|
||||
|
||||
var MyService Repository
|
||||
|
||||
var WebSocketConns []*websocket.Conn
|
||||
|
||||
var SocketRun bool
|
||||
|
||||
type Repository interface {
|
||||
App() AppService
|
||||
DDNS() DDNSService
|
||||
@@ -15,7 +23,7 @@ type Repository interface {
|
||||
//Redis() RedisService
|
||||
ZeroTier() ZeroTierService
|
||||
ZiMa() ZiMaService
|
||||
OAPI() OasisService
|
||||
OAPI() CasaService
|
||||
Disk() DiskService
|
||||
Notify() NotifyServer
|
||||
ShareDirectory() ShareDirService
|
||||
@@ -24,19 +32,21 @@ type Repository interface {
|
||||
System() SystemService
|
||||
Shortcuts() ShortcutsService
|
||||
Search() SearchService
|
||||
Person() PersonService
|
||||
}
|
||||
|
||||
func NewService(db *gorm.DB, log loger2.OLog) Repository {
|
||||
|
||||
return &store{
|
||||
app: NewAppService(db, log),
|
||||
ddns: NewDDNSService(db, log),
|
||||
user: NewUserService(),
|
||||
docker: NewDcokerService(log),
|
||||
docker: NewDockerService(log),
|
||||
//redis: NewRedisService(rp),
|
||||
zerotier: NewZeroTierService(),
|
||||
zima: NewZiMaService(),
|
||||
oapi: NewOasisService(),
|
||||
disk: NewDiskService(log),
|
||||
disk: NewDiskService(log, db),
|
||||
notify: NewNotifyService(db),
|
||||
shareDirectory: NewShareDirService(db, log),
|
||||
task: NewTaskService(db, log),
|
||||
@@ -44,6 +54,7 @@ func NewService(db *gorm.DB, log loger2.OLog) Repository {
|
||||
system: NewSystemService(log),
|
||||
shortcuts: NewShortcutsService(db),
|
||||
search: NewSearchService(),
|
||||
person: NewPersonService(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +66,7 @@ type store struct {
|
||||
docker DockerService
|
||||
zerotier ZeroTierService
|
||||
zima ZiMaService
|
||||
oapi OasisService
|
||||
oapi CasaService
|
||||
disk DiskService
|
||||
notify NotifyServer
|
||||
shareDirectory ShareDirService
|
||||
@@ -64,6 +75,7 @@ type store struct {
|
||||
system SystemService
|
||||
shortcuts ShortcutsService
|
||||
search SearchService
|
||||
person PersonService
|
||||
}
|
||||
|
||||
func (c *store) Rely() RelyService {
|
||||
@@ -72,6 +84,9 @@ func (c *store) Rely() RelyService {
|
||||
func (c *store) Shortcuts() ShortcutsService {
|
||||
return c.shortcuts
|
||||
}
|
||||
func (c *store) Person() PersonService {
|
||||
return c.person
|
||||
}
|
||||
func (c *store) System() SystemService {
|
||||
return c.system
|
||||
}
|
||||
@@ -102,7 +117,7 @@ func (c *store) ZeroTier() ZeroTierService {
|
||||
func (c *store) ZiMa() ZiMaService {
|
||||
return c.zima
|
||||
}
|
||||
func (c *store) OAPI() OasisService {
|
||||
func (c *store) OAPI() CasaService {
|
||||
return c.oapi
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
@@ -10,18 +14,29 @@ type SystemService interface {
|
||||
UpSystemConfig(str string, widget string)
|
||||
UpdateSystemVersion(version string)
|
||||
GetSystemConfigDebug() []string
|
||||
GetCasaOSLogs(lineNumber int) string
|
||||
UpdateAssist()
|
||||
UpSystemPort(port string)
|
||||
GetTimeZone() string
|
||||
}
|
||||
type systemService struct {
|
||||
log loger.OLog
|
||||
}
|
||||
|
||||
func (s *systemService) UpdateSystemVersion(version string) {
|
||||
s.log.Error(version)
|
||||
//command2.OnlyExec(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version)
|
||||
//s.log.Error(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + 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))
|
||||
}
|
||||
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) GetSystemConfigDebug() []string {
|
||||
return command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetSysInfo")
|
||||
}
|
||||
@@ -34,7 +49,43 @@ func (s *systemService) UpSystemConfig(str string, widget string) {
|
||||
config.Cfg.Section("system").Key("WidgetList").SetValue(widget)
|
||||
config.SystemConfigInfo.WidgetList = widget
|
||||
}
|
||||
config.Cfg.SaveTo("conf/conf.ini")
|
||||
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 {
|
||||
file, err := os.Open(s.log.Path())
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
defer file.Close()
|
||||
content, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
|
||||
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 {
|
||||
return &systemService{log: log}
|
||||
|
||||
@@ -2,6 +2,8 @@ package service
|
||||
|
||||
import (
|
||||
json2 "encoding/json"
|
||||
"strconv"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||
@@ -9,7 +11,6 @@ import (
|
||||
"github.com/IceWhaleTech/CasaOS/types"
|
||||
"github.com/tidwall/gjson"
|
||||
"gorm.io/gorm"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type TaskService interface {
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"os"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
)
|
||||
|
||||
type UserService interface {
|
||||
@@ -20,15 +21,13 @@ func (c *user) SetUser(username, pwd, token, email, desc string) error {
|
||||
if len(username) > 0 {
|
||||
config.Cfg.Section("user").Key("UserName").SetValue(username)
|
||||
config.UserInfo.UserName = username
|
||||
config.Cfg.Section("user").Key("Initialized").SetValue("true")
|
||||
config.UserInfo.Initialized = true
|
||||
}
|
||||
if len(pwd) > 0 {
|
||||
config.Cfg.Section("user").Key("PWD").SetValue(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 {
|
||||
config.Cfg.Section("user").Key("Email").SetValue(email)
|
||||
config.UserInfo.Email = email
|
||||
@@ -37,7 +36,7 @@ func (c *user) SetUser(username, pwd, token, email, desc string) error {
|
||||
config.Cfg.Section("user").Key("Description").SetValue(desc)
|
||||
config.UserInfo.Description = desc
|
||||
}
|
||||
config.Cfg.SaveTo("conf/conf.ini")
|
||||
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -4,18 +4,20 @@ 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"
|
||||
"unicode"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
type ZeroTierService interface {
|
||||
@@ -33,21 +35,22 @@ type ZeroTierService interface {
|
||||
DeleteMember(token string, id, mId string) interface{}
|
||||
DeleteNetwork(token, id string) interface{}
|
||||
GetJoinNetworks() string
|
||||
NetworkIdFilter(letter rune) bool
|
||||
}
|
||||
type zerotierstruct struct {
|
||||
type zerotierStruct struct {
|
||||
}
|
||||
|
||||
var client http.Client
|
||||
|
||||
func (c *zerotierstruct) ZeroTierJoinNetwork(networkId string) {
|
||||
func (c *zerotierStruct) ZeroTierJoinNetwork(networkId string) {
|
||||
command2.OnlyExec(`zerotier-cli join ` + networkId)
|
||||
}
|
||||
func (c *zerotierstruct) ZeroTierLeaveNetwork(networkId string) {
|
||||
func (c *zerotierStruct) ZeroTierLeaveNetwork(networkId string) {
|
||||
command2.OnlyExec(`zerotier-cli leave ` + networkId)
|
||||
}
|
||||
|
||||
//登录并获取token
|
||||
func (c *zerotierstruct) GetToken(username, pwd string) string {
|
||||
func (c *zerotierStruct) GetToken(username, pwd string) string {
|
||||
if len(config.ZeroTierInfo.Token) > 0 {
|
||||
return config.ZeroTierInfo.Token
|
||||
} else {
|
||||
@@ -55,7 +58,7 @@ func (c *zerotierstruct) GetToken(username, pwd string) string {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *zerotierstruct) ZeroTierRegister(email, lastName, firstName, password string) string {
|
||||
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"
|
||||
|
||||
@@ -210,7 +213,7 @@ func ZeroTierGet(url string, cookies []*http.Cookie, t uint8) (action string, c
|
||||
}
|
||||
|
||||
//模拟提交表单
|
||||
func ZeroTierPost(str bytes.Buffer, action string, cookes []*http.Cookie, isLogin bool) (url, errInfo string, err error) {
|
||||
func ZeroTierPost(str bytes.Buffer, action string, cookies []*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")
|
||||
@@ -219,7 +222,7 @@ func ZeroTierPost(str bytes.Buffer, action string, cookes []*http.Cookie, isLogi
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
for _, cookie := range cookes {
|
||||
for _, cookie := range cookies {
|
||||
req.AddCookie(cookie)
|
||||
}
|
||||
res, err := client.Do(req)
|
||||
@@ -273,71 +276,78 @@ func ZeroTierPost(str bytes.Buffer, action string, cookes []*http.Cookie, isLogi
|
||||
}
|
||||
|
||||
//获取zerotile网络列表和本地用户已加入的网络
|
||||
func (c *zerotierstruct) ZeroTierNetworkList(token string) (interface{}, []string) {
|
||||
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) {
|
||||
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{} {
|
||||
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{} {
|
||||
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{} {
|
||||
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{} {
|
||||
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{} {
|
||||
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{} {
|
||||
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{} {
|
||||
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 {
|
||||
func (c *zerotierStruct) GetJoinNetworks() string {
|
||||
json := command2.ExecResultStr("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetLocalJoinNetworks")
|
||||
return json
|
||||
}
|
||||
|
||||
func (c *zerotierStruct) NetworkIdFilter(letter rune) bool {
|
||||
if unicode.IsNumber(letter) || unicode.IsLetter(letter) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
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{}
|
||||
return &zerotierStruct{}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/IceWhaleTech/CasaOS/model"
|
||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||
@@ -84,12 +85,12 @@ func (c *zima) GetDirPath(path string) []model.Path {
|
||||
ls, _ := ioutil.ReadDir(path)
|
||||
dirs := []model.Path{}
|
||||
|
||||
if strings.Count(path, "/") > 1 {
|
||||
if len(path) > 0 {
|
||||
for _, l := range ls {
|
||||
dirs = append(dirs, model.Path{Name: l.Name(), Path: path + l.Name() + "/", IsDir: l.IsDir()})
|
||||
dirs = append(dirs, model.Path{Name: l.Name(), Path: path + "/" + l.Name(), IsDir: l.IsDir(), Date: l.ModTime()})
|
||||
}
|
||||
} 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
|
||||
}
|
||||
@@ -116,7 +117,6 @@ func (c *zima) GetNetState(name string) string {
|
||||
|
||||
//网络信息
|
||||
func (c *zima) GetNetInfo() []net.IOCountersStat {
|
||||
//loger.Error("输出个内容试试")
|
||||
parts, _ := net.IOCounters(true)
|
||||
//fmt.Println(net.ConntrackStatsWithContext(true))
|
||||
return parts
|
||||
@@ -131,6 +131,8 @@ func (c *zima) MkdirAll(path string) (int, error) {
|
||||
if os.IsNotExist(err) {
|
||||
os.MkdirAll(path, os.ModePerm)
|
||||
return oasis_err.SUCCESS, nil
|
||||
} else if strings.Contains(err.Error(), ": not a directory") {
|
||||
return oasis_err.FILE_OR_DIR_EXISTS, err
|
||||
}
|
||||
}
|
||||
return oasis_err.ERROR, err
|
||||
@@ -140,7 +142,7 @@ func (c *zima) MkdirAll(path string) (int, error) {
|
||||
func (c *zima) CreateFile(path string) (int, error) {
|
||||
_, err := os.Stat(path)
|
||||
if err == nil {
|
||||
return oasis_err.DIR_ALREADY_EXISTS, nil
|
||||
return oasis_err.FILE_OR_DIR_EXISTS, nil
|
||||
} else {
|
||||
if os.IsNotExist(err) {
|
||||
file.CreateFile(path)
|
||||
|
||||
40
shell/assist.sh
Normal file
40
shell/assist.sh
Normal file
@@ -0,0 +1,40 @@
|
||||
#!/bin/bash
|
||||
|
||||
#add in v0.2.3
|
||||
version_0_2_3() {
|
||||
((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/
|
||||
|
||||
}
|
||||
|
||||
# add in v0.2.5
|
||||
|
||||
readonly CASA_DEPANDS="curl smartmontools parted fdisk ntfs-3g"
|
||||
|
||||
version_0_2_5() {
|
||||
install_depends "$CASA_DEPANDS"
|
||||
}
|
||||
|
||||
|
||||
#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_3
|
||||
|
||||
version_0_2_5
|
||||
206
shell/helper.sh
206
shell/helper.sh
@@ -30,6 +30,11 @@ GetNetCard() {
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
GetTimeZone(){
|
||||
timedatectl | grep "Time zone" | awk '{print $3}'
|
||||
}
|
||||
|
||||
#查看网卡状态
|
||||
#param 网卡名称
|
||||
CatNetCardState() {
|
||||
@@ -68,10 +73,8 @@ UMountPorintAndRemoveDir() {
|
||||
if [[ -z ${MOUNT_POINT} ]]; then
|
||||
${log} "Warning: ${DEVICE} is not mounted"
|
||||
else
|
||||
umount -l ${DEVICE}
|
||||
${log} "Unmounted ${DEVICE} from ${MOUNT_POINT}"
|
||||
umount -lf ${DEVICE}
|
||||
/bin/rmdir "${MOUNT_POINT}"
|
||||
sed -i.bak "\@${MOUNT_POINT}@d" /var/log/usb-mount.track
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -84,11 +87,11 @@ FormatDisk() {
|
||||
elif [ "$2" == "ntfs" ]; then
|
||||
mkfs.ntfs $1
|
||||
elif [ "$2" == "ext4" ]; then
|
||||
mkfs.ext4 -F $1
|
||||
mkfs.ext4 -m 1 -F $1
|
||||
elif [ "$2" == "exfat" ]; then
|
||||
mkfs.exfat $1
|
||||
else
|
||||
mkfs.ext4 -F $1
|
||||
mkfs.ext4 -m 1 -F $1
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -103,20 +106,20 @@ DelPartition() {
|
||||
EOF
|
||||
}
|
||||
|
||||
#添加分区
|
||||
#添加分区只有一个分区
|
||||
#param 路径 /dev/sdb
|
||||
#param 磁盘号 最大128
|
||||
#param 磁盘大小 字节 512*2048=1024kb=1M
|
||||
#param 要挂载的目录
|
||||
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%
|
||||
PATH=`lsblk -r $1 | sort | grep part | head -n 1 | awk '{print $1}'`
|
||||
mkfs.ext4 -m 1 /dev/${PATH}
|
||||
|
||||
partprobe $1
|
||||
|
||||
}
|
||||
|
||||
#磁盘类型
|
||||
@@ -141,17 +144,184 @@ GetDiskHealthState() {
|
||||
#result bytes
|
||||
#result sectors
|
||||
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
|
||||
#result start,end,sectors
|
||||
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 "Storage[0-9]" | awk '/^d/ {print $NF}')
|
||||
for i in $dir; do
|
||||
|
||||
path="$DIRECTORY$i"
|
||||
mountStr=$(mountpoint $path)
|
||||
notMountpoint="is not a mountpoint"
|
||||
if [[ $mountStr =~ $notMountpoint ]]; then
|
||||
if [ "$(ls -A $path)" = "" ]; then
|
||||
rm -fr $path
|
||||
else
|
||||
echo "$path is not empty"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
#重载samba服务
|
||||
ReloadSamba() {
|
||||
/etc/init.d/smbd reload
|
||||
}
|
||||
|
||||
# $1=sda1
|
||||
# $2=volume{1}
|
||||
do_mount() {
|
||||
DEVBASE=$1
|
||||
DEVICE="${DEVBASE}"
|
||||
# See if this drive is already mounted, and if so where
|
||||
MOUNT_POINT=$(lsblk -o name,mountpoint | grep ${DEVICE} | awk '{print $2}')
|
||||
|
||||
if [ -n "${MOUNT_POINT}" ]; then
|
||||
${log} "Warning: ${DEVICE} is already mounted at ${MOUNT_POINT}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get info for this drive: $ID_FS_LABEL and $ID_FS_TYPE
|
||||
eval $(blkid -o udev ${DEVICE} | grep -i -e "ID_FS_LABEL" -e "ID_FS_TYPE")
|
||||
|
||||
LABEL=$2
|
||||
if grep -q " ${LABEL} " /etc/mtab; then
|
||||
# Already in use, make a unique one
|
||||
LABEL+="-${DEVBASE}"
|
||||
fi
|
||||
DEV_LABEL="${LABEL}"
|
||||
|
||||
# Use the device name in case the drive doesn't have label
|
||||
if [ -z ${DEV_LABEL} ]; then
|
||||
DEV_LABEL="${DEVBASE}"
|
||||
fi
|
||||
|
||||
MOUNT_POINT="${DEV_LABEL}"
|
||||
|
||||
${log} "Mount point: ${MOUNT_POINT}"
|
||||
|
||||
mkdir -p ${MOUNT_POINT}
|
||||
|
||||
case ${ID_FS_TYPE} in
|
||||
vfat)
|
||||
mount -t vfat -o rw,relatime,users,gid=100,umask=000,shortname=mixed,utf8=1,flush ${DEVICE} ${MOUNT_POINT}
|
||||
;;
|
||||
ext[2-4])
|
||||
mount -o noatime ${DEVICE} ${MOUNT_POINT} >/dev/null 2>&1
|
||||
;;
|
||||
exfat)
|
||||
mount -t exfat ${DEVICE} ${MOUNT_POINT} >/dev/null 2>&1
|
||||
;;
|
||||
ntfs)
|
||||
ntfs-3g ${DEVICE} ${MOUNT_POINT}
|
||||
;;
|
||||
iso9660)
|
||||
mount -t iso9660 ${DEVICE} ${MOUNT_POINT}
|
||||
;;
|
||||
*)
|
||||
/bin/rmdir "${MOUNT_POINT}"
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# $1=sda1
|
||||
do_umount() {
|
||||
log="logger -t usb-mount.sh -s "
|
||||
DEVBASE=$1
|
||||
DEVICE="${DEVBASE}"
|
||||
MOUNT_POINT=$(mount | grep ${DEVICE} | awk '{ print $3 }')
|
||||
|
||||
if [[ -z ${MOUNT_POINT} ]]; then
|
||||
${log} "Warning: ${DEVICE} is not mounted"
|
||||
else
|
||||
umount -l ${DEVICE}
|
||||
${log} "Unmounted ${DEVICE} from ${MOUNT_POINT}"
|
||||
/bin/rmdir "${MOUNT_POINT}"
|
||||
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
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ show() {
|
||||
}
|
||||
|
||||
run_external_script() {
|
||||
show 0 "run_external_script"
|
||||
assist.sh
|
||||
}
|
||||
|
||||
update() {
|
||||
@@ -99,13 +99,13 @@ update() {
|
||||
target_arch="386"
|
||||
;;
|
||||
*armv5*)
|
||||
target_arch="armv5"
|
||||
target_arch="arm-5"
|
||||
;;
|
||||
*armv6*)
|
||||
target_arch="armv6"
|
||||
target_arch="arm-6"
|
||||
;;
|
||||
*armv7*)
|
||||
target_arch="armv7"
|
||||
target_arch="arm-7"
|
||||
;;
|
||||
*)
|
||||
show 1 "Aborted, unsupported or unknown architecture: $unamem"
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
|
||||
# copy to /oasis/util/shell path
|
||||
# copy to /casaOS/util/shell path
|
||||
# chmod 755
|
||||
|
||||
log="logger -t usb-mount.sh -s "
|
||||
|
||||
${log} "变量:$1 $2"
|
||||
|
||||
ACTION=$1
|
||||
|
||||
DEVBASE=$2
|
||||
@@ -14,14 +12,14 @@ DEVBASE=$2
|
||||
DEVICE="/dev/${DEVBASE}"
|
||||
|
||||
# See if this drive is already mounted, and if so where
|
||||
MOUNT_POINT=$(mount | grep ${DEVICE} | awk '{ print $3 }')
|
||||
MOUNT_POINT=$(lsblk -o name,mountpoint | grep ${DEVICE} | awk '{print $2}')
|
||||
|
||||
do_mount() {
|
||||
|
||||
if [[ -n ${MOUNT_POINT} ]]; then
|
||||
if [ -n "${MOUNT_POINT}" ]; then
|
||||
${log} "Warning: ${DEVICE} is already mounted at ${MOUNT_POINT}"
|
||||
exit 1
|
||||
fib
|
||||
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")
|
||||
@@ -32,23 +30,32 @@ do_mount() {
|
||||
|
||||
# Figure out a mount point to use
|
||||
# LABEL=${ID_FS_LABEL}
|
||||
LABEL=${DEVBASE}
|
||||
if grep -q " /media/${LABEL} " /etc/mtab; then
|
||||
# Already in use, make a unique one
|
||||
LABEL+="-${DEVBASE}"
|
||||
fi
|
||||
DEV_LABEL="${LABEL}"
|
||||
# LABEL=${DEVBASE}
|
||||
# if grep -q " /DATA/USB_${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
|
||||
# # Use the device name in case the drive doesn't have label
|
||||
# if [ -z ${DEV_LABEL} ]; then
|
||||
# DEV_LABEL="${DEVBASE}"
|
||||
# fi
|
||||
|
||||
MOUNT_POINT="/media/${DEV_LABEL}"
|
||||
MOUNT_POINT="/DATA/USB_Storage1"
|
||||
arr=("/DATA/USB_Storage1" "/DATA/USB_Storage2" "/DATA/USB_Storage3" "/DATA/USB_Storage4" "/DATA/USB_Storage5" "/DATA/USB_Storage6" "/DATA/USB_Storage7" "/DATA/USB_Storage8" "/DATA/USB_Storage9" "/DATA/USB_Storage10" "/DATA/USB_Storage11" "/DATA/USB_Storage12")
|
||||
for folder in ${arr[@]}; do
|
||||
#如果文件夹不存在,创建文件夹
|
||||
if [ ! -d "$folder" ]; then
|
||||
mkdir -p ${folder}
|
||||
MOUNT_POINT=$folder
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
${log} "Mount point: ${MOUNT_POINT}"
|
||||
|
||||
mkdir -p ${MOUNT_POINT}
|
||||
|
||||
|
||||
# # Global mount options
|
||||
# OPTS="rw,relatime"
|
||||
@@ -86,7 +93,7 @@ do_mount() {
|
||||
mount -t iso9660 ${DEVICE} ${MOUNT_POINT}
|
||||
;;
|
||||
*)
|
||||
/bin/rmdir "${MOUNT_POINT}"
|
||||
/bin/rmdir "${MOUNT_POINT}"
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -4,5 +4,5 @@ Description=Mount USB Drive on %i
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=true
|
||||
ExecStart=/oasis/util/shell/usb-mount.sh add %i
|
||||
ExecStop=/oasis/util/shell/usb-mount.sh remove %i
|
||||
ExecStart=/casaOS/server/shell/usb-mount.sh add %i
|
||||
ExecStop=/casaOS/server/shell/usb-mount.sh remove %i
|
||||
|
||||
BIN
snapshot-mobile.png
Normal file
BIN
snapshot-mobile.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
BIN
snapshot.png
Normal file
BIN
snapshot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 MiB |
@@ -11,3 +11,7 @@ const (
|
||||
NOTIFY_TYPE_ERROR
|
||||
NOTIFY_TYPE_INSTALL_LOG
|
||||
)
|
||||
|
||||
const (
|
||||
NOTIFY_APP = iota
|
||||
)
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
package types
|
||||
|
||||
const CURRENTVERSION = "0.1.5"
|
||||
const BODY = `
|
||||
<li>Add CPU RAM Status with widget</li>
|
||||
<li>Add Disk Info with widget</li>
|
||||
<li>Enhance the Docker cli import experience and automatically fill in the folders that need to be mounted</li>
|
||||
<li>Realize automatic loading of widgets</li>
|
||||
<li>Fix display bugs when windows size less than 1024px</li>
|
||||
`
|
||||
const CURRENTVERSION = "0.2.9"
|
||||
|
||||
const BODY = "<li>Custom installation of new parameters</li><li>Fixed issues</li><li>Update front-end translation</li>"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user