From 4281600e0d9f9dc7a17e58a03f6360b760bf0b4f Mon Sep 17 00:00:00 2001 From: "Xinwei Xiong(cubxxw-openim)" <3293172751nss@gmail.com> Date: Wed, 30 Aug 2023 16:21:39 +0800 Subject: [PATCH] feat: add more test project Signed-off-by: Xinwei Xiong(cubxxw-openim) <3293172751nss@gmail.com> --- .github/workflows/greetings.yml | 2 + .github/workflows/scripts-verify.yml | 4 +- config/config-copy.yaml | 378 ------------------------ deployments/templates/env_template.yaml | 18 ++ docker-compose.yml | 10 + go.work | 1 + scripts/install/environment.sh | 5 + tools/component/component_test.go | 41 +++ tools/web/README.md | 64 ++++ tools/web/go.mod | 5 + tools/web/go.sum | 4 + tools/web/web.go | 44 +++ tools/web/web_test.go | 57 ++++ 13 files changed, 254 insertions(+), 379 deletions(-) delete mode 100644 config/config-copy.yaml create mode 100644 tools/component/component_test.go create mode 100644 tools/web/README.md create mode 100644 tools/web/go.mod create mode 100644 tools/web/go.sum create mode 100644 tools/web/web.go create mode 100644 tools/web/web_test.go diff --git a/.github/workflows/greetings.yml b/.github/workflows/greetings.yml index 5ebb3681c..bed465cff 100644 --- a/.github/workflows/greetings.yml +++ b/.github/workflows/greetings.yml @@ -38,6 +38,8 @@ jobs: [Join slack 🤖](https://join.slack.com/t/openimsdk/shared_invite/zt-22720d66b-o_FvKxMTGXtcnnnHiMqe9Q) to connect and communicate with our developers. + Please leave your information in the [✨ discussions](https://github.com/orgs/OpenIMSDK/discussions/426), we expect anyone to join OpenIM developer community. + issue-message: | Hello! Thank you for filing an issue. diff --git a/.github/workflows/scripts-verify.yml b/.github/workflows/scripts-verify.yml index f3d885814..65d61d84b 100644 --- a/.github/workflows/scripts-verify.yml +++ b/.github/workflows/scripts-verify.yml @@ -68,7 +68,9 @@ jobs: - name: verify format run: | sudo make format + continue-on-error: true - name: verify license run: | - sudo make verify-copyright \ No newline at end of file + sudo make verify-copyright + continue-on-error: true \ No newline at end of file diff --git a/config/config-copy.yaml b/config/config-copy.yaml deleted file mode 100644 index 27f01fb8b..000000000 --- a/config/config-copy.yaml +++ /dev/null @@ -1,378 +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. - -# ----------------------------------------------------------------- -# Infrastructural configurations, please modify based on your setup -# ----------------------------------------------------------------- - -###################### Zookeeper ###################### -# Zookeeper configuration -# It's not recommended to modify the schema -# -# Zookeeper address -# Zookeeper username -# Zookeeper password -zookeeper: - schema: openim - address: [ 127.0.0.1:2181 ] - username: - password: - -###################### Mysql ###################### -# MySQL configuration -# Currently, only single machine setup is supported -# -# Maximum number of open connections -# Maximum number of idle connections -# Maximum lifetime in seconds a connection can be reused -# Log level: 1=slient, 2=error, 3=warn, 4=info -# Slow query threshold in milliseconds -mysql: - address: [ 127.0.0.1:13306 ] - username: root - password: openIM123 - database: openIM_v3 - maxOpenConn: 1000 - maxIdleConn: 100 - maxLifeTime: 60 - logLevel: 4 - slowThreshold: 500 - -###################### Mongo ###################### -# MongoDB configuration -# If uri is not empty, it will be used directly -# -# MongoDB address for standalone setup, Mongos address for sharded cluster setup -# Default MongoDB database name -# Maximum connection pool size -mongo: - uri: - address: [ 127.0.0.1:37017 ] - database: openIM_v3 - username: root - password: openIM123 - maxPoolSize: 100 - -###################### Redis ###################### -# Redis configuration -# -# Username is required only for Redis version 6.0+ -redis: - address: [ 127.0.0.1:16379 ] - username: - password: openIM123 - -###################### Kafka ###################### -# Kafka configuration -# -# Kafka username -# Kafka password -# It's not recommended to modify this topic name -# Consumer group ID, it's not recommended to modify -kafka: - username: - password: - addr: [ 127.0.0.1:9092 ] - latestMsgToRedis: - topic: "latestMsgToRedis" - offlineMsgToMongo: - topic: "offlineMsgToMongoMysql" - msgToPush: - topic: "msgToPush" - consumerGroupID: - msgToRedis: redis - msgToMongo: mongo - msgToMySql: mysql - msgToPush: push - -###################### RPC ###################### -# RPC configuration -# -# IP address to register with zookeeper when starting RPC, the IP and corresponding rpcPort should be accessible by api/gateway -# Default listen IP is 0.0.0.0 -rpc: - registerIP: - listenIP: 0.0.0.0 - -###################### API ###################### -# API configuration -# -# API service port -# Default listen IP is 0.0.0.0 -api: - openImApiPort: [ 10002 ] - listenIP: 0.0.0.0 - -###################### Gateway ###################### -# Object storage configuration -# -# Use minio for object storage -# API URL should be accessible by the app -# It's not recommended to modify the bucket name -# Endpoint should be accessible by the app -# Session token -# Configuration for Tencent COS -# Configuration for Aliyun OSS -# apiURL is the address of the api, the access address of the app, use s3 must be configured -# minio.endpoint can be configured as an intranet address, -# minio.signEndpoint is minio public network address -object: - enable: "minio" - apiURL: "http://127.0.0.1:10002" - minio: - bucket: "openim" - endpoint: "http://127.0.0.1:10005" - accessKeyID: "root" - secretAccessKey: "openIM123" - sessionToken: "" - signEndpoint: "http://127.0.0.1:10005" - cos: - bucketURL: "https://temp-1252357374.cos.ap-chengdu.myqcloud.com" - secretID: "" - secretKey: "" - sessionToken: "" - oss: - endpoint: "https://oss-cn-chengdu.aliyuncs.com" - bucket: "demo-9999999" - bucketURL: "https://demo-9999999.oss-cn-chengdu.aliyuncs.com" - accessKeyID: "" - accessKeySecret: "" - sessionToken: "" - -# RPC service ports -# These ports are passed into the program by the script and are not recommended to modify -# For launching multiple programs, just fill in multiple ports separated by commas -# For example, [10110, 10111] -rpcPort: - openImUserPort: [ 10110 ] - openImFriendPort: [ 10120 ] - openImMessagePort: [ 10130 ] - openImMessageGatewayPort: [ 10140 ] - openImGroupPort: [ 10150 ] - openImAuthPort: [ 10160 ] - openImPushPort: [ 10170 ] - openImConversationPort: [ 10180 ] - openImThirdPort: [ 10190 ] - -# RPC service names for registration, it's not recommended to modify these -rpcRegisterName: - openImUserName: User - openImFriendName: Friend - openImMsgName: Msg - openImPushName: Push - openImMessageGatewayName: MessageGateway - openImGroupName: Group - openImAuthName: Auth - openImConversationName: Conversation - openImThirdName: Third - -# Log configuration -# -# Storage directory -# Log rotation time -# Maximum number of logs to retain -# Log level, 6 means all levels -# Whether to output to stdout -# Whether to output in json format -# Whether to include stack trace in logs -log: - storageLocation: ../../../../../logs/ - rotationTime: 24 - remainRotationCount: 2 - remainLogLevel: 6 - isStdout: false - isJson: false - withStack: false - -# Long connection server configuration -# -# Websocket port for msg_gateway -# Maximum number of websocket connections -# Maximum length of websocket request package -# Websocket connection handshake timeout -longConnSvr: - openImWsPort: [ 10001 ] - websocketMaxConnNum: 100000 - websocketMaxMsgLen: 4096 - websocketTimeout: 10 - -# Push notification service configuration -# -# Use GeTui for push notifications -# GeTui offline push configuration -# FCM offline push configuration -# Account file, place it in the config directory -# JPush configuration, modify these after applying in JPush backend -push: - enable: getui - geTui: - pushUrl: "https://restapi.getui.com/v2/$appId" - masterSecret: "" - appKey: "" - intent: "" - channelID: "" - channelName: "" - fcm: - serviceAccount: "x.json" - jpns: - appKey: - masterSecret: - pushUrl: - pushIntent: - -# App manager configuration -# -# Built-in app manager user IDs -# Built-in app manager nicknames -manager: - userID: [ "openIM123456","openIM654321","openIMAdmin" ] - nickname: [ "system1","system2", "system3" ] - -# Multi-platform login policy -# For each platform(Android, iOS, Windows, Mac, web), only one can be online at a time -multiLoginPolicy: 1 - -# Whether to store messages in MySQL, messages in MySQL are only used for management background -chatPersistenceMysql: true - -# Message cache timeout in seconds, it's not recommended to modify -msgCacheTimeout: 86400 - -# Whether to enable read receipts for group chat -groupMessageHasReadReceiptEnable: true - -# Whether to enable read receipts for single chat -singleMessageHasReadReceiptEnable: true - -# MongoDB offline message retention period in days -retainChatRecords: 365 - -# Schedule to clear expired messages(older than retainChatRecords days) in MongoDB every Wednesday at 2am -# This deletion is just for cleaning up disk usage according to previous configuration retainChatRecords, no notification will be sent -chatRecordsClearTime: "0 2 * * 3" - -# Schedule to auto delete messages every day at 2am -# This deletion is for messages that have been retained for more than msg_destruct_time (seconds) in the conversation field -msgDestructTime: "0 2 * * *" - -# Secret key -secret: openIM123 - -# Token policy -# -# Token expiration period in days -tokenPolicy: - expire: 90 - -# Message verification policy -# -# Whether to verify friendship when sending messages -messageVerify: - friendVerify: false - -# iOS push notification configuration -# -# iOS push notification sound -# Whether to count badge -# Whether it's production environment -iosPush: - pushSound: "xxx" - badgeCount: true - production: false - -# Callback configuration -# -# Callback URL -# Whether to enable this callback event -# Timeout in seconds -# Whether to continue execution if callback fails -callback: - url: - beforeSendSingleMsg: - enable: false - timeout: 5 - failedContinue: true - afterSendSingleMsg: - enable: false - timeout: 5 - beforeSendGroupMsg: - enable: false - timeout: 5 - failedContinue: true - afterSendGroupMsg: - enable: false - timeout: 5 - msgModify: - enable: false - timeout: 5 - failedContinue: true - userOnline: - enable: false - timeout: 5 - userOffline: - enable: false - timeout: 5 - userKickOff: - enable: false - timeout: 5 - offlinePush: - enable: false - timeout: 5 - failedContinue: true - onlinePush: - enable: false - timeout: 5 - failedContinue: true - superGroupOnlinePush: - enable: false - timeout: 5 - failedContinue: true - beforeAddFriend: - enable: false - timeout: 5 - failedContinue: true - beforeCreateGroup: - enable: false - timeout: 5 - failedContinue: true - beforeMemberJoinGroup: - enable: false - timeout: 5 - failedContinue: true - beforeSetGroupMemberInfo: - enable: false - timeout: 5 - failedContinue: true - setMessageReactionExtensions: - enable: false - timeout: 5 - failedContinue: true - -###################### Prometheus ###################### -# Prometheus configuration -# The number of Prometheus ports per service needs to correspond to rpcPort -# The number of ports needs to be consistent with msg_transfer_service_num in script/path_info.sh -prometheus: - enable: false - userPrometheusPort: [ 20110 ] - friendPrometheusPort: [ 20120 ] - messagePrometheusPort: [ 20130 ] - messageGatewayPrometheusPort: [ 20140 ] - groupPrometheusPort: [ 20150 ] - authPrometheusPort: [ 20160 ] - pushPrometheusPort: [ 20170 ] - conversationPrometheusPort: [ 20230 ] - rtcPrometheusPort: [ 21300 ] - thirdPrometheusPort: [ 21301 ] - messageTransferPrometheusPort: [ 21400, 21401, 21402, 21403 ] \ No newline at end of file diff --git a/deployments/templates/env_template.yaml b/deployments/templates/env_template.yaml index f3b80b534..9441f24d6 100644 --- a/deployments/templates/env_template.yaml +++ b/deployments/templates/env_template.yaml @@ -1,3 +1,17 @@ +# 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. + # ================= Basic Configuration =================== # User for authentication or system operations USER=${USER} @@ -66,3 +80,7 @@ MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY} # Secret key corresponding to the access key for MinIO authentication MINIO_SECRET_KEY=${MINIO_SECRET_KEY} + +# ================== OpenIM Web =========================== +OPENIM_WEB_DIST_PATH=${OPENIM_WEB_DIST_PATH} +OPENIM_WEB_PPRT=${OPENIM_WEB_PPRT} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 6f4af08ca..9aba5d98d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -94,6 +94,16 @@ services: restart: always command: minio server /data --console-address ':9090' + # openim-web: + # image: ghcr.io/openimsdk/openim-web:main + # container_name: openim-web + # environment: + # - OPENIM_WEB_DIST_PATH=${OPENIM_WEB_DIST_PATH} + # - OPENIM_WEB_PPRT=${OPENIM_WEB_PPRT} + # restart: always + # ports: + # - "${OPENIM_WEB_PPRT}:11001" + openim-server: image: ghcr.io/openimsdk/openim-server:main # image: registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-server:main diff --git a/go.work b/go.work index a7024b994..a2772ddfe 100644 --- a/go.work +++ b/go.work @@ -8,5 +8,6 @@ use ( ./tools/infra ./tools/ncpu ./tools/versionchecker + ./tools/web ./tools/yamlfmt ) diff --git a/scripts/install/environment.sh b/scripts/install/environment.sh index 4e383ccb4..90d6d89d6 100755 --- a/scripts/install/environment.sh +++ b/scripts/install/environment.sh @@ -70,6 +70,11 @@ def "OPENIM_LOG_DIR" "/var/log/openim" def "CA_FILE" "${OPENIM_CONFIG_DIR}/cert/ca.pem" def "OPNEIM_CONFIG" ""${OPENIM_ROOT}"/config" + +# OpenIM Web +def "OPENIM_WEB_DIST_PATH" "/app/dist" +def "OPENIM_WEB_PPRT" "11001" + # TODO 注意: 一般的配置都可以使用 def 函数来定义,如果是包含特殊字符,比如说: # TODO readonly MSG_DESTRUCT_TIME=${MSG_DESTRUCT_TIME:-'0 2 * * *'} # TODO 使用 readonly 来定义合适,负责无法正常解析, 并且 yaml 模板需要加 "" 来包裹 diff --git a/tools/component/component_test.go b/tools/component/component_test.go new file mode 100644 index 000000000..9db3ef60e --- /dev/null +++ b/tools/component/component_test.go @@ -0,0 +1,41 @@ +// 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 ( + "testing" + + "github.com/OpenIMSDK/Open-IM-Server/pkg/common/config" + "github.com/stretchr/testify/assert" +) + +func TestCheckMysql(t *testing.T) { + err := mockInitCfg() + assert.NoError(t, err, "Initialization should not produce errors") + + err = checkMysql() + if err != nil { + // You might expect an error if MySQL isn't running locally with the mock credentials. + t.Logf("Expected error due to mock configuration: %v", err) + } +} + +// Mock for initCfg for testing purpose +func mockInitCfg() error { + config.Config.Mysql.Username = "root" + config.Config.Mysql.Password = "openIM123" + config.Config.Mysql.Address = []string{"127.0.0.1:13306"} + return nil +} diff --git a/tools/web/README.md b/tools/web/README.md new file mode 100644 index 000000000..532375b63 --- /dev/null +++ b/tools/web/README.md @@ -0,0 +1,64 @@ +# OpenIM Web Service + +- [OpenIM Web Service](#openim-web-service) + - [Overview](#overview) + - [User](#user) + - [Docker Deployment](#docker-deployment) + - [Build the Docker Image](#build-the-docker-image) + - [Run the Docker Container](#run-the-docker-container) + - [Configuration](#configuration) + - [Contributions](#contributions) + + +OpenIM Web Service is a lightweight containerized service built with Go. The service serves static files and allows customization via environment variables. + +## Overview + +- Built using Go. +- Deployed as a Docker container. +- Serves static files from a directory which can be set via an environment variable. +- The default port for the service is `20001`, but it can be customized using an environment variable. + +## User + +example: + +```bash +# ./web -h +Usage of ./web: + -distPath string + Path to the distribution (default "/app/dist") + -port string + Port to run the server on (default "20001") +``` + +## Docker Deployment + +### Build the Docker Image + +Even though we've implemented automation, it's to make the developer experience easier: + +To build the Docker image for OpenIM Web Service: + +``` +docker build -t openim-web . +``` + +### Run the Docker Container + +To run the service: + +``` +docker run -e DIST_PATH=/app/dist -e PORT=20001 -p 20001:20001 openim-web +``` + +## Configuration + +You can configure the OpenIM Web Service using the following environment variables: + +- **DIST_PATH**: The path to the directory containing the static files. Default: `/app/dist`. +- **PORT**: The port on which the service listens. Default: `11001`. + +## Contributions + +We welcome contributions from the community. If you find any bugs or have feature suggestions, please create an issue or send a pull request. \ No newline at end of file diff --git a/tools/web/go.mod b/tools/web/go.mod new file mode 100644 index 000000000..2a6790a6f --- /dev/null +++ b/tools/web/go.mod @@ -0,0 +1,5 @@ +module github.com/OpenIMSDK/Open-IM-Server/tools/web + +go 1.18 + +require gopkg.in/yaml.v2 v2.4.0 diff --git a/tools/web/go.sum b/tools/web/go.sum new file mode 100644 index 000000000..dd0bc19f1 --- /dev/null +++ b/tools/web/go.sum @@ -0,0 +1,4 @@ +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/tools/web/web.go b/tools/web/web.go new file mode 100644 index 000000000..08f2ec297 --- /dev/null +++ b/tools/web/web.go @@ -0,0 +1,44 @@ +package main + +import ( + "flag" + "log" + "net/http" + "os" +) + +var ( + distPathFlag string + portFlag string +) + +func init() { + flag.StringVar(&distPathFlag, "distPath", "/app/dist", "Path to the distribution") + flag.StringVar(&portFlag, "port", "11001", "Port to run the server on") +} + +func main() { + flag.Parse() + + distPath := getConfigValue("DIST_PATH", distPathFlag, "/app/dist") + fs := http.FileServer(http.Dir(distPath)) + http.Handle("/", fs) + + port := getConfigValue("PORT", portFlag, "11001") + log.Printf("Server listening on port %s in %s...", port, distPath) + err := http.ListenAndServe(":"+port, nil) + if err != nil { + log.Fatal(err) + } +} + +func getConfigValue(envKey, flagValue, fallback string) string { + envVal := os.Getenv(envKey) + if envVal != "" { + return envVal + } + if flagValue != "" { + return flagValue + } + return fallback +} diff --git a/tools/web/web_test.go b/tools/web/web_test.go new file mode 100644 index 000000000..6d19deb77 --- /dev/null +++ b/tools/web/web_test.go @@ -0,0 +1,57 @@ +package main + +import ( + "os" + "testing" +) + +func TestGetConfigValue(t *testing.T) { + tests := []struct { + name string + envKey string + envValue string + flagValue string + fallback string + wantResult string + }{ + { + name: "environment variable set", + envKey: "TEST_KEY", + envValue: "envValue", + flagValue: "", + fallback: "default", + wantResult: "envValue", + }, + { + name: "flag set and environment variable not set", + envKey: "TEST_KEY", + envValue: "", + flagValue: "flagValue", + fallback: "default", + wantResult: "flagValue", + }, + { + name: "nothing set, use fallback", + envKey: "TEST_KEY", + envValue: "", + flagValue: "", + fallback: "default", + wantResult: "default", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.envValue != "" { + os.Setenv(tt.envKey, tt.envValue) + defer os.Unsetenv(tt.envKey) + } + + got := getConfigValue(tt.envKey, tt.flagValue, tt.fallback) + + if got != tt.wantResult { + t.Errorf("getConfigValue(%s, %s, %s) = %s; want %s", tt.envKey, tt.flagValue, tt.fallback, got, tt.wantResult) + } + }) + } +} \ No newline at end of file