🧶 feat: Big job! kubernetes Deployment Design (#1055)
* fix: fix docker compose file Signed-off-by: Xinwei Xiong(cubxxw-openim) <3293172751nss@gmail.com> * feat: add options about helm deploy Signed-off-by: Xinwei Xiong(cubxxw-openim) <3293172751nss@gmail.com> * feat: add openim server test about openim web Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com> * feat: add openim server test about openim web Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com> * feat: add openim server test about openim web Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com> * feat: add openim test: Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com> * feat: add openim test: Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com> * fix: fix env api url Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com> * fix: fix openim server deployment Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com> * fix: fix openim server deployment Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com> * feat: add openim task list Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com> * feat: remove openim config Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com> * feat: remote tools imctl * feat: add tools imctl * feat: add tools imctl * feat: add config * feat: add config * feat: add openim config * feat: add openim config --------- Signed-off-by: Xinwei Xiong(cubxxw-openim) <3293172751nss@gmail.com> Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>pull/1142/head
parent
80064620b9
commit
f198317ce7
@ -0,0 +1,40 @@
|
||||
# Version logging for OpenIM
|
||||
|
||||
<!-- BEGIN MUNGE: GENERATED_TOC -->
|
||||
|
||||
<!-- END MUNGE: GENERATED_TOC -->
|
||||
|
||||
<a name="unreleased"></a>
|
||||
## [Unreleased]
|
||||
|
||||
|
||||
<a name="v3.3.1"></a>
|
||||
## [v3.3.1] - 2023-09-13
|
||||
|
||||
<a name="v3.3.1-beta.0"></a>
|
||||
## [v3.3.1-beta.0] - 2023-09-11
|
||||
|
||||
<a name="v3.3.0-rc.1"></a>
|
||||
## [v3.3.0-rc.1] - 2023-09-11
|
||||
|
||||
<a name="v3.3.0-rc.12"></a>
|
||||
## [v3.3.0-rc.12] - 2023-09-11
|
||||
|
||||
<a name="v3.3.0"></a>
|
||||
## [v3.3.0] - 2023-09-09
|
||||
|
||||
<a name="v3.3.0-rc.0"></a>
|
||||
## v3.3.0-rc.0 - 2023-09-07
|
||||
### Reverts
|
||||
- update etcd to v3.5.2 ([#206](https://github.com/openimsdk/open-im-server/issues/206))
|
||||
|
||||
### Pull Requests
|
||||
- Merge branch 'tuoyun'
|
||||
|
||||
|
||||
[Unreleased]: https://github.com/openimsdk/open-im-server/compare/v3.3.1...HEAD
|
||||
[v3.3.1]: https://github.com/openimsdk/open-im-server/compare/v3.3.1-beta.0...v3.3.1
|
||||
[v3.3.1-beta.0]: https://github.com/openimsdk/open-im-server/compare/v3.3.0-rc.1...v3.3.1-beta.0
|
||||
[v3.3.0-rc.1]: https://github.com/openimsdk/open-im-server/compare/v3.3.0-rc.12...v3.3.0-rc.1
|
||||
[v3.3.0-rc.12]: https://github.com/openimsdk/open-im-server/compare/v3.3.0...v3.3.0-rc.12
|
||||
[v3.3.0]: https://github.com/openimsdk/open-im-server/compare/v3.3.0-rc.0...v3.3.0
|
@ -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.
|
@ -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.
|
After Width: | Height: | Size: 65 KiB |
@ -0,0 +1,64 @@
|
||||
# Copyright © 2023 OpenIMSDK.
|
||||
#
|
||||
# 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.
|
||||
|
||||
# ==============================================================================
|
||||
# For the entire design of.gitignore, ignore git commits and ignore files
|
||||
#===============================================================================
|
||||
#
|
||||
|
||||
### OpenIM developer supplement ###
|
||||
logs
|
||||
.devcontainer
|
||||
components
|
||||
out-test
|
||||
Dockerfile.cross
|
||||
|
||||
### Makefile ###
|
||||
tmp/
|
||||
bin/
|
||||
output/
|
||||
_output/
|
||||
|
||||
### OpenIM Config ###
|
||||
config/config.yaml
|
||||
./config/config.yaml
|
||||
.env
|
||||
./.env
|
||||
|
||||
### OpenIM deploy ###
|
||||
deploy/openim_demo
|
||||
deploy/openim-api
|
||||
deploy/openim-rpc-msg_gateway
|
||||
deploy/openim-msgtransfer
|
||||
deploy/openim-push
|
||||
deploy/openim_timer_task
|
||||
deploy/openim-rpc-user
|
||||
deploy/openim-rpc-friend
|
||||
deploy/openim-rpc-group
|
||||
deploy/openim-rpc-msg
|
||||
deploy/openim-rpc-auth
|
||||
deploy/Open-IM-SDK-Core
|
||||
|
||||
# files used by the developer
|
||||
.idea.md
|
||||
.todo.md
|
||||
.note.md
|
||||
|
||||
# ==============================================================================
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/go,git,vim,tags,test,emacs,backup,jetbrains
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=go,git,vim,tags,test,emacs,backup,jetbrains
|
||||
|
||||
cmd/
|
||||
internal/
|
||||
pkg/
|
@ -1,49 +0,0 @@
|
||||
# OpenIM `man` Module README
|
||||
|
||||
Welcome to the `man` module of OpenIM, the comprehensive guide for using OpenIM's range of powerful commands. Here, you'll find in-depth details for each command, its options, and examples to help you harness the full power of the OpenIM suite.
|
||||
|
||||
## Overview
|
||||
|
||||
OpenIM is a robust instant messaging solution. To ensure users can effectively harness its capabilities, OpenIM provides a suite of commands that serve different functionalities, from the API level to RPC calls and utilities.
|
||||
|
||||
The `man` module ensures that users, both new and experienced, have a reliable source of information and documentation to use these commands effectively.
|
||||
|
||||
## Available Commands
|
||||
|
||||
The OpenIM commands are divided into core services and tools. Below is a brief overview of each:
|
||||
|
||||
### Core Services
|
||||
|
||||
- **openim-api**: Interface to the main functionalities of OpenIM.
|
||||
- **openim-cmdutils**: Utilities for executing common tasks.
|
||||
- **openim-crontask**: Schedule and manage routine tasks within OpenIM.
|
||||
- **openim-msggateway**: Gateway for managing messages within the OpenIM system.
|
||||
- **openim-msgtransfer**: Handle message transfers across different parts of OpenIM.
|
||||
- **openim-push**: Service for pushing notifications and updates.
|
||||
- **openim-rpc-auth**: RPC interface for authentication tasks.
|
||||
- **openim-rpc-conversation**: RPC service for handling conversations.
|
||||
- **openim-rpc-friend**: Manage friend lists and related functionalities through RPC.
|
||||
- **openim-rpc-group**: Group management via RPC.
|
||||
- **openim-rpc-msg**: Message handling at the RPC level.
|
||||
- **openim-rpc-third**: Third-party integrations and related tasks through RPC.
|
||||
- **openim-rpc-user**: User management and tasks via RPC.
|
||||
|
||||
### Tools
|
||||
|
||||
- **changelog**: Track and manage changes in OpenIM.
|
||||
- **component**: Utilities related to different components within OpenIM.
|
||||
- **infra**: Infrastructure and backend management tools.
|
||||
- **ncpu**: Monitor and manage CPU usage and related tasks.
|
||||
- **yamlfmt**: A tool for formatting and linting YAML files within the OpenIM configuration.
|
||||
|
||||
## How to Use
|
||||
|
||||
To view the manual page for any of the OpenIM commands, use the `man` command followed by the command name. For example:
|
||||
|
||||
```
|
||||
man openim-api
|
||||
```
|
||||
|
||||
## Contributions
|
||||
|
||||
We welcome contributions to enhance the `man` pages. If you discover inconsistencies, errors, or areas where further details are required, feel free to raise an issue or submit a pull request.
|
@ -1,62 +0,0 @@
|
||||
// Copyright © 2023 OpenIM. All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"k8s.io/kubernetes/cmd/genutils"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// TODO use os.Args instead of "flags" because "flags" will mess up the man pages!
|
||||
path := "docs/man/man1"
|
||||
module := ""
|
||||
if len(os.Args) == 3 {
|
||||
path = os.Args[1]
|
||||
module = os.Args[2]
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "usage: %s [output directory] [module] \n", os.Args[0])
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
outDir, err := genutils.OutDir(path)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "failed to get output directory: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Set environment variables used by command so the output is consistent,
|
||||
// regardless of where we run.
|
||||
os.Setenv("HOME", "/home/username")
|
||||
|
||||
// openim-api
|
||||
// openim-cmdutils
|
||||
// openim-crontask
|
||||
// openim-msggateway
|
||||
// openim-msgtransfer
|
||||
// openim-push
|
||||
// openim-rpc-auth
|
||||
// openim-rpc-conversation
|
||||
// openim-rpc-friend
|
||||
// openim-rpc-group
|
||||
// openim-rpc-msg
|
||||
// openim-rpc-third
|
||||
// openim-rpc-user
|
||||
switch module {
|
||||
case "openim-api":
|
||||
}
|
||||
}
|
@ -1,243 +0,0 @@
|
||||
// Copyright © 2023 OpenIM. All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
package genericclioptions
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/AlekSi/pointer"
|
||||
"github.com/marmotedu/marmotedu-sdk-go/rest"
|
||||
"github.com/marmotedu/marmotedu-sdk-go/tools/clientcmd"
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// Defines flag for imctl.
|
||||
const (
|
||||
FlagIMConfig = "imconfig"
|
||||
FlagBearerToken = "user.token"
|
||||
FlagUsername = "user.username"
|
||||
FlagPassword = "user.password"
|
||||
FlagSecretID = "user.secret-id"
|
||||
FlagSecretKey = "user.secret-key"
|
||||
FlagCertFile = "user.client-certificate"
|
||||
FlagKeyFile = "user.client-key"
|
||||
FlagTLSServerName = "server.tls-server-name"
|
||||
FlagInsecure = "server.insecure-skip-tls-verify"
|
||||
FlagCAFile = "server.certificate-authority"
|
||||
FlagAPIServer = "server.address"
|
||||
FlagTimeout = "server.timeout"
|
||||
FlagMaxRetries = "server.max-retries"
|
||||
FlagRetryInterval = "server.retry-interval"
|
||||
)
|
||||
|
||||
// RESTClientGetter is an interface that the ConfigFlags describe to provide an easier way to mock for commands
|
||||
// and eliminate the direct coupling to a struct type. Users may wish to duplicate this type in their own packages
|
||||
// as per the golang type overlapping.
|
||||
type RESTClientGetter interface {
|
||||
// ToRESTConfig returns restconfig
|
||||
ToRESTConfig() (*rest.Config, error)
|
||||
// ToRawIMConfigLoader return imconfig loader as-is
|
||||
ToRawIMConfigLoader() clientcmd.ClientConfig
|
||||
}
|
||||
|
||||
var _ RESTClientGetter = &ConfigFlags{}
|
||||
|
||||
// ConfigFlags composes the set of values necessary
|
||||
// for obtaining a REST client config.
|
||||
type ConfigFlags struct {
|
||||
IMConfig *string
|
||||
|
||||
BearerToken *string
|
||||
Username *string
|
||||
Password *string
|
||||
SecretID *string
|
||||
SecretKey *string
|
||||
|
||||
Insecure *bool
|
||||
TLSServerName *string
|
||||
CertFile *string
|
||||
KeyFile *string
|
||||
CAFile *string
|
||||
|
||||
APIServer *string
|
||||
Timeout *time.Duration
|
||||
MaxRetries *int
|
||||
RetryInterval *time.Duration
|
||||
|
||||
clientConfig clientcmd.ClientConfig
|
||||
lock sync.Mutex
|
||||
// If set to true, will use persistent client config and
|
||||
// propagate the config to the places that need it, rather than
|
||||
// loading the config multiple times
|
||||
usePersistentConfig bool
|
||||
}
|
||||
|
||||
// ToRESTConfig implements RESTClientGetter.
|
||||
// Returns a REST client configuration based on a provided path
|
||||
// to a .imconfig file, loading rules, and config flag overrides.
|
||||
// Expects the AddFlags method to have been called.
|
||||
func (f *ConfigFlags) ToRESTConfig() (*rest.Config, error) {
|
||||
return f.ToRawIMConfigLoader().ClientConfig()
|
||||
}
|
||||
|
||||
// ToRawIMConfigLoader binds config flag values to config overrides
|
||||
// Returns an interactive clientConfig if the password flag is enabled,
|
||||
// or a non-interactive clientConfig otherwise.
|
||||
func (f *ConfigFlags) ToRawIMConfigLoader() clientcmd.ClientConfig {
|
||||
if f.usePersistentConfig {
|
||||
return f.toRawIMPersistentConfigLoader()
|
||||
}
|
||||
|
||||
return f.toRawIMConfigLoader()
|
||||
}
|
||||
|
||||
func (f *ConfigFlags) toRawIMConfigLoader() clientcmd.ClientConfig {
|
||||
config := clientcmd.NewConfig()
|
||||
if err := viper.Unmarshal(&config); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return clientcmd.NewClientConfigFromConfig(config)
|
||||
}
|
||||
|
||||
// toRawIMPersistentConfigLoader binds config flag values to config overrides
|
||||
// Returns a persistent clientConfig for propagation.
|
||||
func (f *ConfigFlags) toRawIMPersistentConfigLoader() clientcmd.ClientConfig {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
if f.clientConfig == nil {
|
||||
f.clientConfig = f.toRawIMConfigLoader()
|
||||
}
|
||||
|
||||
return f.clientConfig
|
||||
}
|
||||
|
||||
// AddFlags binds client configuration flags to a given flagset.
|
||||
func (f *ConfigFlags) AddFlags(flags *pflag.FlagSet) {
|
||||
if f.IMConfig != nil {
|
||||
flags.StringVar(f.IMConfig, FlagIMConfig, *f.IMConfig,
|
||||
fmt.Sprintf("Path to the %s file to use for CLI requests", FlagIMConfig))
|
||||
}
|
||||
|
||||
if f.BearerToken != nil {
|
||||
flags.StringVar(
|
||||
f.BearerToken,
|
||||
FlagBearerToken,
|
||||
*f.BearerToken,
|
||||
"Bearer token for authentication to the API server",
|
||||
)
|
||||
}
|
||||
|
||||
if f.Username != nil {
|
||||
flags.StringVar(f.Username, FlagUsername, *f.Username, "Username for basic authentication to the API server")
|
||||
}
|
||||
|
||||
if f.Password != nil {
|
||||
flags.StringVar(f.Password, FlagPassword, *f.Password, "Password for basic authentication to the API server")
|
||||
}
|
||||
|
||||
if f.SecretID != nil {
|
||||
flags.StringVar(f.SecretID, FlagSecretID, *f.SecretID, "SecretID for JWT authentication to the API server")
|
||||
}
|
||||
|
||||
if f.SecretKey != nil {
|
||||
flags.StringVar(f.SecretKey, FlagSecretKey, *f.SecretKey, "SecretKey for jwt authentication to the API server")
|
||||
}
|
||||
|
||||
if f.CertFile != nil {
|
||||
flags.StringVar(f.CertFile, FlagCertFile, *f.CertFile, "Path to a client certificate file for TLS")
|
||||
}
|
||||
if f.KeyFile != nil {
|
||||
flags.StringVar(f.KeyFile, FlagKeyFile, *f.KeyFile, "Path to a client key file for TLS")
|
||||
}
|
||||
if f.TLSServerName != nil {
|
||||
flags.StringVar(f.TLSServerName, FlagTLSServerName, *f.TLSServerName, ""+
|
||||
"Server name to use for server certificate validation. If it is not provided, the hostname used to contact the server is used")
|
||||
}
|
||||
if f.Insecure != nil {
|
||||
flags.BoolVar(f.Insecure, FlagInsecure, *f.Insecure, ""+
|
||||
"If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure")
|
||||
}
|
||||
if f.CAFile != nil {
|
||||
flags.StringVar(f.CAFile, FlagCAFile, *f.CAFile, "Path to a cert file for the certificate authority")
|
||||
}
|
||||
|
||||
if f.APIServer != nil {
|
||||
flags.StringVarP(f.APIServer, FlagAPIServer, "s", *f.APIServer, "The address and port of the IM API server")
|
||||
}
|
||||
|
||||
if f.Timeout != nil {
|
||||
flags.DurationVar(
|
||||
f.Timeout,
|
||||
FlagTimeout,
|
||||
*f.Timeout,
|
||||
"The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests.",
|
||||
)
|
||||
}
|
||||
|
||||
if f.MaxRetries != nil {
|
||||
flag.IntVar(f.MaxRetries, FlagMaxRetries, *f.MaxRetries, "Maximum number of retries.")
|
||||
}
|
||||
|
||||
if f.RetryInterval != nil {
|
||||
flags.DurationVar(
|
||||
f.RetryInterval,
|
||||
FlagRetryInterval,
|
||||
*f.RetryInterval,
|
||||
"The interval time between each attempt.",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// WithDeprecatedPasswordFlag enables the username and password config flags.
|
||||
func (f *ConfigFlags) WithDeprecatedPasswordFlag() *ConfigFlags {
|
||||
f.Username = pointer.ToString("")
|
||||
f.Password = pointer.ToString("")
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
// WithDeprecatedSecretFlag enables the secretID and secretKey config flags.
|
||||
func (f *ConfigFlags) WithDeprecatedSecretFlag() *ConfigFlags {
|
||||
f.SecretID = pointer.ToString("")
|
||||
f.SecretKey = pointer.ToString("")
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
// NewConfigFlags returns ConfigFlags with default values set.
|
||||
func NewConfigFlags(usePersistentConfig bool) *ConfigFlags {
|
||||
return &ConfigFlags{
|
||||
IMConfig: pointer.ToString(""),
|
||||
|
||||
BearerToken: pointer.ToString(""),
|
||||
Insecure: pointer.ToBool(false),
|
||||
TLSServerName: pointer.ToString(""),
|
||||
CertFile: pointer.ToString(""),
|
||||
KeyFile: pointer.ToString(""),
|
||||
CAFile: pointer.ToString(""),
|
||||
|
||||
APIServer: pointer.ToString(""),
|
||||
Timeout: pointer.ToDuration(30 * time.Second),
|
||||
MaxRetries: pointer.ToInt(0),
|
||||
RetryInterval: pointer.ToDuration(1 * time.Second),
|
||||
usePersistentConfig: usePersistentConfig,
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
// Copyright © 2023 OpenIM. All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// iactl is the command line tool for openim platform.
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/tools/imctl/internal/imctl/cmd"
|
||||
)
|
||||
|
||||
func main() {
|
||||
command := cmd.NewDefaultIMCtlCommand()
|
||||
if err := command.Execute(); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
@ -1,146 +0,0 @@
|
||||
// Copyright © 2023 OpenIM. All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
cliflag "github.com/openimsdk/component-base/pkg/cli/flag"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/pkg/cli/genericclioptions"
|
||||
|
||||
cmdutil "github.com/openimsdk/open-im-server/tools/imctl/inernal/iamctl/cmd/util"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/internal/imctl/cmd/color"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/internal/imctl/cmd/completion"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/internal/imctl/cmd/info"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/internal/imctl/cmd/jwt"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/internal/imctl/cmd/new"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/internal/imctl/cmd/options"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/internal/imctl/cmd/policy"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/internal/imctl/cmd/secret"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/internal/imctl/cmd/set"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/internal/imctl/cmd/user"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/internal/imctl/cmd/validate"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/internal/imctl/cmd/version"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/internal/imctl/util/templates"
|
||||
genericapiserver "github.com/openimsdk/open-im-server/tools/imctl/internal/pkg/server"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/pkg/cli/genericclioptions"
|
||||
)
|
||||
|
||||
// NewDefaultIAMCtlCommand creates the `imctl` command with default arguments.
|
||||
func NewDefaultIMCtlCommand() *cobra.Command {
|
||||
return NewIMCtlCommand(os.Stdin, os.Stdout, os.Stderr)
|
||||
}
|
||||
|
||||
// NewIAMCtlCommand returns new initialized instance of 'imctl' root command.
|
||||
func NewIMCtlCommand(in io.Reader, out, err io.Writer) *cobra.Command {
|
||||
// Parent command to which all subcommands are added.
|
||||
cmds := &cobra.Command{
|
||||
Use: "imctl",
|
||||
Short: "imctl controls the IM platform",
|
||||
Long: templates.LongDesc(`
|
||||
imctl controls the IM platform, is the client side tool for IM platform.
|
||||
|
||||
Find more information at:
|
||||
// TODO: add link to docs, from auto scripts and gendocs
|
||||
https://github.com/openimsdk/open-im-server/tree/main/docs`),
|
||||
Run: runHelp,
|
||||
// Hook before and after Run initialize and write profiles to disk,
|
||||
// respectively.
|
||||
PersistentPreRunE: func(*cobra.Command, []string) error {
|
||||
return initProfiling()
|
||||
},
|
||||
PersistentPostRunE: func(*cobra.Command, []string) error {
|
||||
return flushProfiling()
|
||||
},
|
||||
}
|
||||
|
||||
flags := cmds.PersistentFlags()
|
||||
flags.SetNormalizeFunc(cliflag.WarnWordSepNormalizeFunc) // Warn for "_" flags
|
||||
|
||||
// Normalize all flags that are coming from other packages or pre-configurations
|
||||
// a.k.a. change all "_" to "-". e.g. glog package
|
||||
flags.SetNormalizeFunc(cliflag.WordSepNormalizeFunc)
|
||||
|
||||
addProfilingFlags(flags)
|
||||
|
||||
iamConfigFlags := genericclioptions.NewConfigFlags(true).WithDeprecatedPasswordFlag().WithDeprecatedSecretFlag()
|
||||
iamConfigFlags.AddFlags(flags)
|
||||
matchVersionIAMConfigFlags := cmdutil.NewMatchVersionFlags(iamConfigFlags)
|
||||
matchVersionIAMConfigFlags.AddFlags(cmds.PersistentFlags())
|
||||
|
||||
_ = viper.BindPFlags(cmds.PersistentFlags())
|
||||
cobra.OnInitialize(func() {
|
||||
genericapiserver.LoadConfig(viper.GetString(genericclioptions.FlagIAMConfig), "iamctl")
|
||||
})
|
||||
cmds.PersistentFlags().AddGoFlagSet(flag.CommandLine)
|
||||
|
||||
f := cmdutil.NewFactory(matchVersionIAMConfigFlags)
|
||||
|
||||
// From this point and forward we get warnings on flags that contain "_" separators
|
||||
cmds.SetGlobalNormalizationFunc(cliflag.WarnWordSepNormalizeFunc)
|
||||
|
||||
ioStreams := genericclioptions.IOStreams{In: in, Out: out, ErrOut: err}
|
||||
|
||||
groups := templates.CommandGroups{
|
||||
{
|
||||
Message: "Basic Commands:",
|
||||
Commands: []*cobra.Command{
|
||||
info.NewCmdInfo(f, ioStreams),
|
||||
color.NewCmdColor(f, ioStreams),
|
||||
new.NewCmdNew(f, ioStreams),
|
||||
jwt.NewCmdJWT(f, ioStreams),
|
||||
},
|
||||
},
|
||||
{
|
||||
Message: "Identity and Access Management Commands:",
|
||||
Commands: []*cobra.Command{
|
||||
user.NewCmdUser(f, ioStreams),
|
||||
secret.NewCmdSecret(f, ioStreams),
|
||||
policy.NewCmdPolicy(f, ioStreams),
|
||||
},
|
||||
},
|
||||
{
|
||||
Message: "Troubleshooting and Debugging Commands:",
|
||||
Commands: []*cobra.Command{
|
||||
validate.NewCmdValidate(f, ioStreams),
|
||||
},
|
||||
},
|
||||
{
|
||||
Message: "Settings Commands:",
|
||||
Commands: []*cobra.Command{
|
||||
set.NewCmdSet(f, ioStreams),
|
||||
completion.NewCmdCompletion(ioStreams.Out, ""),
|
||||
},
|
||||
},
|
||||
}
|
||||
groups.Add(cmds)
|
||||
|
||||
filters := []string{"options"}
|
||||
templates.ActsAsRootCommand(cmds, filters, groups...)
|
||||
|
||||
cmds.AddCommand(version.NewCmdVersion(f, ioStreams))
|
||||
cmds.AddCommand(options.NewCmdOptions(ioStreams.Out))
|
||||
|
||||
return cmds
|
||||
}
|
||||
|
||||
func runHelp(cmd *cobra.Command, args []string) {
|
||||
_ = cmd.Help()
|
||||
}
|
@ -1,352 +0,0 @@
|
||||
// Copyright © 2023 OpenIM. All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// Package color print colors supported by the current terminal.
|
||||
package color
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/olekukonko/tablewriter"
|
||||
"github.com/openim-sigs/component-base/util/stringutil"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
cmdutil "github.com/openimsdk/open-im-server/tools/imctl/internal/imctl/cmd/util"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/pkg/cli/genericclioptions"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/pkg/util/templates"
|
||||
)
|
||||
|
||||
// ColorOptions is an options struct to support color subcommands.
|
||||
type ColorOptions struct {
|
||||
Type []string
|
||||
Example bool
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
|
||||
var (
|
||||
colorLong = templates.LongDesc(`Print the colors supported by the current terminal.
|
||||
|
||||
Color lets you use colorized outputs in terms of ANSI Escape Codes in Go (Golang).
|
||||
It has support for Windows too! The API can be used in several ways, pick one that suits you.
|
||||
|
||||
Find more information at:
|
||||
https://github.com/fatih/color`)
|
||||
|
||||
colorExample = templates.Examples(`
|
||||
# Print supported foreground and background colors
|
||||
imctl color
|
||||
|
||||
# Print supported colors by type
|
||||
imctl color -t fg-hi
|
||||
|
||||
# Print all supported colors
|
||||
imctl color -t all`)
|
||||
|
||||
availableTypes = []string{"fg", "fg-hi", "bg", "bg-hi", "base", "all"}
|
||||
|
||||
colorCodeExample = templates.Examples(`
|
||||
### 1. Standard colors
|
||||
|
||||
// Print with default helper functions
|
||||
color.Cyan("Prints text in cyan.")
|
||||
|
||||
// A newline will be appended automatically
|
||||
color.Blue("Prints %s in blue.", "text")
|
||||
|
||||
// These are using the default foreground colors
|
||||
color.Red("We have red")
|
||||
color.Magenta("And many others ..")
|
||||
|
||||
### 2. Mix and reuse colors
|
||||
|
||||
// Create a new color object
|
||||
c := color.New(color.FgCyan).Add(color.Underline)
|
||||
c.Println("Prints cyan text with an underline.")
|
||||
|
||||
// Or just add them to New()
|
||||
d := color.New(color.FgCyan, color.Bold)
|
||||
d.Printf("This prints bold cyan %s\n", "too!.")
|
||||
|
||||
// Mix up foreground and background colors, create new mixes!
|
||||
red := color.New(color.FgRed)
|
||||
|
||||
boldRed := red.Add(color.Bold)
|
||||
boldRed.Println("This will print text in bold red.")
|
||||
|
||||
whiteBackground := red.Add(color.BgWhite)
|
||||
whiteBackground.Println("Red text with white background.")
|
||||
|
||||
### 3. Use your own output (io.Writer)
|
||||
|
||||
// Use your own io.Writer output
|
||||
color.New(color.FgBlue).Fprintln(myWriter, "blue color!")
|
||||
|
||||
blue := color.New(color.FgBlue)
|
||||
blue.Fprint(writer, "This will print text in blue.")
|
||||
|
||||
### 4. Custom print functions (PrintFunc)
|
||||
|
||||
// Create a custom print function for convenience
|
||||
red := color.New(color.FgRed).PrintfFunc()
|
||||
red("Warning")
|
||||
red("Error: %s", err)
|
||||
|
||||
// Mix up multiple attributes
|
||||
notice := color.New(color.Bold, color.FgGreen).PrintlnFunc()
|
||||
notice("Don't forget this...")
|
||||
|
||||
### 5. Custom fprint functions (FprintFunc)
|
||||
|
||||
blue := color.New(FgBlue).FprintfFunc()
|
||||
blue(myWriter, "important notice: %s", stars)
|
||||
|
||||
// Mix up with multiple attributes
|
||||
success := color.New(color.Bold, color.FgGreen).FprintlnFunc()
|
||||
success(myWriter, "Don't forget this...")
|
||||
|
||||
### 6. Insert into noncolor strings (SprintFunc)
|
||||
|
||||
// Create SprintXxx functions to mix strings with other non-colorized strings:
|
||||
yellow := color.New(color.FgYellow).SprintFunc()
|
||||
red := color.New(color.FgRed).SprintFunc()
|
||||
fmt.Printf("This is a %s and this is %s.\n", yellow("warning"), red("error"))
|
||||
|
||||
info := color.New(color.FgWhite, color.BgGreen).SprintFunc()
|
||||
fmt.Printf("This %s rocks!\n", info("package"))
|
||||
|
||||
// Use helper functions
|
||||
fmt.Println("This", color.RedString("warning"), "should be not neglected.")
|
||||
fmt.Printf("%v %v\n", color.GreenString("Info:"), "an important message.")
|
||||
|
||||
// Windows supported too! Just don't forget to change the output to color.Output
|
||||
fmt.Fprintf(color.Output, "Windows support: %s", color.GreenString("PASS"))
|
||||
|
||||
### 7. Plug into existing code
|
||||
|
||||
// Use handy standard colors
|
||||
color.Set(color.FgYellow)
|
||||
|
||||
fmt.Println("Existing text will now be in yellow")
|
||||
fmt.Printf("This one %s\n", "too")
|
||||
|
||||
color.Unset() // Don't forget to unset
|
||||
|
||||
// You can mix up parameters
|
||||
color.Set(color.FgMagenta, color.Bold)
|
||||
defer color.Unset() // Use it in your function
|
||||
|
||||
fmt.Println("All text will now be bold magenta.")
|
||||
|
||||
### 8. Disable/Enable color
|
||||
|
||||
There might be a case where you want to explicitly disable/enable color output. the
|
||||
go-isatty package will automatically disable color output for non-tty output streams
|
||||
(for example if the output were piped directly to less)
|
||||
|
||||
Color has support to disable/enable colors both globally and for single color
|
||||
definitions. For example suppose you have a CLI app and a --no-color bool flag. You
|
||||
can easily disable the color output with:
|
||||
|
||||
|
||||
var flagNoColor = flag.Bool("no-color", false, "Disable color output")
|
||||
|
||||
if *flagNoColor {
|
||||
color.NoColor = true // disables colorized output
|
||||
}
|
||||
|
||||
It also has support for single color definitions (local). You can
|
||||
disable/enable color output on the fly:
|
||||
|
||||
c := color.New(color.FgCyan)
|
||||
c.Println("Prints cyan text")
|
||||
|
||||
c.DisableColor()
|
||||
c.Println("This is printed without any color")
|
||||
|
||||
c.EnableColor()
|
||||
c.Println("This prints again cyan...")`)
|
||||
)
|
||||
|
||||
// NewColorOptions returns an initialized ColorOptions instance.
|
||||
func NewColorOptions(ioStreams genericclioptions.IOStreams) *ColorOptions {
|
||||
return &ColorOptions{
|
||||
Type: []string{},
|
||||
Example: false,
|
||||
IOStreams: ioStreams,
|
||||
}
|
||||
}
|
||||
|
||||
// NewCmdColor returns new initialized instance of color sub command.
|
||||
func NewCmdColor(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
|
||||
o := NewColorOptions(ioStreams)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "color",
|
||||
DisableFlagsInUseLine: true,
|
||||
Aliases: []string{},
|
||||
Short: "Print colors supported by the current terminal",
|
||||
TraverseChildren: true,
|
||||
Long: colorLong,
|
||||
Example: colorExample,
|
||||
// NoArgs, ArbitraryArgs, OnlyValidArgs, MinimumArgs, MaximumArgs, ExactArgs, ExactArgs
|
||||
ValidArgs: []string{},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cmdutil.CheckErr(o.Complete(f, cmd, args))
|
||||
cmdutil.CheckErr(o.Validate(cmd, args))
|
||||
cmdutil.CheckErr(o.Run(args))
|
||||
},
|
||||
SuggestFor: []string{},
|
||||
}
|
||||
|
||||
cmd.Flags().StringSliceVarP(&o.Type, "type", "t", o.Type,
|
||||
fmt.Sprintf("Specify the color type, available types: `%s`.", strings.Join(availableTypes, ",")))
|
||||
cmd.Flags().BoolVar(&o.Example, "example", o.Example, "Print code to show how to use color package.")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Complete completes all the required options.
|
||||
func (o *ColorOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
|
||||
if len(o.Type) == 0 {
|
||||
o.Type = []string{"fg", "bg"}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
if stringutil.StringIn("all", o.Type) {
|
||||
o.Type = []string{"fg", "fg-hi", "bg", "bg-hi", "base"}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate makes sure there is no discrepency in command options.
|
||||
func (o *ColorOptions) Validate(cmd *cobra.Command, args []string) error {
|
||||
for _, t := range o.Type {
|
||||
if !stringutil.StringIn(t, availableTypes) {
|
||||
return cmdutil.UsageErrorf(cmd, "--type must be in: %s", strings.Join(availableTypes, ","))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run executes a color subcommand using the specified options.
|
||||
func (o *ColorOptions) Run(args []string) error {
|
||||
if o.Example {
|
||||
fmt.Fprint(o.Out, colorCodeExample+"\n")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var data [][]string
|
||||
|
||||
// print table to stdout
|
||||
table := tablewriter.NewWriter(o.Out)
|
||||
|
||||
// set table attributes
|
||||
table.SetAutoMergeCells(true)
|
||||
table.SetRowLine(false)
|
||||
table.SetBorder(false)
|
||||
table.SetAutoWrapText(false)
|
||||
table.SetAutoFormatHeaders(true)
|
||||
table.SetHeaderAlignment(tablewriter.ALIGN_CENTER)
|
||||
table.SetAlignment(tablewriter.ALIGN_LEFT)
|
||||
table.SetHeader([]string{"Category", "Color Name", "Effect"})
|
||||
table.SetHeaderColor(tablewriter.Colors{tablewriter.FgGreenColor},
|
||||
tablewriter.Colors{tablewriter.FgRedColor},
|
||||
tablewriter.Colors{tablewriter.FgCyanColor})
|
||||
|
||||
for _, t := range o.Type {
|
||||
switch t {
|
||||
// Foreground text colors
|
||||
case "fg":
|
||||
fg := [][]string{
|
||||
{"fg", "black", color.BlackString("color.BlackString")},
|
||||
{"fg", "red", color.RedString("color.RedString")},
|
||||
{"fg", "green", color.GreenString("color.GreenString")},
|
||||
{"fg", "yellow", color.YellowString("color.YellowString")},
|
||||
{"fg", "blue", color.BlueString("color.BlueString")},
|
||||
{"fg", "magenta", color.MagentaString("color.MagentaString")},
|
||||
{"fg", "Cyan", color.CyanString("color.CyanString")},
|
||||
{"fg", "white", color.WhiteString("color.WhiteString")},
|
||||
}
|
||||
data = append(data, fg...)
|
||||
// Foreground Hi-Intensity text colors
|
||||
case "fg-hi":
|
||||
fg := [][]string{
|
||||
{"fg-hi", "black", color.HiBlackString("color.HiBlackString")},
|
||||
{"fg-hi", "red", color.HiRedString("color.HiRedString")},
|
||||
{"fg-hi", "green", color.HiGreenString("color.HiGreenString")},
|
||||
{"fg-hi", "yellow", color.HiYellowString("color.HiYellowString")},
|
||||
{"fg-hi", "blue", color.HiBlueString("color.HiBlueString")},
|
||||
{"fg-hi", "magenta", color.HiMagentaString("color.HiMagentaString")},
|
||||
{"fg-hi", "Cyan", color.HiCyanString("color.HiCyanString")},
|
||||
{"fg-hi", "white", color.HiWhiteString("color.HiWhiteString")},
|
||||
}
|
||||
data = append(data, fg...)
|
||||
|
||||
// Background text colors
|
||||
case "bg":
|
||||
bg := [][]string{
|
||||
{"bg", "black", color.New(color.FgWhite, color.BgBlack).SprintFunc()("color.BgBlack")},
|
||||
{"bg", "red", color.New(color.FgBlack, color.BgRed).SprintFunc()("color.BgRed")},
|
||||
{"bg", "greep", color.New(color.FgBlack, color.BgGreen).SprintFunc()("color.BgGreen")},
|
||||
{"bg", "yellow", color.New(color.FgWhite, color.BgYellow).SprintFunc()("color.BgYellow")},
|
||||
{"bg", "blue", color.New(color.FgWhite, color.BgBlue).SprintFunc()("color.BgBlue")},
|
||||
{"bg", "magenta", color.New(color.FgWhite, color.BgMagenta).SprintFunc()("color.BgMagenta")},
|
||||
{"bg", "cyan", color.New(color.FgWhite, color.BgCyan).SprintFunc()("color.BgCyan")},
|
||||
{"bg", "white", color.New(color.FgBlack, color.BgWhite).SprintFunc()("color.BgWhite")},
|
||||
}
|
||||
data = append(data, bg...)
|
||||
// Background Hi-Intensity text colors
|
||||
case "bg-hi":
|
||||
bghi := [][]string{
|
||||
{"bg-hi", "black", color.New(color.FgWhite, color.BgHiBlack).SprintFunc()("color.BgHiBlack")},
|
||||
{"bg-hi", "red", color.New(color.FgBlack, color.BgHiRed).SprintFunc()("color.BgHiRed")},
|
||||
{"bg-hi", "greep", color.New(color.FgBlack, color.BgHiGreen).SprintFunc()("color.BgHiGreen")},
|
||||
{"bg-hi", "yellow", color.New(color.FgWhite, color.BgHiYellow).SprintFunc()("color.BgHiYellow")},
|
||||
{"bg-hi", "blue", color.New(color.FgWhite, color.BgHiBlue).SprintFunc()("color.BgHiBlue")},
|
||||
{"bg-hi", "magenta", color.New(color.FgWhite, color.BgHiMagenta).SprintFunc()("color.BgHiMagenta")},
|
||||
{"bg-hi", "cyan", color.New(color.FgWhite, color.BgHiCyan).SprintFunc()("color.BgHiCyan")},
|
||||
{"bg-hi", "white", color.New(color.FgBlack, color.BgHiWhite).SprintFunc()("color.BgHiWhite")},
|
||||
}
|
||||
data = append(data, bghi...)
|
||||
// Base attributes
|
||||
case "base":
|
||||
base := [][]string{
|
||||
{"base", "black", color.New(color.FgGreen, color.Reset).SprintFunc()("color.Reset")},
|
||||
{"base", "red", color.New(color.FgGreen, color.Bold).SprintFunc()("color.Bold")},
|
||||
{"base", "greep", color.New(color.FgGreen, color.Faint).SprintFunc()("color.Faint")},
|
||||
{"base", "yellow", color.New(color.FgGreen, color.Italic).SprintFunc()("color.Italic")},
|
||||
{"base", "blue", color.New(color.FgGreen, color.Underline).SprintFunc()("color.Underline")},
|
||||
{"base", "magenta", color.New(color.FgGreen, color.BlinkSlow).SprintFunc()("color.BlinkSlow")},
|
||||
{"base", "cyan", color.New(color.FgGreen, color.BlinkRapid).SprintFunc()("color.BlinkRapid")},
|
||||
{"base", "white", color.New(color.FgGreen, color.ReverseVideo).SprintFunc()("color.ReverseVideo")},
|
||||
{"base", "white", color.New(color.FgGreen, color.Concealed).SprintFunc()("color.Concealed")},
|
||||
{"base", "white", color.New(color.FgGreen, color.CrossedOut).SprintFunc()("color.CrossedOut")},
|
||||
}
|
||||
data = append(data, base...)
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
table.AppendBulk(data)
|
||||
table.Render()
|
||||
|
||||
return nil
|
||||
}
|
@ -1,283 +0,0 @@
|
||||
// Copyright © 2023 OpenIM. All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// Package completion output shell completion code for the specified shell (bash or zsh).
|
||||
package completion
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
cmdutil "github.com/openimsdk/open-im-server/tools/imctl/internal/imctl/cmd/util"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/pkg/util/templates"
|
||||
)
|
||||
|
||||
const defaultBoilerPlate = `
|
||||
# Copyright © 2023 OpenIM. All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
`
|
||||
|
||||
var (
|
||||
completionLong = templates.LongDesc(`
|
||||
Output shell completion code for the specified shell (bash or zsh).
|
||||
The shell code must be evaluated to provide interactive
|
||||
completion of imctl commands. This can be done by sourcing it from
|
||||
the .bash_profile.
|
||||
|
||||
Detailed instructions on how to do this are available here:
|
||||
http://github.com/marmotedu/iam/docs/installation/imctl.md#enabling-shell-autocompletion
|
||||
|
||||
Note for zsh users: [1] zsh completions are only supported in versions of zsh >= 5.2`)
|
||||
|
||||
completionExample = templates.Examples(`
|
||||
# Installing bash completion on macOS using homebrew
|
||||
## If running Bash 3.2 included with macOS
|
||||
brew install bash-completion
|
||||
## or, if running Bash 4.1+
|
||||
brew install bash-completion@2
|
||||
## If imctl is installed via homebrew, this should start working immediately.
|
||||
## If you've installed via other means, you may need add the completion to your completion directory
|
||||
imctl completion bash > $(brew --prefix)/etc/bash_completion.d/imctl
|
||||
|
||||
|
||||
# Installing bash completion on Linux
|
||||
## If bash-completion is not installed on Linux, please install the 'bash-completion' package
|
||||
## via your distribution's package manager.
|
||||
## Load the imctl completion code for bash into the current shell
|
||||
source <(imctl completion bash)
|
||||
## Write bash completion code to a file and source if from .bash_profile
|
||||
imctl completion bash > ~/.iam/completion.bash.inc
|
||||
printf "
|
||||
# IAM shell completion
|
||||
source '$HOME/.iam/completion.bash.inc'
|
||||
" >> $HOME/.bash_profile
|
||||
source $HOME/.bash_profile
|
||||
|
||||
# Load the imctl completion code for zsh[1] into the current shell
|
||||
source <(imctl completion zsh)
|
||||
# Set the imctl completion code for zsh[1] to autoload on startup
|
||||
imctl completion zsh > "${fpath[1]}/_imctl"`)
|
||||
)
|
||||
|
||||
var completionShells = map[string]func(out io.Writer, boilerPlate string, cmd *cobra.Command) error{
|
||||
"bash": runCompletionBash,
|
||||
"zsh": runCompletionZsh,
|
||||
}
|
||||
|
||||
// NewCmdCompletion creates the `completion` command.
|
||||
func NewCmdCompletion(out io.Writer, boilerPlate string) *cobra.Command {
|
||||
shells := []string{}
|
||||
for s := range completionShells {
|
||||
shells = append(shells, s)
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "completion SHELL",
|
||||
DisableFlagsInUseLine: true,
|
||||
Short: "Output shell completion code for the specified shell (bash or zsh)",
|
||||
Long: completionLong,
|
||||
Example: completionExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := RunCompletion(out, boilerPlate, cmd, args)
|
||||
cmdutil.CheckErr(err)
|
||||
},
|
||||
ValidArgs: shells,
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// RunCompletion checks given arguments and executes command.
|
||||
func RunCompletion(out io.Writer, boilerPlate string, cmd *cobra.Command, args []string) error {
|
||||
if len(args) == 0 {
|
||||
return cmdutil.UsageErrorf(cmd, "Shell not specified.")
|
||||
}
|
||||
|
||||
if len(args) > 1 {
|
||||
return cmdutil.UsageErrorf(cmd, "Too many arguments. Expected only the shell type.")
|
||||
}
|
||||
|
||||
run, found := completionShells[args[0]]
|
||||
if !found {
|
||||
return cmdutil.UsageErrorf(cmd, "Unsupported shell type %q.", args[0])
|
||||
}
|
||||
|
||||
return run(out, boilerPlate, cmd.Parent())
|
||||
}
|
||||
|
||||
func runCompletionBash(out io.Writer, boilerPlate string, imctl *cobra.Command) error {
|
||||
if len(boilerPlate) == 0 {
|
||||
boilerPlate = defaultBoilerPlate
|
||||
}
|
||||
|
||||
if _, err := out.Write([]byte(boilerPlate)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return imctl.GenBashCompletion(out)
|
||||
}
|
||||
|
||||
func runCompletionZsh(out io.Writer, boilerPlate string, imctl *cobra.Command) error {
|
||||
zshHead := "#compdef imctl\n"
|
||||
|
||||
if _, err := out.Write([]byte(zshHead)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(boilerPlate) == 0 {
|
||||
boilerPlate = defaultBoilerPlate
|
||||
}
|
||||
|
||||
if _, err := out.Write([]byte(boilerPlate)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
zshInitialization := `
|
||||
__imctl_bash_source() {
|
||||
alias shopt=':'
|
||||
emulate -L sh
|
||||
setopt kshglob noshglob braceexpand
|
||||
|
||||
source "$@"
|
||||
}
|
||||
|
||||
__imctl_type() {
|
||||
# -t is not supported by zsh
|
||||
if [ "$1" == "-t" ]; then
|
||||
shift
|
||||
|
||||
# fake Bash 4 to disable "complete -o nospace". Instead
|
||||
# "compopt +-o nospace" is used in the code to toggle trailing
|
||||
# spaces. We don't support that, but leave trailing spaces on
|
||||
# all the time
|
||||
if [ "$1" = "__imctl_compopt" ]; then
|
||||
echo builtin
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
type "$@"
|
||||
}
|
||||
|
||||
__imctl_compgen() {
|
||||
local completions w
|
||||
completions=( $(compgen "$@") ) || return $?
|
||||
|
||||
# filter by given word as prefix
|
||||
while [[ "$1" = -* && "$1" != -- ]]; do
|
||||
shift
|
||||
shift
|
||||
done
|
||||
if [[ "$1" == -- ]]; then
|
||||
shift
|
||||
fi
|
||||
for w in "${completions[@]}"; do
|
||||
if [[ "${w}" = "$1"* ]]; then
|
||||
echo "${w}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
__imctl_compopt() {
|
||||
true # don't do anything. Not supported by bashcompinit in zsh
|
||||
}
|
||||
|
||||
__imctl_ltrim_colon_completions()
|
||||
{
|
||||
if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
|
||||
# Remove colon-word prefix from COMPREPLY items
|
||||
local colon_word=${1%${1##*:}}
|
||||
local i=${#COMPREPLY[*]}
|
||||
while [[ $((--i)) -ge 0 ]]; do
|
||||
COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
__imctl_get_comp_words_by_ref() {
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
prev="${COMP_WORDS[${COMP_CWORD}-1]}"
|
||||
words=("${COMP_WORDS[@]}")
|
||||
cword=("${COMP_CWORD[@]}")
|
||||
}
|
||||
|
||||
__imctl_filedir() {
|
||||
# Don't need to do anything here.
|
||||
# Otherwise we will get trailing space without "compopt -o nospace"
|
||||
true
|
||||
}
|
||||
|
||||
autoload -U +X bashcompinit && bashcompinit
|
||||
|
||||
# use word boundary patterns for BSD or GNU sed
|
||||
LWORD='[[:<:]]'
|
||||
RWORD='[[:>:]]'
|
||||
if sed --help 2>&1 | grep -q 'GNU\|BusyBox'; then
|
||||
LWORD='\<'
|
||||
RWORD='\>'
|
||||
fi
|
||||
|
||||
__imctl_convert_bash_to_zsh() {
|
||||
sed \
|
||||
-e 's/declare -F/whence -w/' \
|
||||
-e 's/_get_comp_words_by_ref "\$@"/_get_comp_words_by_ref "\$*"/' \
|
||||
-e 's/local \([a-zA-Z0-9_]*\)=/local \1; \1=/' \
|
||||
-e 's/flags+=("\(--.*\)=")/flags+=("\1"); two_word_flags+=("\1")/' \
|
||||
-e 's/must_have_one_flag+=("\(--.*\)=")/must_have_one_flag+=("\1")/' \
|
||||
-e "s/${LWORD}_filedir${RWORD}/__imctl_filedir/g" \
|
||||
-e "s/${LWORD}_get_comp_words_by_ref${RWORD}/__imctl_get_comp_words_by_ref/g" \
|
||||
-e "s/${LWORD}__ltrim_colon_completions${RWORD}/__imctl_ltrim_colon_completions/g" \
|
||||
-e "s/${LWORD}compgen${RWORD}/__imctl_compgen/g" \
|
||||
-e "s/${LWORD}compopt${RWORD}/__imctl_compopt/g" \
|
||||
-e "s/${LWORD}declare${RWORD}/builtin declare/g" \
|
||||
-e "s/\\\$(type${RWORD}/\$(__imctl_type/g" \
|
||||
<<'BASH_COMPLETION_EOF'
|
||||
`
|
||||
if _, err := out.Write([]byte(zshInitialization)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
if err := imctl.GenBashCompletion(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := out.Write(buf.Bytes()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
zshTail := `
|
||||
BASH_COMPLETION_EOF
|
||||
}
|
||||
|
||||
__imctl_bash_source <(__imctl_convert_bash_to_zsh)
|
||||
`
|
||||
if _, err := out.Write([]byte(zshTail)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
// Copyright © 2023 OpenIM. All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// Package info print the host information.
|
||||
package info
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
hoststat "github.com/likexian/host-stat-go"
|
||||
"github.com/openim-sigs/component-base/util/iputil"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
cmdutil "github.com/openimsdk/open-im-server/tools/imctl/internal/imctl/cmd/util"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/pkg/cli/genericclioptions"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/pkg/util/templates"
|
||||
)
|
||||
|
||||
// Info defines the host information struct.
|
||||
type Info struct {
|
||||
HostName string
|
||||
IPAddress string
|
||||
OSRelease string
|
||||
CPUCore uint64
|
||||
MemTotal string
|
||||
MemFree string
|
||||
}
|
||||
|
||||
// InfoOptions is an options struct to support 'info' sub command.
|
||||
type InfoOptions struct {
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
|
||||
var infoExample = templates.Examples(`
|
||||
# Print the host information
|
||||
imctl info`)
|
||||
|
||||
// NewInfoOptions returns an initialized InfoOptions instance.
|
||||
func NewInfoOptions(ioStreams genericclioptions.IOStreams) *InfoOptions {
|
||||
return &InfoOptions{
|
||||
IOStreams: ioStreams,
|
||||
}
|
||||
}
|
||||
|
||||
// NewCmdInfo returns new initialized instance of 'info' sub command.
|
||||
func NewCmdInfo(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
|
||||
o := NewInfoOptions(ioStreams)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "info",
|
||||
DisableFlagsInUseLine: true,
|
||||
Aliases: []string{},
|
||||
Short: "Print the host information",
|
||||
Long: "Print the host information.",
|
||||
Example: infoExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cmdutil.CheckErr(o.Run(args))
|
||||
},
|
||||
SuggestFor: []string{},
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Run executes an info sub command using the specified options.
|
||||
func (o *InfoOptions) Run(args []string) error {
|
||||
var info Info
|
||||
|
||||
hostInfo, err := hoststat.GetHostInfo()
|
||||
if err != nil {
|
||||
return fmt.Errorf("get host info failed!error:%w", err)
|
||||
}
|
||||
|
||||
info.HostName = hostInfo.HostName
|
||||
info.OSRelease = hostInfo.Release + " " + hostInfo.OSBit
|
||||
|
||||
memStat, err := hoststat.GetMemStat()
|
||||
if err != nil {
|
||||
return fmt.Errorf("get mem stat failed!error:%w", err)
|
||||
}
|
||||
|
||||
info.MemTotal = strconv.FormatUint(memStat.MemTotal, 10) + "M"
|
||||
info.MemFree = strconv.FormatUint(memStat.MemFree, 10) + "M"
|
||||
info.IPAddress = iputil.GetLocalIP()
|
||||
|
||||
cpuStat, err := hoststat.GetCPUInfo()
|
||||
if err != nil {
|
||||
return fmt.Errorf("get cpu stat failed!error:%w", err)
|
||||
}
|
||||
|
||||
info.CPUCore = cpuStat.CoreCount
|
||||
|
||||
s := reflect.ValueOf(&info).Elem()
|
||||
typeOfInfo := s.Type()
|
||||
|
||||
for i := 0; i < s.NumField(); i++ {
|
||||
f := s.Field(i)
|
||||
|
||||
v := fmt.Sprintf("%v", f.Interface())
|
||||
if v != "" {
|
||||
fmt.Fprintf(o.Out, "%12s %v\n", typeOfInfo.Field(i).Name+":", f.Interface())
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,619 +0,0 @@
|
||||
// Copyright © 2023 OpenIM. All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// Package new used to generate demo command code.
|
||||
// nolint: predeclared
|
||||
package new
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/openim-sigs/component-base/pkg/util/fileutil"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/internal/imctl/util/templates"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/pkg/cli/genericclioptions"
|
||||
cmdutil "github.com/openimsdk/open-im-server/tools/imctl/pkg/util"
|
||||
)
|
||||
|
||||
const (
|
||||
newUsageStr = "new CMD_NAME | CMD_NAME CMD_DESCRIPTION"
|
||||
)
|
||||
|
||||
var (
|
||||
newLong = templates.LongDesc(`Used to generate demo command source code file.
|
||||
|
||||
Can use this command generate a command template file, and do some modify based on your needs.
|
||||
This can improve your R&D efficiency.`)
|
||||
|
||||
newExample = templates.Examples(`
|
||||
# Create a default 'test' command file without a description
|
||||
imctl new test
|
||||
|
||||
# Create a default 'test' command file in /tmp/
|
||||
imctl new test -d /tmp/
|
||||
|
||||
# Create a default 'test' command file with a description
|
||||
imctl new test "This is a test command"
|
||||
|
||||
# Create command 'test' with two subcommands
|
||||
imctl new -g test "This is a test command with two subcommands"`)
|
||||
|
||||
newUsageErrStr = fmt.Sprintf(
|
||||
"expected '%s'.\nat least CMD_NAME is a required argument for the new command",
|
||||
newUsageStr,
|
||||
)
|
||||
|
||||
cmdTemplate = `package {{.CommandName}}
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
cmdutil "github.com/openimsdk/open-im-server/tools/imctl/pkg/util"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/internal/imctl/util/templates"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/pkg/cli/genericclioptions"
|
||||
)
|
||||
|
||||
const (
|
||||
{{.CommandName}}UsageStr = "{{.CommandName}} USERNAME PASSWORD"
|
||||
maxStringLength = 17
|
||||
)
|
||||
|
||||
// {{.CommandFunctionName}}Options is an options struct to support '{{.CommandName}}' sub command.
|
||||
type {{.CommandFunctionName}}Options struct {
|
||||
// options
|
||||
StringOption string
|
||||
StringSliceOption []string
|
||||
IntOption int
|
||||
BoolOption bool
|
||||
|
||||
// args
|
||||
Username string
|
||||
Password string
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
|
||||
var (
|
||||
{{.CommandName}}Long = templates.LongDesc({{.Dot}}A longer description that spans multiple lines and likely contains examples
|
||||
and usage of using your command. For example:
|
||||
|
||||
Cobra is a CLI library for Go that empowers applications.
|
||||
This application is a tool to generate the needed files
|
||||
to quickly create a Cobra application.{{.Dot}})
|
||||
|
||||
{{.CommandName}}Example = templates.Examples({{.Dot}}
|
||||
# Print all option values for {{.CommandName}}
|
||||
imctl {{.CommandName}} marmotedu marmotedupass{{.Dot}})
|
||||
|
||||
{{.CommandName}}UsageErrStr = fmt.Sprintf("expected '%s'.\nUSERNAME and PASSWORD are required arguments for the {{.CommandName}} command", {{.CommandName}}UsageStr)
|
||||
)
|
||||
|
||||
// New{{.CommandFunctionName}}Options returns an initialized {{.CommandFunctionName}}Options instance.
|
||||
func New{{.CommandFunctionName}}Options(ioStreams genericclioptions.IOStreams) *{{.CommandFunctionName}}Options {
|
||||
return &{{.CommandFunctionName}}Options{
|
||||
StringOption: "default",
|
||||
IOStreams: ioStreams,
|
||||
}
|
||||
}
|
||||
|
||||
// NewCmd{{.CommandFunctionName}} returns new initialized instance of '{{.CommandName}}' sub command.
|
||||
func NewCmd{{.CommandFunctionName}}(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
|
||||
o := New{{.CommandFunctionName}}Options(ioStreams)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: {{.CommandName}}UsageStr,
|
||||
DisableFlagsInUseLine: true,
|
||||
Aliases: []string{},
|
||||
Short: "{{.CommandDescription}}",
|
||||
TraverseChildren: true,
|
||||
Long: {{.CommandName}}Long,
|
||||
Example: {{.CommandName}}Example,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cmdutil.CheckErr(o.Complete(f, cmd, args))
|
||||
cmdutil.CheckErr(o.Validate(cmd, args))
|
||||
cmdutil.CheckErr(o.Run(args))
|
||||
},
|
||||
SuggestFor: []string{},
|
||||
Args: func(cmd *cobra.Command, args []string) error {
|
||||
// nolint: gomnd // no need
|
||||
if len(args) < 2 {
|
||||
return cmdutil.UsageErrorf(cmd, {{.CommandName}}UsageErrStr)
|
||||
}
|
||||
|
||||
// if need args equal to zero, uncomment the following code
|
||||
/*
|
||||
if len(args) != 0 {
|
||||
return cmdutil.UsageErrorf(cmd, "Unexpected args: %v", args)
|
||||
}
|
||||
*/
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// mark flag as deprecated
|
||||
_ = cmd.Flags().MarkDeprecated("deprecated-opt", "This flag is deprecated and will be removed in future.")
|
||||
cmd.Flags().StringVarP(&o.StringOption, "string", "", o.StringOption, "String option.")
|
||||
cmd.Flags().StringSliceVar(&o.StringSliceOption, "slice", o.StringSliceOption, "String slice option.")
|
||||
cmd.Flags().IntVarP(&o.IntOption, "int", "i", o.IntOption, "Int option.")
|
||||
cmd.Flags().BoolVarP(&o.BoolOption, "bool", "b", o.BoolOption, "Bool option.")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Complete completes all the required options.
|
||||
func (o *{{.CommandFunctionName}}Options) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
|
||||
if o.StringOption != "" {
|
||||
o.StringOption += "(complete)"
|
||||
}
|
||||
|
||||
o.Username = args[0]
|
||||
o.Password = args[1]
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate makes sure there is no discrepency in command options.
|
||||
func (o *{{.CommandFunctionName}}Options) Validate(cmd *cobra.Command, args []string) error {
|
||||
if len(o.StringOption) > maxStringLength {
|
||||
return cmdutil.UsageErrorf(cmd, "--string length must less than 18")
|
||||
}
|
||||
|
||||
if o.IntOption < 0 {
|
||||
return cmdutil.UsageErrorf(cmd, "--int must be a positive integer: %v", o.IntOption)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run executes a {{.CommandName}} sub command using the specified options.
|
||||
func (o *{{.CommandFunctionName}}Options) Run(args []string) error {
|
||||
fmt.Fprintf(o.Out, "The following is option values:\n")
|
||||
fmt.Fprintf(o.Out, "==> --string: %v\n==> --slice: %v\n==> --int: %v\n==> --bool: %v\n",
|
||||
o.StringOption, o.StringSliceOption, o.IntOption, o.BoolOption)
|
||||
|
||||
fmt.Fprintf(o.Out, "\nThe following is args values:\n")
|
||||
fmt.Fprintf(o.Out, "==> username: %v\n==> password: %v\n", o.Username, o.Password)
|
||||
|
||||
return nil
|
||||
}
|
||||
`
|
||||
|
||||
maincmdTemplate = `package {{.CommandName}}
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
cmdutil "github.com/openimsdk/open-im-server/tools/imctl/pkg/util"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/internal/imctl/util/templates"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/pkg/cli/genericclioptions"
|
||||
)
|
||||
|
||||
const maxStringLength = 17
|
||||
|
||||
var (
|
||||
{{.CommandName}}Long = templates.LongDesc({{.Dot}}
|
||||
Demo command.
|
||||
|
||||
This commands show you how to implement a command with two sub commands.{{.Dot}})
|
||||
)
|
||||
|
||||
// NewCmd{{.CommandFunctionName}} returns new initialized instance of '{{.CommandName}}' sub command.
|
||||
func NewCmd{{.CommandFunctionName}}(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "{{.CommandName}} SUBCOMMAND",
|
||||
DisableFlagsInUseLine: true,
|
||||
Short: "{{.CommandDescription}}",
|
||||
Long: {{.CommandName}}Long,
|
||||
Run: cmdutil.DefaultSubCommandRun(ioStreams.ErrOut),
|
||||
}
|
||||
|
||||
// add subcommands
|
||||
cmd.AddCommand(NewCmdSubCmd1(f, ioStreams))
|
||||
cmd.AddCommand(NewCmdSubCmd2(f, ioStreams))
|
||||
|
||||
// add persistent flags for '{{.CommandName}}'
|
||||
cmdutil.AddCleanFlags(cmd)
|
||||
|
||||
// persistent flag, we can get the value in subcommand via {{.Dot}}viper.Get{{.Dot}}
|
||||
cmd.PersistentFlags().StringP("persistent", "p", "this is a persistent option", "Cobra persistent option.")
|
||||
|
||||
// bind flags with viper
|
||||
viper.BindPFlag("persistent", cmd.PersistentFlags().Lookup("persistent"))
|
||||
|
||||
return cmd
|
||||
}
|
||||
`
|
||||
subcmd1Template = `package {{.CommandName}}
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
cmdutil "github.com/openimsdk/open-im-server/tools/imctl/pkg/util"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/internal/imctl/util/templates"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/pkg/cli/genericclioptions"
|
||||
)
|
||||
|
||||
const (
|
||||
subcmd1UsageStr = "subcmd1 USERNAME PASSWORD"
|
||||
)
|
||||
|
||||
// SubCmd1Options is an options struct to support subcmd1 subcommands.
|
||||
type SubCmd1Options struct {
|
||||
// options
|
||||
StringOption string
|
||||
StringSliceOption []string
|
||||
IntOption int
|
||||
BoolOption bool
|
||||
PersistentOption string
|
||||
|
||||
// args
|
||||
Username string
|
||||
Password string
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
|
||||
var (
|
||||
subcmd1Long = templates.LongDesc({{.Dot}}A longer description that spans multiple lines and likely contains examples
|
||||
and usage of using your command. For example:
|
||||
|
||||
Cobra is a CLI library for Go that empowers applications.
|
||||
This application is a tool to generate the needed files
|
||||
to quickly create a Cobra application.{{.Dot}})
|
||||
|
||||
subcmd1Example = templates.Examples({{.Dot}}
|
||||
# Print all option values for subcmd1
|
||||
imctl {{.CommandName}} subcmd1 marmotedu marmotedupass
|
||||
|
||||
# Print all option values for subcmd1 with --persistent specified
|
||||
imctl {{.CommandName}} subcmd1 marmotedu marmotedupass --persistent="specified persistent option in command line"{{.Dot}})
|
||||
|
||||
subcmd1UsageErrStr = fmt.Sprintf("expected '%s'.\nUSERNAME and PASSWORD are required arguments for the subcmd1 command", subcmd1UsageStr)
|
||||
)
|
||||
|
||||
// NewSubCmd1Options returns an initialized SubCmd1Options instance.
|
||||
func NewSubCmd1Options(ioStreams genericclioptions.IOStreams) *SubCmd1Options {
|
||||
return &SubCmd1Options{
|
||||
StringOption: "default",
|
||||
IOStreams: ioStreams,
|
||||
}
|
||||
}
|
||||
|
||||
// NewCmdSubCmd1 returns new initialized instance of subcmd1 sub command.
|
||||
func NewCmdSubCmd1(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
|
||||
o := NewSubCmd1Options(ioStreams)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "subcmd1 USERNAME PASSWORD",
|
||||
DisableFlagsInUseLine: true,
|
||||
Aliases: []string{"sub1"},
|
||||
Short: "A brief description of your command",
|
||||
TraverseChildren: true,
|
||||
Long: subcmd1Long,
|
||||
Example: subcmd1Example,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cmdutil.CheckErr(o.Complete(f, cmd, args))
|
||||
cmdutil.CheckErr(o.Validate(cmd, args))
|
||||
cmdutil.CheckErr(o.Run(args))
|
||||
},
|
||||
SuggestFor: []string{},
|
||||
Args: func(cmd *cobra.Command, args []string) error {
|
||||
// nolint: gomnd // no need
|
||||
if len(args) < 2 {
|
||||
return cmdutil.UsageErrorf(cmd, subcmd1UsageErrStr)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// mark flag as deprecated
|
||||
_ = cmd.Flags().MarkDeprecated("deprecated-opt", "This flag is deprecated and will be removed in future.")
|
||||
cmd.Flags().StringVarP(&o.StringOption, "string", "", o.StringOption, "String option.")
|
||||
cmd.Flags().StringSliceVar(&o.StringSliceOption, "slice", o.StringSliceOption, "String slice option.")
|
||||
cmd.Flags().IntVarP(&o.IntOption, "int", "i", o.IntOption, "Int option.")
|
||||
cmd.Flags().BoolVarP(&o.BoolOption, "bool", "b", o.BoolOption, "Bool option.")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Complete completes all the required options.
|
||||
func (o *SubCmd1Options) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
|
||||
if o.StringOption != "" {
|
||||
o.StringOption += "(complete)"
|
||||
}
|
||||
|
||||
o.PersistentOption = viper.GetString("persistent")
|
||||
o.Username = args[0]
|
||||
o.Password = args[1]
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate makes sure there is no discrepency in command options.
|
||||
func (o *SubCmd1Options) Validate(cmd *cobra.Command, args []string) error {
|
||||
if len(o.StringOption) > maxStringLength {
|
||||
return cmdutil.UsageErrorf(cmd, "--string length must less than 18")
|
||||
}
|
||||
|
||||
if o.IntOption < 0 {
|
||||
return cmdutil.UsageErrorf(cmd, "--int must be a positive integer: %v", o.IntOption)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run executes a subcmd1 subcommand using the specified options.
|
||||
func (o *SubCmd1Options) Run(args []string) error {
|
||||
fmt.Fprintf(o.Out, "The following is option values:\n")
|
||||
fmt.Fprintf(o.Out, "==> --string: %v\n==> --slice: %v\n==> --int: %v\n==> --bool: %v\n==> --persistent: %v\n",
|
||||
o.StringOption, o.StringSliceOption, o.IntOption, o.BoolOption, o.PersistentOption)
|
||||
|
||||
fmt.Fprintf(o.Out, "\nThe following is args values:\n")
|
||||
fmt.Fprintf(o.Out, "==> username: %v\n==> password: %v\n", o.Username, o.Password)
|
||||
return nil
|
||||
}
|
||||
`
|
||||
subcmd2Template = `package {{.CommandName}}
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
cmdutil "github.com/openimsdk/open-im-server/tools/imctl/pkg/util"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/internal/imctl/util/templates"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/pkg/cli/genericclioptions"
|
||||
)
|
||||
|
||||
// SubCmd2Options is an options struct to support subcmd2 subcommands.
|
||||
type SubCmd2Options struct {
|
||||
StringOption string
|
||||
StringSliceOption []string
|
||||
IntOption int
|
||||
BoolOption bool
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
|
||||
var (
|
||||
subcmd2Long = templates.LongDesc({{.Dot}}A longer description that spans multiple lines and likely contains examples
|
||||
and usage of using your command. For example:
|
||||
|
||||
Cobra is a CLI library for Go that empowers applications.
|
||||
This application is a tool to generate the needed files
|
||||
to quickly create a Cobra application.{{.Dot}})
|
||||
|
||||
subcmd2Example = templates.Examples({{.Dot}}
|
||||
# Print all option values for subcmd2
|
||||
imctl {{.CommandName}} subcmd2{{.Dot}})
|
||||
)
|
||||
|
||||
// NewSubCmd2Options returns an initialized SubCmd2Options instance.
|
||||
func NewSubCmd2Options(ioStreams genericclioptions.IOStreams) *SubCmd2Options {
|
||||
return &SubCmd2Options{
|
||||
StringOption: "default",
|
||||
IOStreams: ioStreams,
|
||||
}
|
||||
}
|
||||
|
||||
// NewCmdSubCmd2 returns new initialized instance of subcmd2 sub command.
|
||||
func NewCmdSubCmd2(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
|
||||
o := NewSubCmd2Options(ioStreams)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "subcmd2",
|
||||
DisableFlagsInUseLine: true,
|
||||
Aliases: []string{"sub2"},
|
||||
Short: "A brief description of your command",
|
||||
TraverseChildren: true,
|
||||
Long: subcmd2Long,
|
||||
Example: subcmd2Example,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cmdutil.CheckErr(o.Complete(f, cmd, args))
|
||||
cmdutil.CheckErr(o.Validate(cmd, args))
|
||||
cmdutil.CheckErr(o.Run(args))
|
||||
},
|
||||
SuggestFor: []string{},
|
||||
}
|
||||
|
||||
// mark flag as deprecated
|
||||
cmd.Flags().StringVarP(&o.StringOption, "string", "", o.StringOption, "String option.")
|
||||
cmd.Flags().StringSliceVar(&o.StringSliceOption, "slice", o.StringSliceOption, "String slice option.")
|
||||
cmd.Flags().IntVarP(&o.IntOption, "int", "i", o.IntOption, "Int option.")
|
||||
cmd.Flags().BoolVarP(&o.BoolOption, "bool", "b", o.BoolOption, "Bool option.")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Complete completes all the required options.
|
||||
func (o *SubCmd2Options) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
|
||||
if len(args) != 0 {
|
||||
return cmdutil.UsageErrorf(cmd, "Unexpected args: %v", args)
|
||||
}
|
||||
|
||||
if o.StringOption != "" {
|
||||
o.StringOption += "(complete)"
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate makes sure there is no discrepency in command options.
|
||||
func (o *SubCmd2Options) Validate(cmd *cobra.Command, args []string) error {
|
||||
if len(o.StringOption) > maxStringLength {
|
||||
return cmdutil.UsageErrorf(cmd, "--string length must less than 18")
|
||||
}
|
||||
|
||||
if o.IntOption < 0 {
|
||||
return cmdutil.UsageErrorf(cmd, "--int must be a positive integer: %v", o.IntOption)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run executes a subcmd2 subcommand using the specified options.
|
||||
func (o *SubCmd2Options) Run(args []string) error {
|
||||
fmt.Fprintf(o.Out, "The following is option values:\n")
|
||||
fmt.Fprintf(o.Out, "==> --string: %v\n==> --slice: %v\n==> --int: %v\n==> --bool: %v\n",
|
||||
o.StringOption, o.StringSliceOption, o.IntOption, o.BoolOption)
|
||||
return nil
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
// NewOptions is an options struct to support 'new' sub command.
|
||||
type NewOptions struct {
|
||||
Group bool
|
||||
Outdir string
|
||||
|
||||
// command template options, will render to command template
|
||||
CommandName string
|
||||
CommandDescription string
|
||||
CommandFunctionName string
|
||||
Dot string
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
|
||||
// NewNewOptions returns an initialized NewOptions instance.
|
||||
func NewNewOptions(ioStreams genericclioptions.IOStreams) *NewOptions {
|
||||
return &NewOptions{
|
||||
Group: false,
|
||||
Outdir: ".",
|
||||
CommandDescription: "A brief description of your command",
|
||||
Dot: "`",
|
||||
IOStreams: ioStreams,
|
||||
}
|
||||
}
|
||||
|
||||
// NewCmdNew returns new initialized instance of 'new' sub command.
|
||||
func NewCmdNew(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
|
||||
o := NewNewOptions(ioStreams)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: newUsageStr,
|
||||
DisableFlagsInUseLine: true,
|
||||
Short: "Generate demo command code",
|
||||
Long: newLong,
|
||||
Example: newExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cmdutil.CheckErr(o.Complete(cmd, args))
|
||||
cmdutil.CheckErr(o.Validate(cmd))
|
||||
cmdutil.CheckErr(o.Run(args))
|
||||
},
|
||||
Aliases: []string{},
|
||||
SuggestFor: []string{},
|
||||
}
|
||||
|
||||
cmd.Flags().BoolVarP(&o.Group, "group", "g", o.Group, "Generate two subcommands.")
|
||||
cmd.Flags().StringVarP(&o.Outdir, "outdir", "d", o.Outdir, "Where to create demo command files.")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Complete completes all the required options.
|
||||
func (o *NewOptions) Complete(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 1 {
|
||||
return cmdutil.UsageErrorf(cmd, newUsageErrStr)
|
||||
}
|
||||
|
||||
o.CommandName = strings.ToLower(args[0])
|
||||
if len(args) > 1 {
|
||||
o.CommandDescription = args[1]
|
||||
}
|
||||
|
||||
o.CommandFunctionName = cases.Title(language.English).String(o.CommandName)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate makes sure there is no discrepency in command options.
|
||||
func (o *NewOptions) Validate(cmd *cobra.Command) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run executes a new sub command using the specified options.
|
||||
func (o *NewOptions) Run(args []string) error {
|
||||
if o.Group {
|
||||
return o.CreateCommandWithSubCommands()
|
||||
}
|
||||
|
||||
return o.CreateCommand()
|
||||
}
|
||||
|
||||
// CreateCommand create the command with options.
|
||||
func (o *NewOptions) CreateCommand() error {
|
||||
return o.GenerateGoCode(o.CommandName+".go", cmdTemplate)
|
||||
}
|
||||
|
||||
// CreateCommandWithSubCommands create sub commands with options.
|
||||
func (o *NewOptions) CreateCommandWithSubCommands() error {
|
||||
if err := o.GenerateGoCode(o.CommandName+".go", maincmdTemplate); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := o.GenerateGoCode(o.CommandName+"_subcmd1.go", subcmd1Template); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := o.GenerateGoCode(o.CommandName+"_subcmd2.go", subcmd2Template); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GenerateGoCode generate go source file.
|
||||
func (o *NewOptions) GenerateGoCode(name, codeTemplate string) error {
|
||||
tmpl, err := template.New("cmd").Parse(codeTemplate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = fileutil.EnsureDirAll(o.Outdir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
filename := filepath.Join(o.Outdir, name)
|
||||
fd, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer fd.Close()
|
||||
|
||||
err = tmpl.Execute(fd, o)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Command file generated: %s\n", filename)
|
||||
|
||||
return nil
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
// Copyright © 2023 OpenIM. All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// Package options print a list of global command-line options (applies to all commands).
|
||||
package options
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/pkg/util/templates"
|
||||
)
|
||||
|
||||
var optionsExample = templates.Examples(`
|
||||
# Print flags inherited by all commands
|
||||
iamctl options`)
|
||||
|
||||
// NewCmdOptions implements the options command.
|
||||
func NewCmdOptions(out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "options",
|
||||
Short: "Print the list of flags inherited by all commands",
|
||||
Long: "Print the list of flags inherited by all commands",
|
||||
Example: optionsExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
_ = cmd.Usage()
|
||||
},
|
||||
}
|
||||
|
||||
// The `options` command needs write its output to the `out` stream
|
||||
// (typically stdout). Without calling SetOutput here, the Usage()
|
||||
// function call will fall back to stderr.
|
||||
cmd.SetOutput(out)
|
||||
|
||||
templates.UseOptionsTemplates(cmd)
|
||||
|
||||
return cmd
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
// Copyright © 2023 OpenIM. All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"runtime/pprof"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
// profiling configuration variables
|
||||
var (
|
||||
profileName string = "none" // Name of the profile to capture.
|
||||
profileOutput string = "profile.pprof" // File to write the profile data.
|
||||
)
|
||||
|
||||
// addProfilingFlags registers profiling related flags to the given FlagSet.
|
||||
func addProfilingFlags(flags *pflag.FlagSet) {
|
||||
flags.StringVar(
|
||||
&profileName,
|
||||
"profile",
|
||||
"none",
|
||||
"Type of profile to capture. Options: none, cpu, heap, goroutine, threadcreate, block, mutex",
|
||||
)
|
||||
flags.StringVar(&profileOutput, "profile-output", "profile.pprof", "File to write the profile data")
|
||||
}
|
||||
|
||||
// initProfiling sets up profiling based on the user's choice.
|
||||
// If 'cpu' is selected, it starts the CPU profile. For block and mutex profiles,
|
||||
// sampling rates are set up.
|
||||
func initProfiling() error {
|
||||
switch profileName {
|
||||
case "none":
|
||||
return nil
|
||||
case "cpu":
|
||||
f, err := os.Create(profileOutput)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return pprof.StartCPUProfile(f)
|
||||
case "block":
|
||||
runtime.SetBlockProfileRate(1) // Sampling every block event
|
||||
return nil
|
||||
case "mutex":
|
||||
runtime.SetMutexProfileFraction(1) // Sampling every mutex event
|
||||
return nil
|
||||
default:
|
||||
if profile := pprof.Lookup(profileName); profile == nil {
|
||||
return fmt.Errorf("unknown profile type: '%s'", profileName)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// flushProfiling writes the profiling data to the specified file.
|
||||
// For heap profiles, it runs the GC before capturing the data.
|
||||
// It stops the CPU profile if it was started.
|
||||
func flushProfiling() error {
|
||||
switch profileName {
|
||||
case "none":
|
||||
return nil
|
||||
case "cpu":
|
||||
pprof.StopCPUProfile()
|
||||
return nil
|
||||
case "heap":
|
||||
runtime.GC() // Run garbage collection before writing heap profile
|
||||
fallthrough
|
||||
default:
|
||||
profile := pprof.Lookup(profileName)
|
||||
if profile == nil {
|
||||
return errors.New("invalid profile type")
|
||||
}
|
||||
f, err := os.Create(profileOutput)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return profile.WriteTo(f, 0)
|
||||
}
|
||||
}
|
@ -1,165 +0,0 @@
|
||||
// Copyright © 2023 OpenIM. All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// Package version print the client and server version information.
|
||||
package version
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/openim-sigs/component-base/pkg/json"
|
||||
"github.com/openim-sigs/component-base/pkg/version"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/internal/imctl/util/templates"
|
||||
"github.com/openimsdk/open-im-server/tools/imctl/pkg/cli/genericclioptions"
|
||||
cmdutil "github.com/openimsdk/open-im-server/tools/imctl/pkg/util"
|
||||
)
|
||||
|
||||
// Version is a struct for version information.
|
||||
type Version struct {
|
||||
ClientVersion *version.Info `json:"clientVersion,omitempty" yaml:"clientVersion,omitempty"`
|
||||
ServerVersion *version.Info `json:"serverVersion,omitempty" yaml:"serverVersion,omitempty"`
|
||||
}
|
||||
|
||||
var versionExample = templates.Examples(`
|
||||
# Print the client and server versions for the current context
|
||||
imctl version`)
|
||||
|
||||
// Options is a struct to support version command.
|
||||
type Options struct {
|
||||
ClientOnly bool
|
||||
Short bool
|
||||
Output string
|
||||
|
||||
client *restclient.RESTClient
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
|
||||
// NewOptions returns initialized Options.
|
||||
func NewOptions(ioStreams genericclioptions.IOStreams) *Options {
|
||||
return &Options{
|
||||
IOStreams: ioStreams,
|
||||
}
|
||||
}
|
||||
|
||||
// NewCmdVersion returns a cobra command for fetching versions.
|
||||
func NewCmdVersion(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
|
||||
o := NewOptions(ioStreams)
|
||||
cmd := &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Print the client and server version information",
|
||||
Long: "Print the client and server version information for the current context",
|
||||
Example: versionExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cmdutil.CheckErr(o.Complete(f, cmd))
|
||||
cmdutil.CheckErr(o.Validate())
|
||||
cmdutil.CheckErr(o.Run())
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().BoolVar(
|
||||
&o.ClientOnly,
|
||||
"client",
|
||||
o.ClientOnly,
|
||||
"If true, shows client version only (no server required).",
|
||||
)
|
||||
cmd.Flags().BoolVar(&o.Short, "short", o.Short, "If true, print just the version number.")
|
||||
cmd.Flags().StringVarP(&o.Output, "output", "o", o.Output, "One of 'yaml' or 'json'.")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Complete completes all the required options.
|
||||
func (o *Options) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
|
||||
var err error
|
||||
if o.ClientOnly {
|
||||
return nil
|
||||
}
|
||||
|
||||
o.client, err = f.RESTClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate validates the provided options.
|
||||
func (o *Options) Validate() error {
|
||||
if o.Output != "" && o.Output != "yaml" && o.Output != "json" {
|
||||
return errors.New(`--output must be 'yaml' or 'json'`)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run executes version command.
|
||||
func (o *Options) Run() error {
|
||||
var (
|
||||
serverVersion *version.Info
|
||||
serverErr error
|
||||
versionInfo Version
|
||||
)
|
||||
|
||||
clientVersion := version.Get()
|
||||
versionInfo.ClientVersion = &clientVersion
|
||||
|
||||
if !o.ClientOnly && o.client != nil {
|
||||
// Always request fresh data from the server
|
||||
if err := o.client.Get().AbsPath("/version").Do(context.TODO()).Into(&serverVersion); err != nil {
|
||||
return err
|
||||
}
|
||||
versionInfo.ServerVersion = serverVersion
|
||||
}
|
||||
|
||||
switch o.Output {
|
||||
case "":
|
||||
if o.Short {
|
||||
fmt.Fprintf(o.Out, "Client Version: %s\n", clientVersion.GitVersion)
|
||||
|
||||
if serverVersion != nil {
|
||||
fmt.Fprintf(o.Out, "Server Version: %s\n", serverVersion.GitVersion)
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(o.Out, "Client Version: %s\n", fmt.Sprintf("%#v", clientVersion))
|
||||
if serverVersion != nil {
|
||||
fmt.Fprintf(o.Out, "Server Version: %s\n", fmt.Sprintf("%#v", *serverVersion))
|
||||
}
|
||||
}
|
||||
case "yaml":
|
||||
marshaled, err := yaml.Marshal(&versionInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintln(o.Out, string(marshaled))
|
||||
case "json":
|
||||
marshaled, err := json.MarshalIndent(&versionInfo, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintln(o.Out, string(marshaled))
|
||||
default:
|
||||
// There is a bug in the program if we hit this case.
|
||||
// However, we follow a policy of never panicking.
|
||||
return fmt.Errorf("VersionOptions were not validated: --output=%q should have been rejected", o.Output)
|
||||
}
|
||||
|
||||
return serverErr
|
||||
}
|
Loading…
Reference in new issue