🧶 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
Xinwei Xiong 9 months ago committed by GitHub
parent 80064620b9
commit f198317ce7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -227,7 +227,6 @@ OPENIM_WEB_PORT=11001
# Default: OPENIM_WEB_ADDRESS=172.28.0.1
OPENIM_WEB_ADDRESS=172.28.0.8
# ======================================
# ========= OpenIM Server ==============
# ======================================

@ -15,6 +15,8 @@
name: Publish Docker image
on:
schedule:
- cron: '30 2 * * *'
push:
branches:
- main

@ -15,6 +15,8 @@
name: Build OpenIM Web Docker image
on:
schedule:
- cron: '30 3 * * *'
push:
branches:
- main
@ -28,114 +30,6 @@ env:
GO_VERSION: "1.20"
jobs:
build-dockerhub:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
# docker.io/openim/openim-server:latest
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v4.6.0
with:
images: openim/openim-server
# generate Docker tags based on the following events/attributes
tags: |
type=schedule
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha
- name: Log in to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push Docker image
uses: docker/build-push-action@v4
with:
context: .
# linux/ppc64le,linux/s390x
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-aliyun:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
# registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-server:latest
- name: Extract metadata (tags, labels) for Docker
id: meta2
uses: docker/metadata-action@v4.6.0
with:
images: registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-web
- name: Log in to AliYun Docker Hub
uses: docker/login-action@v2
with:
registry: registry.cn-hangzhou.aliyuncs.com
username: ${{ secrets.ALIREGISTRY_USERNAME }}
password: ${{ secrets.ALIREGISTRY_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v4
with:
context: .
# linux/ppc64le,linux/s390x
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta2.outputs.tags }}
labels: ${{ steps.meta2.outputs.labels }}
build-ghcr:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
# ghcr.io/openimsdk/openim-server:latest
- name: Extract metadata (tags, labels) for Docker
id: meta3
uses: docker/metadata-action@v4.6.0
with:
images: ghcr.io/openimsdk/openim-web
- name: Log in to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v4
with:
context: .
# linux/ppc64le,linux/s390x
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta3.outputs.tags }}
labels: ${{ steps.meta3.outputs.labels }}
build-openim-web-dockerhub:
runs-on: ubuntu-latest
steps:
@ -146,12 +40,12 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
# docker.io/openim/openim-server:latest
# docker.io/openim/openim-web:latest
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v4.6.0
with:
images: openim/openim-server
images: openim/openim-web
# generate Docker tags based on the following events/attributes
tags: |
type=schedule
@ -187,12 +81,12 @@ jobs:
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
# registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-server:latest
# registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-web:latest
- name: Extract metadata (tags, labels) for Docker
id: meta2
uses: docker/metadata-action@v4.6.0
with:
images: registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-server
images: registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-web
- name: Log in to AliYun Docker Hub
uses: docker/login-action@v2

@ -151,7 +151,7 @@ jobs:
version: 2.x
- name: Docker Operations
run: |
curl -o docker-compose.yaml https://raw.githubusercontent.com/OpenIMSDK/openim-docker/main/example/basic-openim-server-dependency.yml
curl -o docker-compose.yml https://raw.githubusercontent.com/OpenIMSDK/openim-docker/main/example/basic-openim-server-dependency.yml
sudo docker compose up -d
sudo sleep 60

1
.gitignore vendored

@ -160,7 +160,6 @@ flycheck_*.el
# Dependency directories (remove the comment below to include it)
vendor/
tools/imctl
# Go workspace file
# go.work

@ -8,24 +8,6 @@
## [Unreleased]
<a name="v3.1.3-beta.1"></a>
## [v3.1.3-beta.1] - 2023-08-14
<a name="v3.1.3"></a>
## [v3.1.3] - 2023-08-14
<a name="v3.1.2-beta.3"></a>
## [v3.1.2-beta.3] - 2023-08-09
<a name="v3.1.2-beta.2"></a>
## [v3.1.2-beta.2] - 2023-08-09
<a name="v3.1.2-beta.1"></a>
## [v3.1.2-beta.1] - 2023-08-09
<a name="v3.1.2-beta.0"></a>
## [v3.1.2-beta.0] - 2023-08-08
<a name="v3.1.0"></a>
## v3.1.0 - 2023-07-28
### Reverts
@ -35,10 +17,4 @@
- Merge branch 'tuoyun'
[Unreleased]: https://github.com/openimsdk/open-im-server/compare/v3.1.3-beta.1...HEAD
[v3.1.3-beta.1]: https://github.com/openimsdk/open-im-server/compare/v3.1.3...v3.1.3-beta.1
[v3.1.3]: https://github.com/openimsdk/open-im-server/compare/v3.1.2-beta.3...v3.1.3
[v3.1.2-beta.3]: https://github.com/openimsdk/open-im-server/compare/v3.1.2-beta.2...v3.1.2-beta.3
[v3.1.2-beta.2]: https://github.com/openimsdk/open-im-server/compare/v3.1.2-beta.1...v3.1.2-beta.2
[v3.1.2-beta.1]: https://github.com/openimsdk/open-im-server/compare/v3.1.2-beta.0...v3.1.2-beta.1
[v3.1.2-beta.0]: https://github.com/openimsdk/open-im-server/compare/v3.1.0...v3.1.2-beta.0
[Unreleased]: https://github.com/openimsdk/open-im-server/compare/v3.1.0...HEAD

@ -8,39 +8,15 @@
## [Unreleased]
<a name="v3.2.2"></a>
## [v3.2.2] - 2023-09-03
<a name="v3.2.3"></a>
## [v3.2.3] - 2023-09-03
<a name="v3.2.1"></a>
## [v3.2.1] - 2023-09-03
<a name="v3.2.2-beta.4"></a>
## [v3.2.2-beta.4] - 2023-08-28
<a name="v3.2.2-alpha.0"></a>
## [v3.2.2-alpha.0] - 2023-08-25
<a name="v3.2.2-beta.3"></a>
## [v3.2.2-beta.3] - 2023-08-22
<a name="v3.2.2-beta.2"></a>
## [v3.2.2-beta.2] - 2023-08-21
<a name="v3.2.2-beta.1"></a>
## [v3.2.2-beta.1] - 2023-08-19
<a name="v3.2.0"></a>
## [v3.2.0] - 2023-08-18
## [v3.2.0] - 2023-08-19
<a name="v3.2.0-rc.0"></a>
## [v3.2.0-rc.0] - 2023-08-17
<a name="v3.2.2-beta.0"></a>
## [v3.2.2-beta.0] - 2023-08-17
<a name="v3.2.0-alpha.0"></a>
## v3.2.0-alpha.0 - 2023-08-16
### Reverts
@ -50,15 +26,7 @@
- Merge branch 'tuoyun'
[Unreleased]: https://github.com/openimsdk/open-im-server/compare/v3.2.2...HEAD
[v3.2.2]: https://github.com/openimsdk/open-im-server/compare/v3.2.3...v3.2.2
[v3.2.3]: https://github.com/openimsdk/open-im-server/compare/v3.2.1...v3.2.3
[v3.2.1]: https://github.com/openimsdk/open-im-server/compare/v3.2.2-beta.4...v3.2.1
[v3.2.2-beta.4]: https://github.com/openimsdk/open-im-server/compare/v3.2.2-alpha.0...v3.2.2-beta.4
[v3.2.2-alpha.0]: https://github.com/openimsdk/open-im-server/compare/v3.2.2-beta.3...v3.2.2-alpha.0
[v3.2.2-beta.3]: https://github.com/openimsdk/open-im-server/compare/v3.2.2-beta.2...v3.2.2-beta.3
[v3.2.2-beta.2]: https://github.com/openimsdk/open-im-server/compare/v3.2.2-beta.1...v3.2.2-beta.2
[v3.2.2-beta.1]: https://github.com/openimsdk/open-im-server/compare/v3.2.0...v3.2.2-beta.1
[Unreleased]: https://github.com/openimsdk/open-im-server/compare/v3.2.2-alpha.0...HEAD
[v3.2.2-alpha.0]: https://github.com/openimsdk/open-im-server/compare/v3.2.0...v3.2.2-alpha.0
[v3.2.0]: https://github.com/openimsdk/open-im-server/compare/v3.2.0-rc.0...v3.2.0
[v3.2.0-rc.0]: https://github.com/openimsdk/open-im-server/compare/v3.2.2-beta.0...v3.2.0-rc.0
[v3.2.2-beta.0]: https://github.com/openimsdk/open-im-server/compare/v3.2.0-alpha.0...v3.2.2-beta.0
[v3.2.0-rc.0]: https://github.com/openimsdk/open-im-server/compare/v3.2.0-alpha.0...v3.2.0-rc.0

@ -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

@ -73,6 +73,11 @@ gen:
demo:
@$(MAKE) go.demo
## versionchecker: Check version of openim. ✨
.PHONY: versionchecker
versionchecker:
@$(MAKE) go.versionchecker
## build: Build binaries by default ✨
.PHONY: build
build:

@ -24,7 +24,7 @@
<p align="center">
<a href="./README.md"><b> English </b></a>
<a href="./README-zh_CN.md"><b> 简体中文 </b></a>
<a href="https://www.openim.online/en"><b> Docs </b></a>
<a href="https://www.openim.online/en"><b> Docs </b></a>
</p>
@ -166,7 +166,7 @@ Deploy basic components at the click of a command:
```bash
# install openim dependency
$ git clone https://github.com/openimsdk/open-im-server openim/openim-server && export openim=$(pwd)/openim/openim-server && cd $openim/openim-server && git checkout $OPENIM_VERSION
$ make init && docker compose -f basic-openim-server-dependency.yml up -d && make start && make check
$ make init && docker compose up -d && make start && make check
```
> `make help` to help you see the instructions supported by OpenIM.
@ -211,17 +211,17 @@ Read: https://github.com/openimsdk/open-im-server/blob/main/deployments/README.m
</details>
## :link: Relationship Between APP and OpenIM
## :link: OpenIM and your application
OpenIM isn't just an open-source instant messaging component, it's an integral part of your application ecosystem. Check out this diagram to understand how AppServer, AppClient, Open-IM-Server, and Open-IM-SDK interact.
OpenIM isn't just an open-source instant messaging component, it's an integral part of your application ecosystem. Check out this diagram to understand how AppServer, AppClient, OpenIMServer, and OpenIMSDK interact.
![App-OpenIM Relationship](https://github.com/openimsdk/open-im-server/blob/main/docs/images/open-im-server.png)
![App-OpenIM Relationship](./docs/images/oepnim-design.png)
## :building_construction: Overall Architecture
<!-- ## :building_construction: Overall Architecture
Delve into the heart of Open-IM-Server's functionality with our architecture diagram.
![Overall Architecture](https://github.com/openimsdk/open-im-server/blob/main/docs/images/Architecture.jpg)
![Overall Architecture](./docs/images/Architecture.jpg) -->
## :hammer_and_wrench: To start developing OpenIM

@ -49,17 +49,17 @@ While it is possible to build OpenIM using a local golang installation, we have
## Basic Flow
The scripts directly under [`build/`](.) are used to build and test. They will ensure that the `kube-build` Docker image is built (based on [`build/build-image/Dockerfile`](build-image/Dockerfile) and after base image's `KUBE_BUILD_IMAGE_CROSS_TAG` from Dockerfile is replaced with one of those actual tags of the base image, like `v1.13.9-2`) and then execute the appropriate command in that container. These scripts will both ensure that the right data is cached from run to run for incremental builds and will copy the results back out of the container. You can specify a different registry/name and version for `kube-cross` by setting `KUBE_CROSS_IMAGE` and `KUBE_CROSS_VERSION`, see [`common.sh`](common.sh) for more details.
The scripts directly under [`build/`](.) are used to build and test. They will ensure that the `openim-build` Docker image is built (based on [`build/build-image/Dockerfile`](../Dockerfile) and after base image's `OPENIM_BUILD_IMAGE_CROSS_TAG` from Dockerfile is replaced with one of those actual tags of the base image, like `v1.13.9-2`) and then execute the appropriate command in that container. These scripts will both ensure that the right data is cached from run to run for incremental builds and will copy the results back out of the container. You can specify a different registry/name and version for `openim-cross` by setting `OPENIM_CROSS_IMAGE` and `OPENIM_CROSS_VERSION`, see [`common.sh`](common.sh) for more details.
The `kube-build` container image is built by first creating a "context" directory in `_output/images/build-image`. It is done there instead of at the root of the OpenIM repo to minimize the amount of data we need to package up when building the image.
The `openim-build` container image is built by first creating a "context" directory in `_output/images/build-image`. It is done there instead of at the root of the OpenIM repo to minimize the amount of data we need to package up when building the image.
There are 3 different containers instances that are run from this image. The first is a "data" container to store all data that needs to persist across to support incremental builds. Next there is an "rsync" container that is used to transfer data in and out to the data container. Lastly there is a "build" container that is used for actually doing build actions. The data container persists across runs while the rsync and build containers are deleted after each use.
`rsync` is used transparently behind the scenes to efficiently move data in and out of the container. This will use an ephemeral port picked by Docker. You can modify this by setting the `KUBE_RSYNC_PORT` env variable.
`rsync` is used transparently behind the scenes to efficiently move data in and out of the container. This will use an ephemeral port picked by Docker. You can modify this by setting the `OPENIM_RSYNC_PORT` env variable.
All Docker names are suffixed with a hash derived from the file path (to allow concurrent usage on things like CI machines) and a version number. When the version number changes all state is cleared and clean build is started. This allows the build infrastructure to be changed and signal to CI systems that old artifacts need to be deleted.
## Build artifacts
The build system output all its products to a top level directory in the source repository named `_output`.
These include the binary compiled packages (e.g. kubectl, kube-scheduler etc.) and archived Docker images.
These include the binary compiled packages (e.g. imctl, openim-api etc.) and archived Docker images.
If you intend to run a component with a docker image you will need to import it from this directory with

@ -156,7 +156,6 @@ object:
sessionToken: ''
publicRead: false
###################### RPC Port Configuration ######################
# RPC service ports
# These ports are passed into the program by the script and are not recommended to modify
@ -197,7 +196,7 @@ rpcRegisterName:
# Whether to output in json format
# Whether to include stack trace in logs
log:
storageLocation: /root/workspaces/openim/openim-server/logs/
storageLocation: ../../logs/
rotationTime: 24
remainRotationCount: 2
remainLogLevel: 6
@ -229,18 +228,18 @@ push:
enable: getui
geTui:
pushUrl: "https://restapi.getui.com/v2/$appId"
masterSecret: ""
appKey: ""
intent: ""
channelID: ""
channelName: ""
masterSecret: ''
appKey: ''
intent: ''
channelID: ''
channelName: ''
fcm:
serviceAccount: "x.json"
jpns:
appKey:
masterSecret:
pushUrl:
pushIntent:
appKey: ''
masterSecret: ''
pushUrl: ''
pushIntent: ''
# App manager configuration
#

@ -73,7 +73,7 @@ $ SEALOS_VERSION=`curl -s https://api.github.com/repos/labring/sealos/releases/l
```bash
$ export CLUSTER_USERNAME=ubuntu
$ export CLUSTER_PASSWORD=123456
$ sealos run labring/kubernetes:v1.25.0 labring/helm:v3.8.2 labring/calico:v3.24.1 \
$ sudo sealos run labring/kubernetes:v1.25.0 labring/helm:v3.8.2 labring/calico:v3.24.1 \
--masters 10.0.0.9 \
--nodes 10.0.0.4,10.0.0.10 \
-u "$CLUSTER_USERNAME" \

@ -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.

@ -35,4 +35,40 @@ version: 0.1.0
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "1.16.0"
appVersion: "default"
icon: https://raw.githubusercontent.com/openimsdk/open-im-server/main/assets/openim-logo-gradient.svg
maintainers:
- name: "OpenIM"
url: "https://github.com/openimsdk"
keywords:
- openim
- im
- chat
sources:
- "https://github.com/openimsdk/open-im-server"
- "https://github.com/openimsdk/openim-sdk-core"
- "https://github.com/openimsdk/openim-docker"
dependencies:
- name: mysql
version: 8.0.25
repository: https://charts.bitnami.com/bitnami
- name: redis
version: 14.6.1
repository: https://charts.bitnami.com/bitnami
- name: mongodb
version: 10.1.0
repository: https://charts.bitnami.com/bitnami
- name: kafka
version: 14.1.0
repository: https://charts.bitnami.com/bitnami
- name: minio
version: 8.1.2
repository: https://charts.bitnami.com/bitnami
- name: zookeeper
version: 5.17.0
repository: https://charts.bitnami.com/bitnami

@ -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,15 @@
# OpenIM Server Chat
## 目录结构
```bash
openim-server/
Chart.yaml # 包含了chart信息的YAML文件
LICENSE # 包含OpenIM Chart许可证的纯文本文件
README.md # OpenIM 可读的README文件
values.yaml # chart 默认的配置值
charts/ # 包含chart依赖的其他chart
crds/ # 自定义资源的定义
templates/ # 模板目录, 当和values 结合时可生成有效的Kubernetes manifest文件
templates/NOTES.txt # 包含简要使用说明的纯文本文件
```

@ -36,6 +36,13 @@ API_URL=${API_URL}
# Default: DATA_DIR=./
DATA_DIR=${DATA_DIR}
# Choose the appropriate image address, the default is GITHUB image,
# you can choose docker hub, for Chinese users can choose Ali Cloud
# export IMAGE_REGISTRY="ghcr.io/openimsdk"
# export IMAGE_REGISTRY="openim"
# export IMAGE_REGISTRY="registry.cn-hangzhou.aliyuncs.com/openimsdk"
IMAGE_REGISTRY=${IMAGE_REGISTRY}
# ======================================
# ========= Network Configuration ======
# ======================================
@ -227,7 +234,6 @@ OPENIM_WEB_PORT=${OPENIM_WEB_PORT}
# Default: OPENIM_WEB_ADDRESS=172.28.0.1
OPENIM_WEB_ADDRESS=${OPENIM_WEB_NETWORK_ADDRESS}
# ======================================
# ========= OpenIM Server ==============
# ======================================

@ -228,18 +228,18 @@ push:
enable: ${PUSH_ENABLE}
geTui:
pushUrl: "${GETUI_PUSH_URL}"
masterSecret: ""
appKey: ""
intent: ""
channelID: ""
channelName: ""
masterSecret: ${GETUI_MASTER_SECRET}
appKey: ${GETUI_APP_KEY}
intent: ${GETUI_INTENT}
channelID: ${GETUI_CHANNEL_ID}
channelName: ${GETUI_CHANNEL_NAME}
fcm:
serviceAccount: "${FCM_SERVICE_ACCOUNT}"
jpns:
appKey:
masterSecret:
pushUrl:
pushIntent:
appKey: ${JPNS_APP_KEY}
masterSecret: ${JPNS_MASTER_SECRET}
pushUrl: ${JPNS_PUSH_URL}
pushIntent: ${JPNS_PUSH_INTENT}
# App manager configuration
#
@ -353,6 +353,10 @@ callback:
enable: false
timeout: 5
failedContinue: true
beforeUpdateUserInfo:
enable: false
timeout: 5
failedContinue: true
beforeCreateGroup:
enable: false
timeout: 5

@ -127,9 +127,10 @@ services:
ipv4_address: ${MINIO_NETWORK_ADDRESS}
openim-web:
image: ghcr.io/openimsdk/openim-web:latest
# image: ghcr.io/openimsdk/openim-web:latest
# image: registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-web:latest
# image: openim/openim-web:latest
image: ${IMAGE_REGISTRY}/openim-web:latest
container_name: openim-web
environment:
- OPENIM_WEB_DIST_PATH=${OPENIM_WEB_DIST_PATH}
@ -142,9 +143,10 @@ services:
ipv4_address: ${OPENIM_WEB_NETWORK_ADDRESS}
# openim-server:
# image: ghcr.io/openimsdk/openim-server:main
# # image: ghcr.io/openimsdk/openim-server:main
# # image: registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-server:main
# # image: openim/openim-server:main
# image: ${IMAGE_REGISTRY}/openim-server:main
# # build: .
# container_name: openim-server
# ports:
@ -203,4 +205,4 @@ services:
# - prometheus
# networks:
# openim-server:
# ipv4_address: ${GRAFANA_NETWORK_ADDRESS}
# ipv4_address: ${GRAFANA_NETWORK_ADDRESS}

@ -199,9 +199,6 @@ It's crucial to verify the configurations by checking the connectivity between y
```
## Config options
...

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

@ -62,6 +62,7 @@ echo "+++ The port being checked: ${OPENIM_DEPENDENCY_PORT_LISTARIES[@]}"
set +e
# Later, after discarding Docker, the Docker keyword is unreliable, and Kubepods is used
if grep -qE 'docker|kubepods' /proc/1/cgroup || [ -f /.dockerenv ]; then
openim::color::echo ${COLOR_BLUE} "Environment in the interior of the container"
else

@ -25,7 +25,6 @@ source "${OPENIM_ROOT}/scripts/lib/init.sh"
trap 'openim::util::onCtrlC' INT
chmod +x "${OPENIM_ROOT}"/scripts/*.sh
"${OPENIM_ROOT}"/scripts/init-config.sh
openim::util::ensure_docker_daemon_connectivity
@ -40,10 +39,12 @@ else
fi
pushd "${OPENIM_ROOT}"
${DOCKER_COMPOSE_COMMAND} up -d
${DOCKER_COMPOSE_COMMAND} stop
curl https://gitee.com/openimsdk/openim-docker/raw/main/example/full-openim-server-and-chat.yml -o docker-compose.yml && make init && docker compose up -d
"${OPENIM_ROOT}"/scripts/init-config.sh
${DOCKER_COMPOSE_COMMAND} up --remove-orphans -d
sleep 60
${DOCKER_COMPOSE_COMMAND} logs
${DOCKER_COMPOSE_COMMAND} logs openim-server
${DOCKER_COMPOSE_COMMAND} ps
popd

@ -69,6 +69,15 @@ def "ENV_FILE" ""${OPENIM_ROOT}"/scripts/install/environment.sh"
def "CHAT_BRANCH" "main"
def "SERVER_BRANCH" "main"
# Choose the appropriate image address, the default is GITHUB image,
# you can choose docker hub, for Chinese users can choose Ali Cloud
# export IMAGE_REGISTRY="ghcr.io/openimsdk"
# export IMAGE_REGISTRY="openim"
# export IMAGE_REGISTRY="registry.cn-hangzhou.aliyuncs.com/openimsdk"
def "IMAGE_REGISTRY" "ghcr.io/openimsdk"
# def "IMAGE_REGISTRY" "openim"
# def "IMAGE_REGISTRY" "registry.cn-hangzhou.aliyuncs.com/openimsdk"
###################### OpenIM Docker Network ######################
# 设置 Docker 网络的网段
readonly DOCKER_BRIDGE_SUBNET=${DOCKER_BRIDGE_SUBNET:-'172.28.0.0/16'}
@ -289,11 +298,16 @@ def "WEBSOCKET_TIMEOUT" "10" # Websocket超时
def "PUSH_ENABLE" "getui" # 推送是否启用
# GeTui推送URL
readonly GETUI_PUSH_URL=${GETUI_PUSH_URL:-'https://restapi.getui.com/v2/$appId'}
def "GETUI_MASTER_SECRET" "" # GeTui主密钥
def "GETUI_APP_KEY" "" # GeTui应用密钥
def "GETUI_INTENT" "" # GeTui推送意图
def "GETUI_CHANNEL_ID" "" # GeTui渠道ID
def "GETUI_CHANNEL_NAME" "" # GeTui渠道名称
def "FCM_SERVICE_ACCOUNT" "x.json" # FCM服务账户
def "JPNS_APP_KEY" # JPNS应用密钥
def "JPNS_MASTER_SECRET" # JPNS主密钥
def "JPNS_PUSH_URL" # JPNS推送URL
def "JPNS_PUSH_INTENT" # JPNS推送意图
def "JPNS_APP_KEY" "" # JPNS应用密钥
def "JPNS_MASTER_SECRET" "" # JPNS主密钥
def "JPNS_PUSH_URL" "" # JPNS推送URL
def "JPNS_PUSH_INTENT" "" # JPNS推送意图
def "MANAGER_USERID_1" "openIM123456" # 管理员ID 1
def "MANAGER_USERID_2" "openIM654321" # 管理员ID 2
def "MANAGER_USERID_3" "openIMAdmin" # 管理员ID 3

@ -48,7 +48,7 @@ function openim::crontask::start()
openim::log::info "Start OpenIM Cron, binary root: ${SERVER_NAME}"
openim::log::status "Start OpenIM Cron, path: ${OPENIM_CRONTASK_BINARY}"
openim::util::stop_services_with_name ${SERVER_NAME}
openim::util::stop_services_with_name ${OPENIM_CRONTASK_BINARY}
openim::log::status "start cron_task process, path: ${OPENIM_CRONTASK_BINARY}"
nohup ${OPENIM_CRONTASK_BINARY} >> ${LOG_FILE} 2>&1 &

@ -54,14 +54,14 @@ function openim::push::start()
openim::log::status "Start OpenIM Push, binary root: ${SERVER_NAME}"
openim::log::info "Start OpenIM Push, path: ${OPENIM_PUSH_BINARY}"
openim::util::stop_services_with_name ${SERVER_NAME}
openim::log::status "prepare start push process, path: ${OPENIM_PUSH_BINARY}"
openim::log::status "prepare start push process, port: ${OPENIM_PUSH_PORT}, prometheus port: ${PUSH_PROM_PORT}"
OPENIM_PUSH_PORTS_ARRAY=$(openim::util::list-to-string ${OPENIM_PUSH_PORT} )
PUSH_PROM_PORTS_ARRAY=$(openim::util::list-to-string ${PUSH_PROM_PORT} )
openim::util::stop_services_with_name ${SERVER_NAME}
openim::log::status "push port list: ${OPENIM_PUSH_PORTS_ARRAY[@]}"
openim::log::status "prometheus port list: ${PUSH_PROM_PORTS_ARRAY[@]}"
@ -94,7 +94,7 @@ function openim::push::install()
# 1. Build openim-push
make build BINS=${SERVER_NAME}
openim::common::sudo "cp ${OPENIM_OUTPUT_HOSTBIN}/${SERVER_NAME} ${OPENIM_INSTALL_DIR}/bin"
openim::common::sudo "cp -r ${OPENIM_OUTPUT_HOSTBIN}/${SERVER_NAME} ${OPENIM_INSTALL_DIR}/bin"
openim::log::status "${SERVER_NAME} binary: ${OPENIM_INSTALL_DIR}/bin/${SERVER_NAME}"
@ -150,4 +150,4 @@ function openim::push::status()
if [[ "$*" =~ openim::push:: ]];then
eval $*
fi
fi

@ -129,7 +129,7 @@ function openim::tools::post-start() {
openim::log::info "Post-start actions for OpenIM Tools..."
for tool in "${OPENIM_TOOLS_POST_START_NAME_LISTARIES[@]}"; do
openim::log::info "Starting ${tool}..."
# openim::tools::start_service ${tool}
openim::tools::start_service ${tool}
sleep 0.2
done
}

@ -17,7 +17,7 @@
#
GO := go
GO_SUPPORTED_VERSIONS ?= 1.18|1.19|1.20|1.21
GO_SUPPORTED_VERSIONS ?= 1.18|1.19|1.20|1.21|1.22
GO_LDFLAGS += -X $(VERSION_PACKAGE).gitVersion=$(GIT_TAG) \
-X $(VERSION_PACKAGE).gitCommit=$(GIT_COMMIT) \
@ -125,6 +125,10 @@ go.check-component:
@echo "===========> Checking openim component"
@$(ROOT_DIR)/scripts/install/openim-tools.sh openim::tools::pre-start
## go.versionchecker: Design, detect some environment variables and versions
go.versionchecker:
@$(ROOT_DIR)/scripts/install/openim-tools.sh openim::tools::post-start
## go.build.verify: Verify that a suitable version of Go exists
.PHONY: go.build.verify
go.build.verify:

@ -21,7 +21,7 @@
#
DOCKER := docker
DOCKER_SUPPORTED_API_VERSION ?= 1.32|1.40|1.41
DOCKER_SUPPORTED_API_VERSION ?= 1.32|1.40|1.41|1.42
# read: https://github.com/openimsdk/open-im-server/blob/main/docs/conversions/images.md
REGISTRY_PREFIX ?= ghcr.io/openimsdk

@ -22,6 +22,7 @@ import (
"net"
"net/url"
"os"
"strings"
"time"
"github.com/minio/minio-go/v7"
@ -116,24 +117,16 @@ func main() {
os.Exit(1)
}
func checkMinioIP() error {
for _, i := range []string{config.Config.Object.ApiURL, config.Config.Object.Minio.SignEndpoint} {
u, err := url.Parse(i)
if err != nil {
return utils.Wrap(err, "api format error,please check config file apiURL or Minio SignEndpoint")
}
if u.Scheme == "https" {
continue
}
host, _, err := net.SplitHostPort(u.Host)
if err != nil {
host = u.Host
}
if host == "127.0.0.1" {
return ErrConfig.Wrap("apiURL or Minio SignEndpoint endpoint contain 127.0.0.1,please modify it")
}
func exactIP(urll string) string {
u, _ := url.Parse(urll)
host, _, err := net.SplitHostPort(u.Host)
if err != nil {
host = u.Host
}
return nil
if strings.HasSuffix(host, ":") {
host = host[0 : len(host)-1]
}
return host
}
func checkMysql() error {
@ -212,8 +205,8 @@ func checkMinio() error {
return ErrComponentStart.Wrap("Minio server is offline")
}
}
if checkMinioIP() != nil {
return checkMinioIP()
if exactIP(config.Config.Object.ApiURL) == "127.0.0.1" || exactIP(config.Config.Object.Minio.SignEndpoint) == "127.0.0.1" {
return ErrConfig.Wrap("apiURL or Minio SignEndpoint endpoint contain 127.0.0.1")
}
}
return nil

@ -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,4 +1,4 @@
module github.com/openimsdk/open-im-server/v3/tools/imctl
module github.com/openimsdk/open-im-server/v3/tools/imctl
go 1.18
@ -14,6 +14,5 @@ require (
require (
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
golang.org/x/sys v0.10.0 // indirect
k8s.io/kubernetes v1.28.2
golang.org/x/sys v0.1.0 // indirect
)

@ -20,8 +20,5 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/kubernetes v1.28.2 h1:GhcnYeNTukeaC0dD5BC+UWBvzQsFEpWj7XBVMQptfYc=
k8s.io/kubernetes v1.28.2/go.mod h1:FmB1Mlp9ua0ezuwQCTGs/y6wj/fVisN2sVxhzjj0WDk=

@ -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…
Cancel
Save