Compare commits

...

70 Commits

Author SHA1 Message Date
eball
1aa3def59d olaresd: add node pressure status 2025-08-21 18:59:25 +08:00
eball
aa34dc4412 authelia: add priority class to auth frontend (#1723) 2025-08-19 16:02:26 +08:00
aby913
54155edbbf ci(files): paste task refactor (#1722)
ci: paste task
2025-08-19 00:57:06 +08:00
eball
a776efa62e fix: bump hami core version (#1721) 2025-08-19 00:56:42 +08:00
Calvin W.
ada4d129f6 docs: fix format issues and add notes for domain (#1720) 2025-08-18 21:52:47 +08:00
dkeven
dfb7c5bcc4 feat(cli): add option to skip collecting logs from kube-apiserver (#1719) 2025-08-18 21:46:51 +08:00
Peng Peng
a5b9696d16 feat(docs): update storage requirement (#1717)
feat: update storage requirement
2025-08-16 18:49:29 +08:00
wiy
1870859034 feat(system-frontend): fix system-frontend some bugs (#1715)
* feat(user-service): add /alluser/namespaces api

* feat(system-frontend): release system-frontend new version

---------

Co-authored-by: yyh <24493052+yongheng2016@users.noreply.github.com>
2025-08-16 01:22:23 +08:00
hysyeah
25854d1b14 ks,l4,bfl: remove unused code and vendor dir (#1714) 2025-08-16 01:21:34 +08:00
aby913
cfb4bf93be ci: cloud preview and download, code trimming (#1712)
* ci: cloud preview and download, code trimming

* ci: remove unused drives

* style: remove old watcher and external_watcher

---------

Co-authored-by: lovehunter9 <wangrx07@aliyun.com>
2025-08-16 01:20:55 +08:00
wiy
1571bd82d9 feat(vault-server): update vault support org (#1713) 2025-08-15 00:37:01 +08:00
hysyeah
324456b653 app-service, authelia: fix myapps app sort and authelia ttlcache panic bug (#1711) 2025-08-15 00:36:30 +08:00
Sai
b64e2bd19e feat:Improve the speed of market processing applications (#1710)
Improve the speed of market processing applications
2025-08-15 00:36:07 +08:00
lovehunter9
b49b59e07c fix: cloud move delete and fix a bug because of mkdir for copy and upload (#1708) 2025-08-14 01:00:09 +08:00
dkeven
5dcb0ee7e9 fix(cli): skip failed & deleting users when upgrading (#1705) 2025-08-14 00:59:39 +08:00
dkeven
37b9afe7d5 fix(manifest): add missing condition for sharedlib vol in files (#1704) 2025-08-14 00:59:00 +08:00
Calvin W.
9219fca0ad docs: update custom domain binding for apps (#1706) 2025-08-13 21:31:01 +08:00
wiy
9dd72f2c42 feat(system-frontend): update system-frontend new version (#1702) 2025-08-13 00:13:15 +08:00
hysyeah
9227d9f04e authelia,lldap: group operation api and event publish (#1701)
* authelia,lldap: group operation api and event publish

* fix: add env for os.groups
2025-08-13 00:12:33 +08:00
aby913
41e701b929 ci(files): fix sync rename and copy, cloud copy and integration (#1700) 2025-08-13 00:11:26 +08:00
aby913
7503eb7f42 ci(files): rename, create file and copy with rclone (#1698)
* ci(files): rename, create file and copy with rclone

* feat: sync rename, batch copy & move, copy/move

---------

Co-authored-by: lovehunter9 <wangrx07@aliyun.com>
2025-08-12 00:31:03 +08:00
wiy
0b84f278af feat(system-frontend): update system-frontend and wizard new version (#1697) 2025-08-12 00:30:38 +08:00
hysyeah
62cec2de53 fix: remove values for redis (#1696) 2025-08-12 00:30:07 +08:00
dkeven
ad183f05ce chore: get rid of unused values & ops related to ks redis (#1695) 2025-08-12 00:29:28 +08:00
CobraSoftware
8dea896a28 feat(testing‑mode): allow installation on unsupported OS + ignore build artifacts (#1673)
This commit included updated code to add a
developer mode allowing installation on an
unsupported os. Some of the code was made
by Chatgpt.

Co-authored-by: Cobra Software <crane-tiny-parcel@duck.com>
2025-08-11 11:32:40 +08:00
dependabot[bot]
b62a264c38 chore(deps): bump dompurify and mermaid in /docs (#1694)
Bumps [dompurify](https://github.com/cure53/DOMPurify) to 3.2.6 and updates ancestor dependency [mermaid](https://github.com/mermaid-js/mermaid). These dependencies need to be updated together.


Updates `dompurify` from 3.1.6 to 3.2.6
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/3.1.6...3.2.6)

Updates `mermaid` from 10.9.3 to 11.9.0
- [Release notes](https://github.com/mermaid-js/mermaid/releases)
- [Commits](https://github.com/mermaid-js/mermaid/compare/v10.9.3...mermaid@11.9.0)

---
updated-dependencies:
- dependency-name: dompurify
  dependency-version: 3.2.6
  dependency-type: indirect
- dependency-name: mermaid
  dependency-version: 11.9.0
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-09 15:07:47 +08:00
hysyeah
a030b047b4 app-service, l4, bfl: support creator cli (#1693) 2025-08-09 00:22:29 +08:00
eball
86083ce63c authelia: send the cookie of an ephemeral user to subdomain (#1692) 2025-08-09 00:22:07 +08:00
dkeven
ab0ba8fde6 feat(cli): add commands to manage users (#1691) 2025-08-08 21:27:21 +08:00
hysyeah
a6c44cf29e app-service, cli: queued request; remove ks redis (#1690)
* app-service, cli: queued request; remove ks redis

* fix: omit redis deploy

* fix: rm redis secret from ks-apiserver
2025-08-08 01:48:31 +08:00
Calvin W.
dda43a49ae docs: fix link on dochome and remove dev badge (#1689) 2025-08-07 12:20:06 +08:00
lovehunter9
cad4c09cd4 feat: seahub init and old username migration (#1688) 2025-08-07 01:30:48 +08:00
Sai
0a39b03fbb fix: update check condition for failed task in chart repo (#1686)
update check condition for failed task
2025-08-06 20:44:21 +08:00
dependabot[bot]
b1c525d0dc chore(deps): bump github.com/gofiber/fiber/v2 from 2.52.5 to 2.52.9 in /daemon (#1684)
chore(deps): bump github.com/gofiber/fiber/v2 in /daemon

Bumps [github.com/gofiber/fiber/v2](https://github.com/gofiber/fiber) from 2.52.5 to 2.52.9.
- [Release notes](https://github.com/gofiber/fiber/releases)
- [Commits](https://github.com/gofiber/fiber/compare/v2.52.5...v2.52.9)

---
updated-dependencies:
- dependency-name: github.com/gofiber/fiber/v2
  dependency-version: 2.52.9
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-06 20:43:49 +08:00
Calvin W.
2b45ef7bcf docs: expose other installation methods (#1685)
* docs: expose other installation methods

* fix case in manifest
2025-08-06 14:59:05 +08:00
aby913
060d57a2b9 ci: integrate rclone, seahub replace (#1683)
* feat: files replace seahub part 1

* ci(files): integrate rclone, seahub part replace

---------

Co-authored-by: lovehunter9 <wangrx07@aliyun.com>
2025-08-06 11:02:31 +08:00
hysyeah
496ed1c6fb fix: sync users group error (#1682) 2025-08-05 21:40:17 +08:00
dkeven
4c912e1485 chore(cli): remove any call to ulimit that has no effect (#1680) 2025-08-05 21:26:38 +08:00
dkeven
c313982033 fix(ci): copy built script to correct path (#1681) 2025-08-05 17:18:14 +08:00
dkeven
83e070761c fix(cli): create symlink to sysconf if none exists (#1679) 2025-08-05 15:44:42 +08:00
salt
beed97f704 feat: refactor based on fileparam (#1675)
Co-authored-by: ubuntu <you@example.com>
2025-08-05 11:06:40 +08:00
berg
116fa8df72 system-frontend: update system frontend version to v1.3.126 (#1678)
feat: update system frontend version to v1.3.126
2025-08-05 11:06:17 +08:00
hysyeah
7fa1f093ed app-service: set concurrent downloads to 1 (#1677)
app-service: set concurent downloads to 1
2025-08-04 21:57:15 +08:00
Sai
65ca835684 fix: entrance url matching error in market (#1676)
fix URL matching error
2025-08-04 15:53:29 +08:00
eball
fd4b0e3a92 daemon: fix checking if ip changed bug (#1674)
* daemon: fix checking if ip changed bug

* fix: check master ip bug
2025-08-04 13:31:08 +08:00
berg
1ec300360c system frontend: update version to v1.3.124 (#1672)
* feat: update system frontend to v1.3.124

* feat(dashboard): update hami webui request to user-service

---------

Co-authored-by: qq815776412 <815776412@qq.com>
2025-08-02 00:00:55 +08:00
hysyeah
fc0781580e fix: v2 upgrade and cs chart render (#1671)
fix: v2 upgrade; cs chart render
2025-08-01 20:40:15 +08:00
Calvin W.
88bff41d83 docs: add a note for custom domain hosting (#1669) 2025-08-01 20:29:28 +08:00
dkeven
7d758befde fix(cli): lift the constraint on version level in upgrade (#1666) 2025-08-01 19:48:14 +08:00
eball
a8e074bec1 daemon: fix recreate download-cert job bug (#1668) 2025-08-01 16:05:51 +08:00
Sai
12302696c8 fix: nats message concurrent (#1667)
fix nats message concurrent
2025-08-01 14:33:14 +08:00
eball
3edef07ebe authelia: ignore error when app policies reloading (#1665) 2025-08-01 00:47:14 +08:00
wiy
170492b733 feat(system-frontend): release new version to fix some bugs (#1664) 2025-07-31 23:08:08 +08:00
hysyeah
b5f2d4baa5 fix: use new files api to delete app cache dir (#1659)
* fix: use new files api to delete app cache dir

* fix: user create pending;entrance state update missing
2025-07-31 23:04:31 +08:00
dkeven
358dc9a957 fix(cli): installation on MacOS using minikube (#1661) 2025-07-31 22:37:06 +08:00
dkeven
c6cf22f3a2 fix(ci): correct path to release joincluster script (#1660) 2025-07-31 22:35:17 +08:00
eball
cd6d502f4a cli: add a command of olares-cli to show full system info (#1658)
* feat: add show all info

* fix: add a wsl info

* Update main.go
2025-07-31 22:32:40 +08:00
Calvin W.
0b05f33f52 docs: update Market doc with latest enhancements (#1662) 2025-07-31 22:28:37 +08:00
Calvin W.
995f03ea7b docs: hide sync and cloud storage feature for optimization (#1663) 2025-07-31 22:28:22 +08:00
aby913
c4ed5c6d15 fix(backup): check wise installed (#1656) 2025-07-31 16:50:25 +08:00
hysyeah
992a2bd343 app-service: fix downloading limit;user create failed bug (#1657) 2025-07-31 16:49:52 +08:00
wiy
f8205f0b7a wizard,login: fix compare olares version error (#1655) 2025-07-31 14:13:16 +08:00
Sai
121a8009ea fix: nats upversion to 1.44.0 for market (#1654)
nats upversion to 1.44.0
2025-07-31 13:58:21 +08:00
dkeven
d6dff36e35 feat(upgrade): lift constraint in version.hint (#1653) 2025-07-31 12:40:48 +08:00
berg
8913e10e7b feat(system-frontend): update system-frontend new version (#1652)
* feat(system-frontend): update system-frontend new version

* feat(user-service): add cookie provider

---------

Co-authored-by: qq815776412 <815776412@qq.com>
2025-07-31 00:12:18 +08:00
dkeven
faa655f928 feat(cli): fallback target to current cli version for both release line (#1651) 2025-07-31 00:10:01 +08:00
Sai
df6d9c440d fix: market render chart for multiple admin (#1650)
fix multiple admin
2025-07-31 00:07:44 +08:00
eball
1f2fd0619f ci: bump version to 1.12.1 (#1648) 2025-07-30 21:30:35 +08:00
Calvin W.
9dbb52dedc docs: batch update images and outdated info for Settings (#1649)
* docs: batch update images and outdated info for Settings

* fix links
2025-07-30 21:20:29 +08:00
Calvin W.
a08c8129ab docs: update dashboard doc for 1.12 (#1618)
* docs: update dashboard doc for 1.12

* update latest UI screenshots for dashboards
2025-07-30 21:20:17 +08:00
192 changed files with 3065 additions and 2224 deletions

View File

@@ -59,7 +59,7 @@ jobs:
steps:
- id: generate
run: |
v=1.12.0-$(echo $RANDOM$RANDOM)
v=1.12.1-$(echo $RANDOM$RANDOM)
echo "version=$v" >> "$GITHUB_OUTPUT"
upload-cli:

View File

@@ -17,7 +17,7 @@ jobs:
steps:
- id: generate
run: |
v=1.12.0-$(date +"%Y%m%d")
v=1.12.1-$(date +"%Y%m%d")
echo "version=$v" >> "$GITHUB_OUTPUT"
release-cli:

View File

@@ -157,7 +157,7 @@ jobs:
cp .dist/install-wizard/install.sh build/base-package
cp build/base-package/install.sh build/base-package/publicInstaller.sh
cp build/base-package/install.sh build/base-package/publicInstaller.latest
cp .dist/install-wizard/install.ps1 build/insbase-packagetaller
cp .dist/install-wizard/install.ps1 build/base-package
cp build/base-package/install.ps1 build/base-package/publicInstaller.latest.ps1
cp .dist/install-wizard/joincluster.sh build/base-package
@@ -174,7 +174,7 @@ jobs:
build/base-package/publicInstaller.latest.ps1
build/base-package/install.ps1
build/base-package/publicAddnode.sh
build/instbase-packagealler/joincluster.sh
build/base-package/joincluster.sh
build/base-package/version.hint
build/base-package/publicRestoreInstaller.sh
prerelease: true

3
.gitignore vendored
View File

@@ -36,4 +36,5 @@ daemon/bin
docs/.vitepress/dist/
docs/.vitepress/cache/
node_modules
.idea/
.idea/
cli/olares-cli*

View File

@@ -333,7 +333,7 @@ spec:
- name: PGDB
value: user_space_{{ .Values.bfl.username }}_cloud_drive_integration
- name: system-frontend-init
image: beclab/system-frontend:v1.3.116
image: beclab/system-frontend:v1.4.6
imagePullPolicy: IfNotPresent
command:
- /bin/sh
@@ -455,7 +455,7 @@ spec:
- name: NATS_SUBJECT_VAULT
value: os.vault.{{ .Values.bfl.username}}
- name: user-service
image: beclab/user-service:v0.0.41
image: beclab/user-service:v0.0.44
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3000
@@ -1211,6 +1211,8 @@ spec:
uri: /api/account/all
- name: POST
uri: /api/cookie/retrieve
- name: POST
uri: /api/cookie
status:
state: active
---

View File

@@ -44,5 +44,3 @@ os:
dashboard:
appKey: '${ks[0]}'
appSecret: test
kubesphere:
redis_password: ""

View File

@@ -29,7 +29,7 @@ spec:
containers:
- name: wizard
image: beclab/wizard:v1.3.111
image: beclab/wizard:v1.4.3
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80

View File

@@ -34,5 +34,3 @@ os:
appstore:
appKey: '${ks[0]}'
appSecret: test
kubesphere:
redis_password: ""

View File

@@ -10,7 +10,7 @@ function command_exists() {
if [[ x"$VERSION" == x"" ]]; then
if [[ "$LOCAL_RELEASE" == "1" ]]; then
ts=$(date +%Y%m%d%H%M%S)
export VERSION="1.12.0-$ts"
export VERSION="1.12.1-$ts"
echo "will build and use a local release of Olares with version: $VERSION"
echo ""
else
@@ -20,7 +20,7 @@ fi
if [[ "x${VERSION}" == "x" || "x${VERSION:3}" == "xVERSION__" ]]; then
echo "error: Olares version is unspecified, please set the VERSION env var and rerun this script."
echo "for example: VERSION=1.12.0-20241124 bash $0"
echo "for example: VERSION=1.12.1-20241124 bash $0"
exit 1
fi

View File

@@ -149,7 +149,7 @@ export VERSION="#__VERSION__"
if [[ "x${VERSION}" == "x" || "x${VERSION:3}" == "xVERSION__" ]]; then
echo "error: Olares version is unspecified, please set the VERSION env var and rerun this script."
echo "for example: VERSION=1.12.0-20241124 bash $0"
echo "for example: VERSION=1.12.1-20241124 bash $0"
exit 1
fi

View File

@@ -1,2 +1,2 @@
upgrade:
minVersion: 1.12.0-1
minVersion: 1.12.0-0

View File

@@ -1,5 +1,3 @@
kubesphere:
redis_password: ""
backup:
bucket: "${BACKUP_CLUSTER_BUCKET}"
key_prefix: "${BACKUP_KEY_PREFIX}"

View File

@@ -5,16 +5,19 @@ import (
"compress/gzip"
"fmt"
"io"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"log"
"net"
"os"
"os/exec"
"path/filepath"
ctrl "sigs.k8s.io/controller-runtime"
"strings"
"time"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/core/util"
"github.com/spf13/cobra"
)
@@ -30,14 +33,57 @@ type LogCollectOptions struct {
Components []string
// Whether to ignore errors from kubectl commands
IgnoreKubeErrors bool
// Skip retrieving logs from kube-apiserver
SkipKubeAPISserver bool
}
var servicesToCollectLogs = []string{"k3s", "containerd", "olaresd", "kubelet", "juicefs", "redis", "minio", "etcd", "NetworkManager"}
// setSkipIfK8sNotReachable checks if the Kubernetes API server port is reachable
// and automatically sets skip-kube-apiserver to true if not reachable
func setSkipIfK8sNotReachable(options *LogCollectOptions) {
// if the env is not set explicitly by user
// fallback to k3s config path as it's a non-standard path
if os.Getenv(clientcmd.RecommendedConfigPathEnvVar) == "" {
os.Setenv(clientcmd.RecommendedConfigPathEnvVar, "/etc/rancher/k3s/k3s.yaml")
}
config, err := ctrl.GetConfig()
if err != nil {
fmt.Printf("Warning: failed to get kubeconfig: %v\n", err)
fmt.Println("Automatically setting skip-kube-apiserver option")
options.SkipKubeAPISserver = true
return
}
url, _, err := rest.DefaultServerUrlFor(config)
if err != nil {
fmt.Printf("Warning: failed to parse server url in kubeconfig: %v\n", err)
fmt.Println("Automatically setting skip-kube-apiserver option")
options.SkipKubeAPISserver = true
return
}
timeout := config.Timeout
if timeout == 0 {
timeout = 5 * time.Second
}
conn, err := net.DialTimeout("tcp", url.Host, timeout)
if err != nil {
fmt.Printf("Warning: Kubernetes API server at %s is not reachable: %v\n", config.Host, err)
fmt.Println("Automatically setting skip-kube-apiserver option")
options.SkipKubeAPISserver = true
return
}
conn.Close()
}
func collectLogs(options *LogCollectOptions) error {
if os.Getuid() != 0 {
return fmt.Errorf("os: please run as root")
}
if !options.SkipKubeAPISserver {
setSkipIfK8sNotReachable(options)
}
if err := os.MkdirAll(options.OutputDir, 0755); err != nil {
return fmt.Errorf("failed to create output directory: %v", err)
}
@@ -296,13 +342,21 @@ func collectKubernetesLogs(tw *tar.Writer, options *LogCollectOptions) error {
}
}
if options.SkipKubeAPISserver {
return nil
}
if _, err := util.GetCommand("kubectl"); err != nil {
fmt.Printf("warning: kubectl not found, skipping collecting cluster info from kube-apiserver\n")
return nil
}
cmd := exec.Command("kubectl", "get", "pods", "--all-namespaces", "-o", "wide")
output, err := tryKubectlCommand(cmd, "get pods", options)
var cmd *exec.Cmd
var output []byte
var err error
cmd = exec.Command("kubectl", "get", "pods", "--all-namespaces", "-o", "wide")
output, err = tryKubectlCommand(cmd, "get pods", options)
if err != nil && !options.IgnoreKubeErrors {
return err
}
@@ -517,7 +571,8 @@ func NewCmdLogs() *cobra.Command {
cmd.Flags().IntVar(&options.MaxLines, "max-lines", options.MaxLines, "Maximum number of lines to collect per log source, to limit the log file size")
cmd.Flags().StringVar(&options.OutputDir, "output-dir", options.OutputDir, "Directory to store collected logs, will be created if not existing")
cmd.Flags().StringSliceVar(&options.Components, "components", nil, "Specific components (systemd service) to collect logs from (comma-separated). If empty, collects from all Olares-related components that can be found")
cmd.Flags().BoolVar(&options.IgnoreKubeErrors, "ignore-kube-errors", options.IgnoreKubeErrors, "Continue collecting logs even if kubectl commands fail, e.g., when kube-apiserver is not reachable")
cmd.Flags().BoolVar(&options.IgnoreKubeErrors, "ignore-kube-errors", options.IgnoreKubeErrors, "Continue collecting logs even if kubectl commands fail")
cmd.Flags().BoolVar(&options.SkipKubeAPISserver, "skip-kube-apiserver", options.SkipKubeAPISserver, "Skip retrieving logs from kube-apiserver, it's automatically set if apiserver is not reachable. To tolerate other cases, set the ignore-kube-errors")
return cmd
}

View File

@@ -49,7 +49,7 @@ func NewCmdRelease() *cobra.Command {
}
if version == "" {
version = fmt.Sprintf("1.12.0-%s", time.Now().Format("20060102150405"))
version = fmt.Sprintf("1.12.1-%s", time.Now().Format("20060102150405"))
fmt.Printf("--version unspecified, using: %s\n", version)
time.Sleep(1 * time.Second)
}

View File

@@ -1,15 +1,10 @@
package os
import (
"os/exec"
"github.com/spf13/cobra"
)
func NewOSCommands() []*cobra.Command {
_ = exec.Command("/bin/bash", "-c", "ulimit -u 65535").Run()
_ = exec.Command("/bin/bash", "-c", "ulimit -n 65535").Run()
return []*cobra.Command{
NewCmdPrecheck(),
NewCmdRootDownload(),

View File

@@ -3,6 +3,7 @@ package osinfo
import (
"fmt"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/core/connector"
"github.com/spf13/cobra"
)
@@ -14,6 +15,7 @@ func NewCmdInfo() *cobra.Command {
Long: "help for printing info",
}
infoCmd.AddCommand(showInfoCommand())
infoCmd.AddCommand(showAllCommand())
return infoCmd
}
@@ -37,3 +39,17 @@ OS_INFO=%s
}
return cmd
}
func showAllCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "showall",
Short: "Print full os information",
Long: "help for printing os info",
Run: func(cmd *cobra.Command, args []string) {
arg := common.NewArgument()
arg.SystemInfo.Print()
},
}
return cmd
}

View File

@@ -5,6 +5,7 @@ import (
"github.com/beclab/Olares/cli/cmd/ctl/node"
"github.com/beclab/Olares/cli/cmd/ctl/os"
"github.com/beclab/Olares/cli/cmd/ctl/osinfo"
"github.com/beclab/Olares/cli/cmd/ctl/user"
"github.com/beclab/Olares/cli/version"
"github.com/spf13/cobra"
)
@@ -31,6 +32,7 @@ func NewDefaultCommand() *cobra.Command {
cmds.AddCommand(os.NewOSCommands()...)
cmds.AddCommand(node.NewNodeCommand())
cmds.AddCommand(gpu.NewCmdGpu())
cmds.AddCommand(user.NewUserCommand())
return cmds
}

192
cli/cmd/ctl/user/create.go Normal file
View File

@@ -0,0 +1,192 @@
package user
import (
"bytetrade.io/web3os/app-service/api/sys.bytetrade.io/v1alpha1"
"context"
"fmt"
"github.com/beclab/Olares/cli/pkg/utils"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/validation"
"log"
"strings"
iamv1alpha2 "github.com/beclab/api/iam/v1alpha2"
"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type createUserOptions struct {
name string
displayName string
domain string
role string
resourceLimit
password string
description string
kubeConfig string
}
func NewCmdCreateUser() *cobra.Command {
o := &createUserOptions{}
cmd := &cobra.Command{
Use: "create {name}",
Aliases: []string{"add", "new"},
Short: "create a new user",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
o.name = args[0]
if err := o.Validate(); err != nil {
log.Fatal(err)
}
if err := o.Run(); err != nil {
log.Fatal(err)
}
},
}
o.AddFlags(cmd)
return cmd
}
func (o *createUserOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVar(&o.displayName, "display-name", "", "display name (optional)")
cmd.Flags().StringVar(&o.domain, "domain", "", "domain (optional, defaults to the Olares system's domain)")
cmd.Flags().StringVarP(&o.role, "role", "r", "normal", "owner role (optional, one of owner, admin, normal)")
cmd.Flags().StringVarP(&o.memoryLimit, "memory-limit", "m", defaultMemoryLimit, "memory limit (optional)")
cmd.Flags().StringVarP(&o.cpuLimit, "cpu-limit", "c", defaultCPULimit, "cpu limit (optional)")
cmd.Flags().StringVarP(&o.password, "password", "p", "", "initial password (optional)")
cmd.Flags().StringVar(&o.description, "description", "", "user description (optional)")
cmd.Flags().StringVar(&o.kubeConfig, "kubeconfig", "", "path to kubeconfig file (optional)")
}
func (o *createUserOptions) Validate() error {
if o.name == "" {
return fmt.Errorf("name is required")
}
if errs := validation.IsDNS1123Subdomain(o.name); len(errs) > 0 {
return fmt.Errorf("invalid name: %s", strings.Join(errs, ","))
}
if o.domain != "" {
if errs := validation.IsDNS1123Subdomain(o.domain); len(errs) > 0 {
return fmt.Errorf("invalid domain: %s", strings.Join(errs, ","))
}
if len(strings.Split(o.domain, ".")) < 2 {
return errors.New("invalid domain: should be a domain with at least two segments separated by dots")
}
for _, label := range strings.Split(o.domain, ".") {
if errs := validation.IsDNS1123Label(label); len(errs) > 0 {
return fmt.Errorf("invalid domain: %s", strings.Join(errs, ","))
}
}
}
if o.role != "" {
if o.role != roleOwner && o.role != roleAdmin && o.role != roleNormal {
return fmt.Errorf("invalid role: should be one of owner, admin, or normal")
}
}
if err := validateResourceLimit(o.resourceLimit); err != nil {
return err
}
return nil
}
func (o *createUserOptions) Run() error {
ctx := context.Background()
userClient, err := newUserClientFromKubeConfig(o.kubeConfig)
if err != nil {
return err
}
if o.memoryLimit == "" {
o.memoryLimit = defaultMemoryLimit
}
if o.cpuLimit == "" {
o.cpuLimit = defaultCPULimit
}
if o.domain == "" {
var system v1alpha1.Terminus
err := userClient.Get(ctx, types.NamespacedName{Name: systemObjectName}, &system)
if err != nil {
return fmt.Errorf("failed to get system info: %v", err)
}
o.domain = system.Spec.Settings[systemObjectDomainKey]
}
var userList iamv1alpha2.UserList
err = userClient.List(ctx, &userList)
if err != nil {
return fmt.Errorf("failed to list users to set creator: %w", err)
}
var owners []iamv1alpha2.User
for _, user := range userList.Items {
if role, ok := user.Annotations[annotationKeyRole]; ok && role == roleOwner {
owners = append(owners, user)
}
}
if len(owners) > 1 {
fmt.Printf("Warning: multiple owners found\n")
}
if o.role == roleOwner && len(owners) > 0 {
return fmt.Errorf("an owner '%s' already exists", owners[0].Name)
}
if o.password == "" {
password, passwordEncrypted, err := utils.GenerateEncryptedPassword(8)
if err != nil {
return fmt.Errorf("error generating password: %v", err)
}
log.Println("generated initial password:", password)
o.password = passwordEncrypted
} else {
o.password = utils.MD5(o.password + "@Olares2025")
}
olaresName := fmt.Sprintf("%s@%s", o.name, o.domain)
user := &iamv1alpha2.User{
TypeMeta: metav1.TypeMeta{
APIVersion: iamv1alpha2.SchemeGroupVersion.String(),
Kind: iamv1alpha2.ResourceKindUser,
},
ObjectMeta: metav1.ObjectMeta{
Name: o.name,
Annotations: map[string]string{
"bytetrade.io/creator": creatorCLI,
annotationKeyRole: o.role,
"bytetrade.io/is-ephemeral": "true",
"bytetrade.io/terminus-name": olaresName,
"bytetrade.io/launcher-auth-policy": "two_factor",
"bytetrade.io/launcher-access-level": "1",
annotationKeyMemoryLimit: o.memoryLimit,
annotationKeyCPULimit: o.cpuLimit,
"iam.kubesphere.io/sync-to-lldap": "true",
"iam.kubesphere.io/synced-to-lldap": "false",
},
},
Spec: iamv1alpha2.UserSpec{
DisplayName: o.displayName,
Email: olaresName,
InitialPassword: o.password,
Description: o.description,
},
}
if o.role == roleOwner || o.role == roleAdmin {
user.Spec.Groups = append(user.Spec.Groups, lldapGroupAdmin)
}
err = userClient.Create(ctx, user)
if err != nil {
return fmt.Errorf("failed to create user: %w", err)
}
fmt.Printf("User '%s' created successfully\n", o.name)
return nil
}

View File

@@ -0,0 +1,81 @@
package user
import (
"context"
"fmt"
iamv1alpha2 "github.com/beclab/api/iam/v1alpha2"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
"log"
)
type deleteUserOptions struct {
name string
kubeConfig string
}
func NewCmdDeleteUser() *cobra.Command {
o := &deleteUserOptions{}
cmd := &cobra.Command{
Use: "delete {name}",
Short: "delete an existing user",
Aliases: []string{"d", "del", "rm", "remove"},
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
o.name = args[0]
if err := o.Validate(); err != nil {
log.Fatal(err)
}
if err := o.Run(); err != nil {
log.Fatal(err)
}
},
}
o.AddFlags(cmd)
return cmd
}
func (o *deleteUserOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVar(&o.kubeConfig, "kubeconfig", "", "path to kubeconfig file")
}
func (o *deleteUserOptions) Validate() error {
if o.name == "" {
return fmt.Errorf("name is required")
}
return nil
}
func (o *deleteUserOptions) Run() error {
ctx := context.Background()
userClient, err := newUserClientFromKubeConfig(o.kubeConfig)
if err != nil {
return err
}
var user iamv1alpha2.User
err = userClient.Get(ctx, types.NamespacedName{Name: o.name}, &user)
if err != nil {
if errors.IsNotFound(err) {
return fmt.Errorf("user '%s' not found", o.name)
}
return fmt.Errorf("failed to get user: %w", err)
}
if user.Status.State == "Creating" {
return fmt.Errorf("user '%s' is under creation", o.name)
}
if role, ok := user.Annotations[annotationKeyRole]; ok && role == roleOwner {
return fmt.Errorf("cannot delete user '%s' with role '%s' ", o.name, role)
}
err = userClient.Delete(ctx, &user)
if err != nil && !errors.IsNotFound(err) {
return fmt.Errorf("failed to delete user: %w", err)
}
fmt.Printf("User '%s' deleted successfully\n", o.name)
return nil
}

84
cli/cmd/ctl/user/get.go Normal file
View File

@@ -0,0 +1,84 @@
package user
import (
"context"
"encoding/json"
"fmt"
iamv1alpha2 "github.com/beclab/api/iam/v1alpha2"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
"log"
)
type getUserOptions struct {
name string
kubeConfig string
output string
noHeaders bool
}
func NewCmdGetUser() *cobra.Command {
o := &getUserOptions{}
cmd := &cobra.Command{
Use: "get {name}",
Short: "get user details",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
o.name = args[0]
if err := o.Validate(); err != nil {
log.Fatal(err)
}
if err := o.Run(); err != nil {
log.Fatal(err)
}
},
}
o.AddFlags(cmd)
return cmd
}
func (o *getUserOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVar(&o.kubeConfig, "kubeconfig", "", "path to kubeconfig file")
cmd.Flags().StringVarP(&o.output, "output", "o", "table", "output format (table, json)")
cmd.Flags().BoolVar(&o.noHeaders, "no-headers", false, "disable headers")
}
func (o *getUserOptions) Validate() error {
if o.name == "" {
return fmt.Errorf("name is required")
}
return nil
}
func (o *getUserOptions) Run() error {
ctx := context.Background()
userClient, err := newUserClientFromKubeConfig(o.kubeConfig)
if err != nil {
return err
}
var user iamv1alpha2.User
err = userClient.Get(ctx, types.NamespacedName{Name: o.name}, &user)
if err != nil {
if errors.IsNotFound(err) {
return fmt.Errorf("user '%s' not found", o.name)
}
return fmt.Errorf("failed to get user: %w", err)
}
info := convertUserObjectToUserInfo(user)
if o.output == "json" {
jsonOutput, _ := json.MarshalIndent(info, "", " ")
fmt.Println(string(jsonOutput))
} else {
if !o.noHeaders {
printUserTableHeaders()
}
printUserTableRow(info)
}
return nil
}

182
cli/cmd/ctl/user/list.go Normal file
View File

@@ -0,0 +1,182 @@
package user
import (
"context"
"encoding/json"
"fmt"
iamv1alpha2 "github.com/beclab/api/iam/v1alpha2"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/util/sets"
"log"
"slices"
"sort"
"strings"
)
var sortFuncs = map[string]func(users []iamv1alpha2.User, i, j int) bool{
"name": func(users []iamv1alpha2.User, i, j int) bool {
return strings.Compare(users[i].Name, users[j].Name) == -1
},
"role": func(users []iamv1alpha2.User, i, j int) bool {
return strings.Compare(users[i].Annotations[annotationKeyRole], users[j].Annotations[annotationKeyRole]) == -1
},
"create-time": func(users []iamv1alpha2.User, i, j int) bool {
return users[i].CreationTimestamp.Before(&users[j].CreationTimestamp)
},
"memory": func(users []iamv1alpha2.User, i, j int) bool {
iMemoryStr, ok := users[i].Annotations[annotationKeyMemoryLimit]
if !ok || iMemoryStr == "" {
return false
}
jMemoryStr, ok := users[j].Annotations[annotationKeyMemoryLimit]
if !ok || jMemoryStr == "" {
return true
}
iMemory, err := resource.ParseQuantity(iMemoryStr)
if err != nil {
fmt.Printf("Warning: invalid memory limit '%s' is set on user '%s'\n", iMemoryStr, users[i].Name)
return false
}
jMemory, err := resource.ParseQuantity(jMemoryStr)
if err != nil {
fmt.Printf("Warning: invalid memory limit '%s' is set on user '%s'\n", jMemoryStr, users[j].Name)
return true
}
return iMemory.Cmp(jMemory) == -1
},
"cpu": func(users []iamv1alpha2.User, i, j int) bool {
iCPUStr, ok := users[i].Annotations[annotationKeyCPULimit]
if !ok || iCPUStr == "" {
return false
}
jCPUStr, ok := users[j].Annotations[annotationKeyCPULimit]
if !ok || jCPUStr == "" {
return true
}
iCPU, err := resource.ParseQuantity(iCPUStr)
if err != nil {
fmt.Printf("Warning: invalid cpu limit '%s' is set on user '%s'", iCPUStr, users[i].Name)
return false
}
jCPU, err := resource.ParseQuantity(jCPUStr)
if err != nil {
fmt.Printf("Warning: invalid cpu limit '%s' is set on user '%s'", jCPUStr, users[j].Name)
return true
}
return iCPU.Cmp(jCPU) == -1
},
}
var sortAliases = map[string]sets.Set[string]{
"name": sets.New[string]("n", "N", "Name"),
"role": sets.New[string]("r", "R", "Role"),
"create-time": sets.New[string]("creation", "created", "created-at", "createdat", "createtime"),
"cpu": sets.New[string]("c", "C", "CPU"),
"memory": sets.New[string]("m", "M", "Memory"),
}
func getSortFunc(sortBy string) func(users []iamv1alpha2.User, i, j int) bool {
if f, ok := sortFuncs[sortBy]; ok {
return f
}
for origin, sortAlias := range sortAliases {
if sortAlias.Has(sortBy) {
return sortFuncs[origin]
}
}
return nil
}
type listUsersOptions struct {
kubeConfig string
output string
noHeaders bool
sortBys []string
reverse bool
}
func NewCmdListUsers() *cobra.Command {
o := &listUsersOptions{}
cmd := &cobra.Command{
Use: "list",
Aliases: []string{"ls", "l"},
Short: "list all users",
Run: func(cmd *cobra.Command, args []string) {
if err := o.Validate(); err != nil {
log.Fatal(err)
}
if err := o.Run(); err != nil {
log.Fatal(err)
}
},
}
o.AddFlags(cmd)
return cmd
}
func (o *listUsersOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVar(&o.kubeConfig, "kubeconfig", "", "path to kubeconfig file")
cmd.Flags().StringVarP(&o.output, "output", "o", "table", "output format (table, json)")
cmd.Flags().BoolVar(&o.noHeaders, "no-headers", false, "disable headers")
cmd.Flags().StringSliceVar(&o.sortBys, "sort", []string{}, "sort output order by (name, role, create-time, memory, cpu)")
cmd.Flags().BoolVarP(&o.reverse, "reverse", "r", false, "reverse order")
}
func (o *listUsersOptions) Validate() error {
for _, sortBy := range o.sortBys {
f := getSortFunc(sortBy)
if f == nil {
return fmt.Errorf("unknown sort option: %s", sortBy)
}
}
return nil
}
func (o *listUsersOptions) Run() error {
ctx := context.Background()
userClient, err := newUserClientFromKubeConfig(o.kubeConfig)
if err != nil {
return err
}
var userList iamv1alpha2.UserList
err = userClient.List(ctx, &userList)
if err != nil {
return fmt.Errorf("failed to list users: %w", err)
}
for _, sortBy := range o.sortBys {
sort.SliceStable(userList.Items, func(i, j int) bool {
f := getSortFunc(sortBy)
if f == nil {
log.Fatalf("unkown sort option: %s", sortBy)
}
return f(userList.Items, i, j)
})
}
if o.reverse {
slices.Reverse(userList.Items)
}
users := make([]userInfo, 0, len(userList.Items))
for _, user := range userList.Items {
users = append(users, convertUserObjectToUserInfo(user))
}
if o.output == "json" {
jsonOutput, _ := json.MarshalIndent(users, "", " ")
fmt.Println(string(jsonOutput))
} else {
if !o.noHeaders {
printUserTableHeaders()
}
for _, user := range users {
printUserTableRow(user)
}
}
return nil
}

16
cli/cmd/ctl/user/root.go Normal file
View File

@@ -0,0 +1,16 @@
package user
import "github.com/spf13/cobra"
func NewUserCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "user",
Short: "user management operations",
}
cmd.AddCommand(NewCmdCreateUser())
cmd.AddCommand(NewCmdDeleteUser())
cmd.AddCommand(NewCmdListUsers())
cmd.AddCommand(NewCmdGetUser())
// cmd.AddCommand(NewCmdUpdateUserLimits())
return cmd
}

43
cli/cmd/ctl/user/types.go Normal file
View File

@@ -0,0 +1,43 @@
package user
type resourceLimit struct {
memoryLimit string
cpuLimit string
}
type userInfo struct {
UID string `json:"uid"`
Name string `json:"name"`
DisplayName string `json:"display_name"`
Description string `json:"description"`
Email string `json:"email"`
State string `json:"state"`
LastLoginTime *int64 `json:"last_login_time"`
CreationTimestamp int64 `json:"creation_timestamp"`
Avatar string `json:"avatar"`
TerminusName string `json:"terminusName"`
WizardComplete bool `json:"wizard_complete"`
Roles []string `json:"roles"`
MemoryLimit string `json:"memory_limit"`
CpuLimit string `json:"cpu_limit"`
}
var (
annotationKeyRole = "bytetrade.io/owner-role"
annotationKeyMemoryLimit = "bytetrade.io/user-memory-limit"
annotationKeyCPULimit = "bytetrade.io/user-cpu-limit"
roleOwner = "owner"
roleAdmin = "admin"
roleNormal = "normal"
creatorCLI = "cli"
lldapGroupAdmin = "lldap_admin"
defaultMemoryLimit = "3G"
defaultCPULimit = "1"
systemObjectName = "terminus"
systemObjectDomainKey = "domainName"
)

View File

@@ -0,0 +1,97 @@
package user
import (
"context"
"fmt"
iamv1alpha2 "github.com/beclab/api/iam/v1alpha2"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
"log"
)
type updateUserLimitsOptions struct {
name string
resourceLimit
kubeConfig string
}
func NewCmdUpdateUserLimits() *cobra.Command {
o := &updateUserLimitsOptions{}
cmd := &cobra.Command{
Use: "update-limits {name}",
Aliases: []string{"update-limit", "ulimit", "ulimits"},
Short: "update user resource limits",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
o.name = args[0]
if err := o.Validate(); err != nil {
log.Fatal(err)
}
if err := o.Run(); err != nil {
log.Fatal(err)
}
},
}
o.AddFlags(cmd)
return cmd
}
func (o *updateUserLimitsOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVarP(&o.memoryLimit, "memory-limit", "m", "", "memory limit")
cmd.Flags().StringVarP(&o.cpuLimit, "cpu-limit", "c", "", "cpu limit")
cmd.Flags().StringVar(&o.kubeConfig, "kubeconfig", "", "path to kubeconfig file")
}
func (o *updateUserLimitsOptions) Validate() error {
if o.name == "" {
return fmt.Errorf("user name is required")
}
if o.memoryLimit == "" && o.cpuLimit == "" {
return fmt.Errorf("one of memory limit or cpu limit is required")
}
if err := validateResourceLimit(o.resourceLimit); err != nil {
return err
}
return nil
}
func (o *updateUserLimitsOptions) Run() error {
ctx := context.Background()
userClient, err := newUserClientFromKubeConfig(o.kubeConfig)
if err != nil {
return err
}
var user iamv1alpha2.User
err = userClient.Get(ctx, types.NamespacedName{Name: o.name}, &user)
if err != nil {
if errors.IsNotFound(err) {
return fmt.Errorf("user '%s' not found", o.name)
}
return fmt.Errorf("failed to get user: %w", err)
}
if user.Annotations == nil {
user.Annotations = make(map[string]string)
}
if o.memoryLimit != "" {
user.Annotations[annotationKeyMemoryLimit] = o.memoryLimit
}
if o.cpuLimit != "" {
user.Annotations[annotationKeyCPULimit] = o.cpuLimit
}
err = userClient.Update(ctx, &user)
if err != nil {
return fmt.Errorf("failed to update user: %w", err)
}
fmt.Printf("User '%s' resource limits updated successfully\n", o.name)
return nil
}

120
cli/cmd/ctl/user/utils.go Normal file
View File

@@ -0,0 +1,120 @@
package user
import (
"bytetrade.io/web3os/app-service/api/sys.bytetrade.io/v1alpha1"
"fmt"
iamv1alpha2 "github.com/beclab/api/iam/v1alpha2"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/tools/clientcmd"
"os"
"sigs.k8s.io/controller-runtime/pkg/client"
"strconv"
"time"
)
func newUserClientFromKubeConfig(kubeconfig string) (client.Client, error) {
if kubeconfig == "" {
kubeconfig = os.Getenv("KUBECONFIG")
if kubeconfig == "" {
kubeconfig = clientcmd.RecommendedHomeFile
}
}
config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
if err != nil {
return nil, fmt.Errorf("failed to get kubeconfig: %w", err)
}
scheme := runtime.NewScheme()
if err := iamv1alpha2.AddToScheme(scheme); err != nil {
return nil, fmt.Errorf("failed to add user scheme: %w", err)
}
if err := v1alpha1.AddToScheme(scheme); err != nil {
return nil, fmt.Errorf("failed to add system scheme: %w", err)
}
userClient, err := client.New(config, client.Options{Scheme: scheme})
if err != nil {
return nil, fmt.Errorf("failed to create user client: %w", err)
}
return userClient, nil
}
func validateResourceLimit(limit resourceLimit) error {
if limit.memoryLimit != "" {
memLimit, err := resource.ParseQuantity(limit.memoryLimit)
if err != nil {
return fmt.Errorf("invalid memory limit: %v", err)
}
minMemLimit, _ := resource.ParseQuantity(defaultMemoryLimit)
if memLimit.Cmp(minMemLimit) < 0 {
return fmt.Errorf("invalid memory limit: %s is less than minimum required: %s", memLimit.String(), minMemLimit.String())
}
}
if limit.cpuLimit != "" {
cpuLimit, err := resource.ParseQuantity(limit.cpuLimit)
if err != nil {
return fmt.Errorf("invalid cpu limit: %v", err)
}
minCPULimit, _ := resource.ParseQuantity(defaultCPULimit)
if cpuLimit.Cmp(minCPULimit) < 0 {
return fmt.Errorf("invalid cpu limit: %s is less than minimum required: %s", cpuLimit.String(), minCPULimit.String())
}
}
return nil
}
func convertUserObjectToUserInfo(user iamv1alpha2.User) userInfo {
info := userInfo{
UID: string(user.UID),
Name: user.Name,
DisplayName: user.Spec.DisplayName,
Description: user.Spec.Description,
Email: user.Spec.Email,
State: string(user.Status.State),
CreationTimestamp: user.CreationTimestamp.Unix(),
}
if user.Annotations != nil {
if role, ok := user.Annotations[annotationKeyRole]; ok {
info.Roles = []string{role}
}
if terminusName, ok := user.Annotations["bytetrade.io/terminus-name"]; ok {
info.TerminusName = terminusName
}
if avatar, ok := user.Annotations["bytetrade.io/avatar"]; ok {
info.Avatar = avatar
}
if memoryLimit, ok := user.Annotations[annotationKeyMemoryLimit]; ok {
info.MemoryLimit = memoryLimit
}
if cpuLimit, ok := user.Annotations[annotationKeyCPULimit]; ok {
info.CpuLimit = cpuLimit
}
}
if user.Status.LastLoginTime != nil {
lastLogin := user.Status.LastLoginTime.Unix()
info.LastLoginTime = &lastLogin
}
return info
}
func printUserTableHeaders() {
fmt.Printf("%-20s %-10s %-10s %-30s %-10s %-10s %-10s\n", "NAME", "ROLE", "STATE", "CREATE TIME", "ACTIVATED", "MEMORY", "CPU")
}
func printUserTableRow(info userInfo) {
role := roleNormal
if len(info.Roles) > 0 {
role = info.Roles[0]
}
fmt.Printf("%-20s %-10s %-10s %-30s %-10s %-10s %-10s\n",
info.Name, role, info.State, time.Unix(info.CreationTimestamp, 0).Format(time.RFC3339), strconv.FormatBool(info.WizardComplete), info.MemoryLimit, info.CpuLimit)
}

View File

@@ -1,16 +1,12 @@
package main
import (
"os"
"os/exec"
"github.com/beclab/Olares/cli/cmd/ctl"
"os"
)
func main() {
cmd := ctl.NewDefaultCommand()
_ = exec.Command("/bin/bash", "-c", "ulimit -u 65535").Run()
_ = exec.Command("/bin/bash", "-c", "ulimit -n 65535").Run()
if err := cmd.Execute(); err != nil {
// fmt.Println(err)

View File

@@ -5,62 +5,67 @@ go 1.24.0
toolchain go1.24.3
replace (
bytetrade.io/web3os/app-service => github.com/beclab/app-service v0.2.33
bytetrade.io/web3os/backups-sdk => github.com/Above-Os/backups-sdk v0.1.17
github.com/containers/image/v5 => github.com/containers/image/v5 v5.21.1
github.com/containers/ocicrypt => github.com/containers/ocicrypt v1.1.10
github.com/containers/storage => github.com/containers/storage v1.40.0
github.com/estesp/manifest-tool/v2 => github.com/estesp/manifest-tool/v2 v2.0.3
github.com/opencontainers/image-spec => github.com/opencontainers/image-spec v1.1.0
)
require (
bytetrade.io/web3os/app-service v0.0.0-00010101000000-000000000000
bytetrade.io/web3os/backups-sdk v0.0.0-00010101000000-000000000000
github.com/Masterminds/semver/v3 v3.3.0
github.com/Masterminds/semver/v3 v3.4.0
github.com/PaesslerAG/jsonpath v0.1.1
github.com/alecthomas/assert/v2 v2.11.0
github.com/beclab/api v0.0.0-20250805111305-08be8f53edf0
github.com/cavaliergopher/grab/v3 v3.0.1
github.com/containerd/containerd v1.7.27
github.com/containerd/containerd v1.7.28
github.com/decentralized-identity/web5-go v0.25.0
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0
github.com/distribution/reference v0.6.0
github.com/dominodatalab/os-release v0.0.0-20190522011736-bcdb4a3e3c2f
github.com/go-playground/validator/v10 v10.22.0
github.com/go-playground/validator/v10 v10.27.0
github.com/google/uuid v1.6.0
github.com/jmoiron/sqlx v1.4.0
github.com/joho/godotenv v1.5.1
github.com/libp2p/go-netroute v0.2.2
github.com/lithammer/dedent v1.1.0
github.com/mattn/go-sqlite3 v1.14.22
github.com/mitchellh/mapstructure v1.5.0
github.com/mattn/go-sqlite3 v1.14.30
github.com/mitchellh/mapstructure v1.4.1
github.com/modood/table v0.0.0-20220527013332-8d47e76dad33
github.com/mr-tron/base58 v1.2.0
github.com/multiformats/go-varint v0.0.7
github.com/pelletier/go-toml v1.9.5
github.com/pkg/errors v0.9.1
github.com/pkg/sftp v1.13.6
github.com/pkg/sftp v1.10.1
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
github.com/schollz/progressbar/v3 v3.17.1
github.com/shirou/gopsutil/v4 v4.25.2
github.com/schollz/progressbar/v3 v3.18.0
github.com/shirou/gopsutil/v4 v4.25.7
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c
github.com/spf13/cobra v1.9.1
github.com/spf13/pflag v1.0.6
github.com/stretchr/testify v1.10.0
github.com/syndtr/goleveldb v1.0.0
go.uber.org/zap v1.27.0
golang.org/x/crypto v0.39.0
golang.org/x/term v0.32.0
golang.org/x/text v0.26.0
golang.org/x/crypto v0.40.0
golang.org/x/sys v0.34.0
golang.org/x/term v0.33.0
golang.org/x/text v0.27.0
gopkg.in/yaml.v2 v2.4.0
helm.sh/helm/v3 v3.18.4
k8s.io/api v0.33.2
k8s.io/apimachinery v0.33.2
k8s.io/cli-runtime v0.33.2
k8s.io/client-go v0.33.2
k8s.io/kubectl v0.33.2
k8s.io/api v0.33.3
k8s.io/apimachinery v0.33.3
k8s.io/cli-runtime v0.33.3
k8s.io/client-go v0.33.3
k8s.io/klog/v2 v2.130.1
k8s.io/kubectl v0.33.3
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738
sigs.k8s.io/controller-runtime v0.21.0
sigs.k8s.io/kustomize/kyaml v0.19.0
sigs.k8s.io/yaml v1.4.0
sigs.k8s.io/kustomize/kyaml v0.20.1
sigs.k8s.io/yaml v1.5.0
)
require (
@@ -80,7 +85,6 @@ require (
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/bshuster-repo/logrus-logstash-hook v1.0.2 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/chai2010/gettext-go v1.0.2 // indirect
github.com/containerd/cgroups v1.1.0 // indirect
@@ -101,15 +105,19 @@ require (
github.com/evanphx/json-patch/v5 v5.9.11 // indirect
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
github.com/fatih/camelcase v1.0.0 // indirect
github.com/fatih/color v1.15.0 // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
github.com/go-errors/errors v1.4.2 // indirect
github.com/go-gorp/gorp/v3 v3.1.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-resty/resty/v2 v2.16.5 // indirect
@@ -129,15 +137,19 @@ require (
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hexops/gotextdiff v1.0.3 // indirect
github.com/huandu/xstrings v1.5.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jonboulle/clockwork v0.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/kr/fs v0.1.0 // indirect
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/lib/pq v1.10.9 // indirect
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
@@ -147,7 +159,7 @@ require (
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/moby/locker v1.0.1 // indirect
github.com/moby/spdystream v0.5.0 // indirect
github.com/moby/sys/mountinfo v0.7.1 // indirect
github.com/moby/sys/mountinfo v0.6.2 // indirect
github.com/moby/sys/sequential v0.5.0 // indirect
github.com/moby/sys/signal v0.7.0 // indirect
github.com/moby/sys/user v0.3.0 // indirect
@@ -177,8 +189,8 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartystreets/goconvey v1.8.1 // indirect
github.com/spf13/cast v1.7.0 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/tklauser/go-sysconf v0.3.15 // indirect
github.com/tklauser/numcpus v0.10.0 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
@@ -191,21 +203,25 @@ require (
go.opentelemetry.io/otel v1.33.0 // indirect
go.opentelemetry.io/otel/metric v1.33.0 // indirect
go.opentelemetry.io/otel/trace v1.33.0 // indirect
golang.org/x/net v0.40.0 // indirect
golang.org/x/oauth2 v0.28.0 // indirect
golang.org/x/sync v0.15.0 // indirect
golang.org/x/time v0.9.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
go.yaml.in/yaml/v3 v3.0.3 // indirect
golang.org/x/net v0.42.0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/sync v0.16.0 // indirect
golang.org/x/time v0.12.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 // indirect
google.golang.org/grpc v1.68.1 // indirect
google.golang.org/protobuf v1.36.5 // indirect
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/apiextensions-apiserver v0.33.2 // indirect
k8s.io/apiserver v0.33.2 // indirect
k8s.io/component-base v0.33.2 // indirect
k8s.io/component-helpers v0.33.2 // indirect
k8s.io/component-base v0.33.3 // indirect
k8s.io/component-helpers v0.33.3 // indirect
k8s.io/cri-api v0.27.1 // indirect
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect
oras.land/oras-go/v2 v2.6.0 // indirect
@@ -214,19 +230,3 @@ require (
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect
)
require (
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/kr/fs v0.1.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/spf13/pflag v1.0.6
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/sys v0.33.0
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/klog/v2 v2.130.1
)

View File

@@ -20,8 +20,8 @@ github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0=
github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM=
@@ -43,13 +43,16 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/beclab/api v0.0.0-20250805111305-08be8f53edf0 h1:U8AFy37epib5ya5By0gHAWVRT+BetExFkmGTjkhZCoY=
github.com/beclab/api v0.0.0-20250805111305-08be8f53edf0/go.mod h1:1tq7ut9hrjgYWTh6UTth0xPRa7Ags0VJvUmbr4GuJuM=
github.com/beclab/app-service v0.2.33 h1:fsv9sTL7guTdU8z8sO5KIxxd1N5K+Rp4zORRebs+wmI=
github.com/beclab/app-service v0.2.33/go.mod h1:Gpp5e2XPU/nHufT7ZBsRMZrYxpFbI6R4AEiKine+RhI=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70=
github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
github.com/bshuster-repo/logrus-logstash-hook v1.0.2 h1:JYRWo+QGnQdedgshosug9hxpPYTB9oJ1ZZD3fY31alU=
github.com/bshuster-repo/logrus-logstash-hook v1.0.2/go.mod h1:HgYntJprnHSPaF9VPPPLP1L5S1vMWxRfa1J+vzDrDTw=
github.com/cavaliergopher/grab/v3 v3.0.1 h1:4z7TkBfmPjmLAAmkkAZNX/6QJ1nNFdv3SdIHXju0Fr4=
github.com/cavaliergopher/grab/v3 v3.0.1/go.mod h1:1U/KNnD+Ft6JJiYoYBAimKH2XrYptb8Kl3DFGmsjpq4=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
@@ -65,8 +68,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
github.com/containerd/containerd v1.7.27 h1:yFyEyojddO3MIGVER2xJLWoCIn+Up4GaHFquP7hsFII=
github.com/containerd/containerd v1.7.27/go.mod h1:xZmPnl75Vc+BLGt4MIfu6bp+fy03gdHAn9bz+FreFR0=
github.com/containerd/containerd v1.7.28 h1:Nsgm1AtcmEh4AHAJ4gGlNSaKgXiNccU270Dnf81FQ3c=
github.com/containerd/containerd v1.7.28/go.mod h1:azUkWcOvHrWvaiUjSQH0fjzuHIwSPg1WL5PshGP4Szs=
github.com/containerd/containerd/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVMyTRdsD2bS0=
github.com/containerd/containerd/api v1.8.0/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc=
github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII=
@@ -86,6 +89,7 @@ github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3H
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
@@ -96,10 +100,10 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decentralized-identity/web5-go v0.25.0 h1:7QcWuIXHybscmoQ6eoEcDGdbQSPqHIJ4WAo7FBbntIE=
github.com/decentralized-identity/web5-go v0.25.0/go.mod h1:fzRcApHJZmekJXwjdbG8tYSFxdyZjyjUEmfh92mdhwY=
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8=
github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/distribution/distribution/v3 v3.0.0 h1:q4R8wemdRQDClzoNNStftB2ZAfqOiN6UX90KJc4HjyM=
@@ -130,8 +134,8 @@ github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc=
github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8=
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/foxcpp/go-mockdns v1.1.0 h1:jI0rD8M0wuYAxL7r/ynTrCQQq0BVqfB99Vgk7DlmewI=
@@ -143,8 +147,8 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs=
@@ -158,10 +162,12 @@ github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
@@ -170,8 +176,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao=
github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4=
github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
github.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptdhTM=
github.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
@@ -254,7 +260,6 @@ github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvH
github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI=
github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
@@ -278,8 +283,11 @@ github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zt
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
@@ -302,16 +310,20 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mattn/go-sqlite3 v1.14.30 h1:bVreufq3EAIG1Quvws73du3/QgdeZ3myglJlrzSYYCY=
github.com/mattn/go-sqlite3 v1.14.30/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM=
github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk=
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
@@ -320,16 +332,16 @@ github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa1
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU=
github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g=
github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78=
github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI=
@@ -357,16 +369,19 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg=
github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw=
github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
github.com/onsi/gomega v1.38.0 h1:c/WX+w8SLAinvuKKQFh77WEucCnPk4j2OTUr7lt7BeY=
github.com/onsi/gomega v1.38.0/go.mod h1:OcXcwId0b9QsE7Y49u+BTrL4IdKOBOKnD6VQNTJEB6o=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
@@ -381,10 +396,11 @@ github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+v
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo=
github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk=
github.com/pkg/sftp v1.10.1 h1:VasscCm72135zRysgrJDKsntdmPN+OuU3+nnHYA9wyc=
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -420,17 +436,16 @@ github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4=
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY=
github.com/schollz/progressbar/v3 v3.17.1 h1:bI1MTaoQO+v5kzklBjYNRQLoVpe0zbyRZNK6DFkVC5U=
github.com/schollz/progressbar/v3 v3.17.1/go.mod h1:RzqpnsPQNjUyIgdglUjRLgD7sVnxN1wpmBMV+UiEbL4=
github.com/schollz/progressbar/v3 v3.18.0 h1:uXdoHABRFmNIjUfte/Ex7WtuyVslrw2wVPQmCN62HpA=
github.com/schollz/progressbar/v3 v3.18.0/go.mod h1:IsO3lpbaGuzh8zIMzgY3+J8l4C8GjO0Y9S69eFvNsec=
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
github.com/shirou/gopsutil/v4 v4.25.2 h1:NMscG3l2CqtWFS86kj3vP7soOczqrQYIEhO/pMvvQkk=
github.com/shirou/gopsutil/v4 v4.25.2/go.mod h1:34gBYJzyqCDT11b6bMHP0XCvWeU3J61XRT7a2EmCRTA=
github.com/shirou/gopsutil/v4 v4.25.7 h1:bNb2JuqKuAu3tRlPv5piSmBZyMfecwQ+t/ILq+1JqVM=
github.com/shirou/gopsutil/v4 v4.25.7/go.mod h1:XV/egmwJtd3ZQjBpJVY5kndsiOO4IRqy9TQnmm6VP7U=
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c h1:aqg5Vm5dwtvL+YgDpBcK1ITf3o96N/K7/wsRXQnUTEs=
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c/go.mod h1:owqhoLW1qZoYLZzLnBw+QkPP9WZnjlSWihhxAJC1+/M=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGByCY=
@@ -450,6 +465,7 @@ github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@@ -459,10 +475,10 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4=
github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4=
github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso=
github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
@@ -476,7 +492,6 @@ github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
@@ -533,13 +548,16 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE=
go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -548,9 +566,8 @@ golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPI
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg=
golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -561,57 +578,44 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc=
golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@@ -621,9 +625,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -659,20 +662,20 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
@@ -682,30 +685,30 @@ helm.sh/helm/v3 v3.18.4 h1:pNhnHM3nAmDrxz6/UC+hfjDY4yeDATQCka2/87hkZXQ=
helm.sh/helm/v3 v3.18.4/go.mod h1:WVnwKARAw01iEdjpEkP7Ii1tT1pTPYfM1HsakFKM3LI=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/api v0.33.2 h1:YgwIS5jKfA+BZg//OQhkJNIfie/kmRsO0BmNaVSimvY=
k8s.io/api v0.33.2/go.mod h1:fhrbphQJSM2cXzCWgqU29xLDuks4mu7ti9vveEnpSXs=
k8s.io/api v0.33.3 h1:SRd5t//hhkI1buzxb288fy2xvjubstenEKL9K51KBI8=
k8s.io/api v0.33.3/go.mod h1:01Y/iLUjNBM3TAvypct7DIj0M0NIZc+PzAHCIo0CYGE=
k8s.io/apiextensions-apiserver v0.33.2 h1:6gnkIbngnaUflR3XwE1mCefN3YS8yTD631JXQhsU6M8=
k8s.io/apiextensions-apiserver v0.33.2/go.mod h1:IvVanieYsEHJImTKXGP6XCOjTwv2LUMos0YWc9O+QP8=
k8s.io/apimachinery v0.33.2 h1:IHFVhqg59mb8PJWTLi8m1mAoepkUNYmptHsV+Z1m5jY=
k8s.io/apimachinery v0.33.2/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
k8s.io/apimachinery v0.33.3 h1:4ZSrmNa0c/ZpZJhAgRdcsFcZOw1PQU1bALVQ0B3I5LA=
k8s.io/apimachinery v0.33.3/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
k8s.io/apiserver v0.33.2 h1:KGTRbxn2wJagJowo29kKBp4TchpO1DRO3g+dB/KOJN4=
k8s.io/apiserver v0.33.2/go.mod h1:9qday04wEAMLPWWo9AwqCZSiIn3OYSZacDyu/AcoM/M=
k8s.io/cli-runtime v0.33.2 h1:koNYQKSDdq5AExa/RDudXMhhtFasEg48KLS2KSAU74Y=
k8s.io/cli-runtime v0.33.2/go.mod h1:gnhsAWpovqf1Zj5YRRBBU7PFsRc6NkEkwYNQE+mXL88=
k8s.io/client-go v0.33.2 h1:z8CIcc0P581x/J1ZYf4CNzRKxRvQAwoAolYPbtQes+E=
k8s.io/client-go v0.33.2/go.mod h1:9mCgT4wROvL948w6f6ArJNb7yQd7QsvqavDeZHvNmHo=
k8s.io/component-base v0.33.2 h1:sCCsn9s/dG3ZrQTX/Us0/Sx2R0G5kwa0wbZFYoVp/+0=
k8s.io/component-base v0.33.2/go.mod h1:/41uw9wKzuelhN+u+/C59ixxf4tYQKW7p32ddkYNe2k=
k8s.io/component-helpers v0.33.2 h1:AjCtYzst11NV8ensxV/2LEEXRwctqS7Bs44bje9Qcnw=
k8s.io/component-helpers v0.33.2/go.mod h1:PsPpiCk74n8pGWp1d6kjK/iSKBTyQfIacv02BNkMenU=
k8s.io/cli-runtime v0.33.3 h1:Dgy4vPjNIu8LMJBSvs8W0LcdV0PX/8aGG1DA1W8lklA=
k8s.io/cli-runtime v0.33.3/go.mod h1:yklhLklD4vLS8HNGgC9wGiuHWze4g7x6XQZ+8edsKEo=
k8s.io/client-go v0.33.3 h1:M5AfDnKfYmVJif92ngN532gFqakcGi6RvaOF16efrpA=
k8s.io/client-go v0.33.3/go.mod h1:luqKBQggEf3shbxHY4uVENAxrDISLOarxpTKMiUuujg=
k8s.io/component-base v0.33.3 h1:mlAuyJqyPlKZM7FyaoM/LcunZaaY353RXiOd2+B5tGA=
k8s.io/component-base v0.33.3/go.mod h1:ktBVsBzkI3imDuxYXmVxZ2zxJnYTZ4HAsVj9iF09qp4=
k8s.io/component-helpers v0.33.3 h1:fjWVORSQfI0WKzPeIFSju/gMD9sybwXBJ7oPbqQu6eM=
k8s.io/component-helpers v0.33.3/go.mod h1:7iwv+Y9Guw6X4RrnNQOyQlXcvJrVjPveHVqUA5dm31c=
k8s.io/cri-api v0.27.1 h1:KWO+U8MfI9drXB/P4oU9VchaWYOlwDglJZVHWMpTT3Q=
k8s.io/cri-api v0.27.1/go.mod h1:+Ts/AVYbIo04S86XbTD73UPp/DkTiYxtsFeOFEu32L0=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8=
k8s.io/kubectl v0.33.2 h1:7XKZ6DYCklu5MZQzJe+CkCjoGZwD1wWl7t/FxzhMz7Y=
k8s.io/kubectl v0.33.2/go.mod h1:8rC67FB8tVTYraovAGNi/idWIK90z2CHFNMmGJZJ3KI=
k8s.io/kubectl v0.33.3 h1:r/phHvH1iU7gO/l7tTjQk2K01ER7/OAJi8uFHHyWSac=
k8s.io/kubectl v0.33.3/go.mod h1:euj2bG56L6kUGOE/ckZbCoudPwuj4Kud7BR0GzyNiT0=
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
oras.land/oras-go/v2 v2.6.0 h1:X4ELRsiGkrbeox69+9tzTu492FMUu7zJQW6eJU+I2oc=
@@ -716,12 +719,13 @@ sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=
sigs.k8s.io/kustomize/api v0.19.0 h1:F+2HB2mU1MSiR9Hp1NEgoU2q9ItNOaBJl0I4Dlus5SQ=
sigs.k8s.io/kustomize/api v0.19.0/go.mod h1:/BbwnivGVcBh1r+8m3tH1VNxJmHSk1PzP5fkP6lbL1o=
sigs.k8s.io/kustomize/kyaml v0.19.0 h1:RFge5qsO1uHhwJsu3ipV7RNolC7Uozc0jUBC/61XSlA=
sigs.k8s.io/kustomize/kyaml v0.19.0/go.mod h1:FeKD5jEOH+FbZPpqUghBP8mrLjJ3+zD3/rf9NNu1cwY=
sigs.k8s.io/kustomize/kyaml v0.20.1 h1:PCMnA2mrVbRP3NIB6v9kYCAc38uvFLVs8j/CD567A78=
sigs.k8s.io/kustomize/kyaml v0.20.1/go.mod h1:0EmkQHRUsJxY8Ug9Niig1pUMSCGHxQ5RklbpV/Ri6po=
sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc=
sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ=
sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4=

View File

@@ -166,6 +166,15 @@ func (c *ConfigureOSModule) Init() {
Parallel: true,
}
symlinkSysconf := &task.RemoteTask{
Name: "SymlinkSysconf",
Desc: "Create symbolic link to sysconf if non-existing",
Hosts: c.Runtime.GetAllHosts(),
Prepare: &kubernetes.NodeInCluster{Not: true},
Action: new(SymLinkSysconf),
Parallel: true,
}
ConfigureNtpServer := &task.RemoteTask{
Name: "ConfigureNtpServer",
Desc: "configure the ntp server for each node",
@@ -191,6 +200,7 @@ func (c *ConfigureOSModule) Init() {
initOS,
GenerateScript,
ExecScript,
symlinkSysconf,
ConfigureNtpServer,
configureSwap,
}

View File

@@ -371,6 +371,35 @@ func (n *NodeExecScript) Execute(runtime connector.Runtime) error {
return nil
}
type SymLinkSysconf struct {
common.KubeAction
}
func (a *SymLinkSysconf) Execute(runtime connector.Runtime) error {
sysconfPath := "/etc/sysctl.conf"
sysconfSymLinkPath := "/etc/sysctl.d/99-sysctl.conf"
linkExists, err := runtime.GetRunner().FileExist(sysconfSymLinkPath)
if err != nil {
return fmt.Errorf("failed to check if %s exists", sysconfSymLinkPath)
}
if linkExists {
return nil
}
sysconfDir := filepath.Dir(sysconfSymLinkPath)
dirExists, err := runtime.GetRunner().DirExist(sysconfDir)
if err != nil {
return fmt.Errorf("failed to check if %s exists", sysconfDir)
}
if !dirExists {
err = runtime.GetRunner().MkDir(sysconfDir)
if err != nil {
return err
}
}
_, err = runtime.GetRunner().SudoCmd(fmt.Sprintf("ln -s %s %s", sysconfPath, sysconfSymLinkPath), true, false)
return err
}
var (
etcdFiles = []string{
"/usr/local/bin/etcd",

View File

@@ -152,9 +152,6 @@ update-alternatives --set arptables /usr/sbin/arptables-legacy >/dev/null 2>&1 |
update-alternatives --set ebtables /usr/sbin/ebtables-legacy >/dev/null 2>&1 || true
for i in $(systemctl list-unit-files --no-legend --no-pager -l | grep --color=never -o .*.slice | grep kubepod); do sudo systemctl stop $i; done
ulimit -u 65535
ulimit -n 65535
`)))
func GenerateHosts(runtime connector.ModuleRuntime, kubeConf *common.KubeConf) []string {

View File

@@ -75,7 +75,22 @@ func (t *SystemSupportCheck) Name() string {
}
func (t *SystemSupportCheck) Check(runtime connector.Runtime) error {
return runtime.GetSystemInfo().IsSupport()
err := runtime.GetSystemInfo().IsSupport()
if err == nil {
return nil
}
// Interactive warning instead of outright failure
fmt.Printf("%v Use at your own risk, would you like to continue? (Y/N): ", err)
reader, err := utils.GetBufIOReaderOfTerminalInput()
if err != nil {
return fmt.Errorf("could not read terminal input: %v", err)
}
input, _ := reader.ReadString('\n')
input = strings.TrimSpace(input)
if !strings.HasPrefix("yes", strings.ToLower(input)) {
return err
}
return nil
}
type RequiredPortsCheck struct{}

View File

@@ -333,8 +333,10 @@ var TerminusGlobalEnvs = map[string]interface{}{
"FRP_LIST_URL": "https://terminus-frp.snowinning.com",
"TAILSCALE_CONTROLPLANE_URL": "https://controlplane.snowinning.com",
"OLARES_ROOT_DIR": "/olares",
ENV_DOWNLOAD_CDN_URL: cc.DownloadUrl,
ENV_MARKET_PROVIDER: "appstore-server-prod.bttcdn.com",
// the default value used by kubeadm
"COREDNS_SVC": "10.96.0.10",
ENV_DOWNLOAD_CDN_URL: cc.DownloadUrl,
ENV_MARKET_PROVIDER: "appstore-server-prod.bttcdn.com",
}
const (

View File

@@ -302,6 +302,8 @@ func (s *SystemInfo) Print() {
fmt.Printf("fs info, fs: %s, zfsmount: %s\n", s.FsInfo.Type, s.FsInfo.DefaultZfsPrefixName)
fmt.Printf("mem info, total: %s, free: %s\n", util.FormatBytes(int64(s.MemoryInfo.Total)), util.FormatBytes(int64(s.MemoryInfo.Free)))
fmt.Printf("cgroup info, cpu: %d, mem: %d\n", s.CgroupInfo.CpuEnabled, s.CgroupInfo.MemoryEnabled)
fmt.Printf("oic: %t\n", s.IsOIC)
fmt.Printf("in wsl: %t\n", s.IsWsl())
}
func GetSystemInfo() *SystemInfo {

View File

@@ -108,22 +108,24 @@ func (t *LoadImages) Execute(runtime connector.Runtime) (reserr error) {
loadParm = "--no-unpack"
}
parsedRef, err := reference.ParseNormalizedNamed(imageRepoTag)
if err != nil {
logger.Warnf("parse image name %s error: %v, skip importing", imageRepoTag, err)
continue
}
if runtime.RemoteHost().GetOs() == common.Darwin {
loadCmd = fmt.Sprintf("%s -p %s ssh --native-ssh=false 'sudo ctr -n k8s.io i import --index-name %s -'", minikubepath, minikubeprofile, parsedRef)
if HasSuffixI(imgFileName, ".tar.gz", ".tgz") {
loadCmd = fmt.Sprintf("gunzip -c %s | %s -p %s image load -", imageFileName, minikubepath, minikubeprofile)
loadCmd = fmt.Sprintf("gunzip -c %s | ", imageFileName) + loadCmd
} else {
loadCmd = fmt.Sprintf("%s -p %s image load %s", minikubepath, minikubeprofile, imageFileName)
loadCmd = fmt.Sprintf("cat %s | ", imageFileName) + loadCmd
}
} else {
switch containerManager {
case "crio":
loadCmd = "ctr" // not implement
case "containerd":
parsedRef, err := reference.ParseNormalizedNamed(imageRepoTag)
if err != nil {
logger.Warnf("parse image name %s error: %v, skip importing", imageRepoTag, err)
continue
}
if HasSuffixI(imgFileName, ".tar.gz", ".tgz") {
loadCmd = fmt.Sprintf("gunzip -c %s | ctr -n k8s.io images import --index-name %s %s -", imageFileName, parsedRef, loadParm)
} else {

View File

@@ -50,7 +50,7 @@ func (t *CreateMiniKubeCluster) Execute(runtime connector.Runtime) error {
}
}
logger.Infof("creating minikube cluster %s ...", t.KubeConf.Arg.MinikubeProfile)
cmd = fmt.Sprintf("%s start -p '%s' --kubernetes-version=v1.22.10 --container-runtime=containerd --network-plugin=cni --cni=calico --cpus='4' --memory='8g' --ports=30180:30180,443:443,80:80", minikube, t.KubeConf.Arg.MinikubeProfile)
cmd = fmt.Sprintf("%s start -p '%s' --kubernetes-version=v1.33.3 --container-runtime=containerd --network-plugin=cni --cni=calico --cpus='4' --memory='8g' --ports=30180:30180,443:443,80:80", minikube, t.KubeConf.Arg.MinikubeProfile)
if _, err := runtime.GetRunner().Cmd(cmd, false, true); err != nil {
return errors.Wrap(err, "failed to create minikube cluster")
}

File diff suppressed because one or more lines are too long

View File

@@ -59,14 +59,7 @@ securityContext: {}
# Kubernetes Version shows in KubeSphere console
# kube_version: "v1.19.4" # ! 这里要替换下
env:
- name: KUBESPHERE_REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: redis-secret
key: auth
tolerations:
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
- key: CriticalAddonsOnly

View File

@@ -32,7 +32,7 @@ spec:
- command:
- ks-apiserver
- --logtostderr=true
image: beclab/ks-apiserver:0.0.21
image: beclab/ks-apiserver:0.0.22
imagePullPolicy: {{ .Values.image.pullPolicy }}
name: ks-apiserver
ports:
@@ -49,10 +49,6 @@ spec:
{{- if .Values.apiserver.extraVolumeMounts }}
{{- toYaml .Values.apiserver.extraVolumeMounts | nindent 8 }}
{{- end }}
env:
{{- if .Values.env }}
{{- toYaml .Values.env | nindent 8 }}
{{- end }}
livenessProbe:
failureThreshold: 8
httpGet:

View File

@@ -58,14 +58,7 @@ securityContext: {}
# Kubernetes Version shows in KubeSphere console
# kube_version: "v1.19.4" # ! 这里要替换下
env:
- name: KUBESPHERE_REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: redis-secret
key: auth
tolerations:
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
- key: CriticalAddonsOnly

View File

@@ -1,23 +0,0 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

View File

@@ -1,15 +0,0 @@
apiVersion: v2
appVersion: 5.0.14
name: redis
description: A Helm chart for redis
version: 0.2.0
kubeVersion: ">=1.17.0-0"
home: https://github.com/kubernetes-csi/external-snapshotter
sources:
- https://github.com/kubesphere/helm-charts
keywords:
- redis
maintainers:
- name: aby913
email: aby913@gmail.com

View File

@@ -1,136 +0,0 @@
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: redis-pvc
namespace: kubesphere-system
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: {{ .Values.persistentVolume.size }}
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: redis
tier: database
version: {{ .Values.version }}
name: redis
namespace: kubesphere-system
spec:
replicas: 1
selector:
matchLabels:
app: redis
tier: database
template:
metadata:
labels:
app: redis
tier: database
version: {{ .Values.version }}
spec:
initContainers:
- name: init
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
command: ['sh', '-c', 'cat /tmp/redis/redis.conf | sed "s/REDIS_PASSWORD/$KUBESPHERE_REDIS_PASSWORD/" > /data/redis.conf']
volumeMounts:
- mountPath: /data
name: redis-pvc
subPath: redis-data
- name: redis-config
mountPath: "/tmp/redis"
readOnly: true
env:
- name: KUBESPHERE_REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: redis-secret
key: auth
containers:
- image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: IfNotPresent
name: redis
args: ["/data/redis.conf"]
volumeMounts:
- mountPath: /data
name: redis-pvc
subPath: redis-data
ports:
- containerPort: 6379
protocol: TCP
resources:
limits:
cpu: 1000m
memory: 1000Mi
requests:
cpu: 20m
memory: 100Mi
volumes:
- name: redis-pvc
persistentVolumeClaim:
claimName: redis-pvc
- name: redis-config
configMap:
name: redis-configmap
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: node-role.kubernetes.io/master
operator: In
values:
- ""
nodeSelector: {}
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
- key: CriticalAddonsOnly
operator: Exists
---
apiVersion: v1
kind: ConfigMap
metadata:
name: redis-configmap
namespace: kubesphere-system
labels:
app: redis
tier: database
version: {{ .Values.version }}
data:
redis.conf: |
requirepass REDIS_PASSWORD
masterauth REDIS_PASSWORD
---
apiVersion: v1
kind: Service
metadata:
labels:
app: redis
tier: database
name: redis
namespace: kubesphere-system
spec:
ports:
- name: redis
port: 6379
protocol: TCP
targetPort: 6379
selector:
app: redis
tier: database
sessionAffinity: None
type: ClusterIP

View File

@@ -1,263 +0,0 @@
## Configure resource requests and limits
## ref: http://kubernetes.io/docs/user-guide/compute-resources/
##
version: redis-4.0
image:
repository: redis
tag: 5.0.14-alpine
pullPolicy: IfNotPresent
## replicas number for each component
replicas: 3
## Kubernetes priorityClass name for the redis-ha-server pod
# priorityClassName: ""
## Custom labels for the redis pod
labels: {}
## Pods Service Account
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
serviceAccount:
## Specifies whether a ServiceAccount should be created
##
create: true
## The name of the ServiceAccount to use.
## If not set and create is true, a name is generated using the redis-ha.fullname template
# name:
## Enables a HA Proxy for better LoadBalancing / Sentinel Master support. Automatically proxies to Redis master.
## Recommend for externally exposed Redis clusters.
## ref: https://cbonte.github.io/haproxy-dconv/1.9/intro.html
haproxy:
enabled: true
# Enable if you want a dedicated port in haproxy for redis-slaves
readOnly:
enabled: false
port: 6380
replicas: 3
image:
repository: haproxy
tag: 2.0.25-alpine
pullPolicy: IfNotPresent
annotations: {}
resources: {}
## Kubernetes priorityClass name for the haproxy pod
# priorityClassName: ""
## Service type for HAProxy
##
service:
type: ClusterIP
loadBalancerIP:
annotations: {}
serviceAccount:
create: true
## Prometheus metric exporter for HAProxy.
##
exporter:
image:
repository: quay.io/prometheus/haproxy-exporter
tag: v0.9.0
enabled: false
port: 9101
init:
resources: {}
timeout:
connect: 10s
server: 360s
client: 360s
securityContext:
runAsUser: 1000
fsGroup: 1000
runAsNonRoot: true
## Role Based Access
## Ref: https://kubernetes.io/docs/admin/authorization/rbac/
##
rbac:
create: true
sysctlImage:
enabled: false
command: []
registry: docker.io
repository: bitnami/minideb
tag: latest
pullPolicy: Always
mountHostSys: false
## Use an alternate scheduler, e.g. "stork".
## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/
##
# schedulerName:
## Redis specific configuration options
redis:
port: 6379
masterGroupName: mymaster
config:
## Additional redis conf options can be added below
## For all available options see http://download.redis.io/redis-stable/redis.conf
min-replicas-to-write: 1
min-replicas-max-lag: 5 # Value in seconds
maxmemory: "0" # Max memory to use for each redis instance. Default is unlimited.
maxmemory-policy: "volatile-lru" # Max memory policy to use for each redis instance. Default is volatile-lru.
# Determines if scheduled RDB backups are created. Default is false.
# Please note that local (on-disk) RDBs will still be created when re-syncing with a new slave. The only way to prevent this is to enable diskless replication.
save: "900 1"
# When enabled, directly sends the RDB over the wire to slaves, without using the disk as intermediate storage. Default is false.
repl-diskless-sync: "yes"
rdbcompression: "yes"
rdbchecksum: "yes"
## Custom redis.conf files used to override default settings. If this file is
## specified then the redis.config above will be ignored.
# customConfig: |-
# Define configuration here
resources: {}
# requests:
# memory: 200Mi
# cpu: 100m
# limits:
# memory: 700Mi
## Sentinel specific configuration options
sentinel:
port: 26379
quorum: 2
config:
## Additional sentinel conf options can be added below. Only options that
## are expressed in the format simialar to 'sentinel xxx mymaster xxx' will
## be properly templated.
## For available options see http://download.redis.io/redis-stable/sentinel.conf
down-after-milliseconds: 10000
## Failover timeout value in milliseconds
failover-timeout: 180000
parallel-syncs: 5
## Custom sentinel.conf files used to override default settings. If this file is
## specified then the sentinel.config above will be ignored.
# customConfig: |-
# Define configuration here
resources: {}
# requests:
# memory: 200Mi
# cpu: 100m
# limits:
# memory: 200Mi
securityContext:
runAsUser: 1000
fsGroup: 1000
runAsNonRoot: true
## Node labels, affinity, and tolerations for pod assignment
## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector
## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#taints-and-tolerations-beta-feature
## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
nodeSelector: {}
tolerations: []
## Whether the Redis server pods should be forced to run on separate nodes.
## This is accomplished by setting their AntiAffinity with requiredDuringSchedulingIgnoredDuringExecution as opposed to preferred.
## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#inter-pod-affinity-and-anti-affinity-beta-feature
##
hardAntiAffinity: true
## Additional affinities to add to the Redis server pods.
##
## Example:
## nodeAffinity:
## preferredDuringSchedulingIgnoredDuringExecution:
## - weight: 50
## preference:
## matchExpressions:
## - key: spot
## operator: NotIn
## values:
## - "true"
##
## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
##
additionalAffinities:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: node-role.kubernetes.io/master
operator: In
values:
- ""
## Override all other affinity settings for the Redis server pods with a string.
affinity: |
# Prometheus exporter specific configuration options
exporter:
enabled: false
image: oliver006/redis_exporter
tag: v0.31.0
pullPolicy: IfNotPresent
# prometheus port & scrape path
port: 9121
scrapePath: /metrics
# cpu/memory resource limits/requests
resources: {}
# Additional args for redis exporter
extraArgs: {}
podDisruptionBudget: {}
# maxUnavailable: 1
# minAvailable: 1
## Configures redis with AUTH (requirepass & masterauth conf params)
auth: true
# redisPassword:
## Use existing secret containing key `authKey` (ignores redisPassword)
existingSecret: redis-secret
## Defines the key holding the redis password in existing secret.
authKey: auth
persistentVolume:
enabled: true
## redis-ha data Persistent Volume Storage Class
## If defined, storageClassName: <storageClass>
## If set to "-", storageClassName: "", which disables dynamic provisioning
## If undefined (the default) or set to null, no storageClassName spec is
## set, choosing the default provisioner. (gp2 on AWS, standard on
## GKE, AWS & OpenStack)
##
accessModes:
- ReadWriteOnce
size: 2Gi
annotations: {}
init:
resources: {}
# To use a hostPath for data, set persistentVolume.enabled to false
# and define hostPath.path.
# Warning: this might overwrite existing folders on the host system!
hostPath:
## path is evaluated as template so placeholders are replaced
# path: "/data/redis"
# if chown is true, an init-container with root permissions is launched to
# change the owner of the hostPath folder to the user defined in the
# security context
chown: true

View File

@@ -39,7 +39,7 @@ func NewDarwinClusterPhase(runtime *common.KubeRuntime, manifestMap manifest.Ins
&kubesphere.DeployMiniKubeModule{},
&kubesphere.DeployModule{Skip: !runtime.Cluster.KubeSphere.Enabled},
&ksplugins.DeployKsPluginsModule{},
&ksplugins.DeployRedisModule{},
//&ksplugins.DeployRedisModule{},
&ksplugins.CreateKubeSphereSecretModule{},
&ksplugins.DeployKsCoreConfigModule{}, // ks-core-config
&ksplugins.CreateMonitorDashboardModule{},
@@ -98,7 +98,7 @@ func NewK3sCreateClusterPhase(runtime *common.KubeRuntime, manifestMap manifest.
&storage.DeployLocalVolumeModule{Skip: skipLocalStorage},
&kubesphere.DeployModule{Skip: !runtime.Cluster.KubeSphere.Enabled}, //
&ksplugins.DeployKsPluginsModule{},
&ksplugins.DeployRedisModule{},
//&ksplugins.DeployRedisModule{},
&ksplugins.CreateKubeSphereSecretModule{},
&ksplugins.DeployKsCoreConfigModule{}, // ks-core-config
&ksplugins.CreateMonitorDashboardModule{},
@@ -161,7 +161,7 @@ func NewCreateClusterPhase(runtime *common.KubeRuntime, manifestMap manifest.Ins
&storage.DeployLocalVolumeModule{Skip: skipLocalStorage},
&kubesphere.DeployModule{Skip: !runtime.Cluster.KubeSphere.Enabled},
&ksplugins.DeployKsPluginsModule{},
&ksplugins.DeployRedisModule{},
//&ksplugins.DeployRedisModule{},
&ksplugins.CreateKubeSphereSecretModule{},
&ksplugins.DeployKsCoreConfigModule{}, // ! ks-core-config
&ksplugins.CreateMonitorDashboardModule{},

View File

@@ -82,10 +82,10 @@ func (u *PrepareAppValues) Execute(runtime connector.Runtime) error {
defer cancel()
ns := fmt.Sprintf("user-space-%s", u.KubeConf.Arg.User.UserName)
redisPassword, err := getRedisPassword(client, runtime)
if err != nil {
return err
}
//redisPassword, err := getRedisPassword(client, runtime)
//if err != nil {
// return err
//}
bfDocUrl, _ := getDocUrl(ctx, runtime)
bflNodeName, err := getBflPod(ctx, ns, client, runtime)
@@ -131,9 +131,9 @@ func (u *PrepareAppValues) Execute(runtime connector.Runtime) error {
"gpu": gpuType,
"fs_type": fsType,
"os": appValues,
"kubesphere": map[string]interface{}{
"redis_password": redisPassword,
},
//"kubesphere": map[string]interface{}{
// "redis_password": redisPassword,
//},
common.HelmValuesKeyTerminusGlobalEnvs: common.TerminusGlobalEnvs,
common.HelmValuesKeyOlaresRootFSPath: storage.OlaresRootDir,
}

View File

@@ -27,27 +27,12 @@ type InstallOsSystem struct {
}
func (t *InstallOsSystem) Execute(runtime connector.Runtime) error {
kubectl, err := util.GetCommand(common.CommandKubectl)
if err != nil {
return errors.Wrap(errors.WithStack(err), "kubectl not found")
}
if !runtime.GetSystemInfo().IsDarwin() {
if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("mkdir -p %s && chown 1000:1000 %s", storage.OlaresSharedLibDir, storage.OlaresSharedLibDir), false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "failed to create shared lib dir")
}
}
var cmd = fmt.Sprintf("%s get secret -n kubesphere-system redis-secret -o jsonpath='{.data.auth}' |base64 -d", kubectl)
redisPwd, err := runtime.GetRunner().SudoCmd(cmd, false, false)
if err != nil {
return errors.Wrap(errors.WithStack(err), "get redis secret error")
}
if redisPwd == "" {
return fmt.Errorf("redis secret not found")
}
config, err := ctrl.GetConfig()
if err != nil {
return err
@@ -61,7 +46,6 @@ func (t *InstallOsSystem) Execute(runtime connector.Runtime) error {
defer cancel()
vals := map[string]interface{}{
"kubesphere": map[string]interface{}{"redis_password": redisPwd},
"backup": map[string]interface{}{
"bucket": t.KubeConf.Arg.Storage.BackupClusterBucket,
"key_prefix": t.KubeConf.Arg.Storage.StoragePrefix,

View File

@@ -5,8 +5,11 @@ import (
"fmt"
"github.com/beclab/Olares/cli/pkg/core/task"
"github.com/beclab/Olares/cli/pkg/terminus"
iamv1alpha2 "github.com/beclab/api/iam/v1alpha2"
kruntime "k8s.io/apimachinery/pkg/runtime"
"os"
"path"
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
"time"
"github.com/beclab/Olares/cli/pkg/common"
@@ -15,9 +18,7 @@ import (
"github.com/beclab/Olares/cli/pkg/utils"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/kubernetes"
metadataclient "k8s.io/client-go/metadata"
ctrl "sigs.k8s.io/controller-runtime"
)
@@ -129,29 +130,37 @@ func (p *prepareUserInfoForUpgrade) Execute(runtime connector.Runtime) error {
if err != nil {
return fmt.Errorf("failed to get rest config: %s", err)
}
// we only need user's metadata, this avoids the dependency on kubesphere's module
metadataClient, err := metadataclient.NewForConfig(config)
scheme := kruntime.NewScheme()
err = iamv1alpha2.AddToScheme(scheme)
if err != nil {
return fmt.Errorf("failed to get metadata client: %s", err)
return fmt.Errorf("failed to add user scheme: %s", err)
}
userGVR := schema.GroupVersionResource{
Group: "iam.kubesphere.io",
Version: "v1alpha2",
Resource: "users",
userClient, err := ctrlclient.New(config, ctrlclient.Options{Scheme: scheme})
if err != nil {
return fmt.Errorf("failed to create client: %s", err)
}
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)
defer cancel()
users, err := metadataClient.Resource(userGVR).List(ctx, metav1.ListOptions{})
var userList iamv1alpha2.UserList
err = userClient.List(ctx, &userList)
if err != nil {
return fmt.Errorf("failed to list users: %s", err)
}
var usersToUpgrade []metav1.PartialObjectMetadata
var usersToUpgrade []iamv1alpha2.User
var adminUser string
client, err := kubernetes.NewForConfig(config)
if err != nil {
return fmt.Errorf("failed to create kubernetes client: %s", err)
}
for _, user := range users.Items {
for _, user := range userList.Items {
if user.Status.State == "Failed" {
logger.Infof("skipping user %s that failed to be created", user.Name)
continue
}
if user.Status.State == "Deleting" || user.DeletionTimestamp != nil {
logger.Infof("skipping user %s that's being deleted", user.Name)
continue
}
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)
defer cancel()
_, err := client.CoreV1().Namespaces().Get(ctx, fmt.Sprintf("user-space-%s", user.Name), metav1.GetOptions{})
@@ -197,7 +206,7 @@ func (u *upgradeUserComponents) Execute(runtime connector.Runtime) error {
if !ok {
return fmt.Errorf("no users to upgrade found in cache")
}
users := usersCache.([]metav1.PartialObjectMetadata)
users := usersCache.([]iamv1alpha2.User)
adminUserCache, ok := u.PipelineCache.Get(common.CacheUpgradeAdminUser)
if !ok {
return fmt.Errorf("no admin user to upgrade found in cache")

View File

@@ -66,7 +66,7 @@ func check(base *semver.Version, target *semver.Version) error {
return fmt.Errorf("upgrade on %s rlease line can only be performed across same major level version", baseReleaseLine)
}
case dailyLine:
if !samePatchLevelVersion(base, target) {
if !sameMinorLevelVersion(base, target) {
return fmt.Errorf("upgrade on %s rlease line can only be performed across same patch version", baseReleaseLine)
}
}
@@ -90,39 +90,34 @@ func GetUpgradePathFor(base *semver.Version, target *semver.Version) ([]*semver.
var path []*semver.Version
var releaseLineUpgraders []breakingUpgrader
var versionFilter func(v *semver.Version) bool
switch getReleaseLineOfVersion(base) {
line := getReleaseLineOfVersion(base)
if target == nil {
cliVersion, err := utils.ParseOlaresVersionString(version.VERSION)
if err != nil {
return path, fmt.Errorf("invalid olares-cli version :\"%s\"", version.VERSION)
}
if getReleaseLineOfVersion(cliVersion) == line && cliVersion.GreaterThan(base) {
target = cliVersion
}
}
switch line {
case mainLine:
releaseLineUpgraders = mainUpgraders
versionFilter = func(v *semver.Version) bool {
if !v.GreaterThan(base) {
return false
}
if !sameMajorLevelVersion(v, base) {
return false
}
if target != nil && !v.LessThan(target) {
return false
}
return true
}
case dailyLine:
if target == nil {
cliVersion, err := utils.ParseOlaresVersionString(version.VERSION)
if err != nil {
return path, fmt.Errorf("invalid olares-cli version :\"%s\"", version.VERSION)
}
if getReleaseLineOfVersion(cliVersion) == dailyLine && samePatchLevelVersion(cliVersion, base) && cliVersion.GreaterThan(base) {
target = cliVersion
}
}
releaseLineUpgraders = dailyUpgraders
versionFilter = func(v *semver.Version) bool {
if !v.GreaterThan(base) {
return false
}
if !samePatchLevelVersion(v, base) {
return false
}
if target != nil && !v.LessThan(target) {
return false
}
@@ -163,6 +158,10 @@ func samePatchLevelVersion(a, b *semver.Version) bool {
return a.Major() == b.Major() && a.Minor() == b.Minor() && a.Patch() == b.Patch()
}
func sameMinorLevelVersion(a, b *semver.Version) bool {
return a.Major() == b.Major() && a.Minor() == b.Minor()
}
func sameMajorLevelVersion(a, b *semver.Version) bool {
return a.Major() == b.Major()
}

View File

@@ -26,7 +26,7 @@ require (
github.com/dustin/go-humanize v1.0.1
github.com/eball/zeroconf v0.2.1
github.com/godbus/dbus/v5 v5.1.0
github.com/gofiber/fiber/v2 v2.52.5
github.com/gofiber/fiber/v2 v2.52.9
github.com/hirochachacha/go-smb2 v1.1.0
github.com/jaypipes/ghw v0.13.0
github.com/jochenvg/go-udev v0.0.0-20171110120927-d6b62d56d37b
@@ -67,7 +67,7 @@ require (
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/Microsoft/hcsshim v0.11.7 // indirect
github.com/StackExchange/wmi v1.2.1 // indirect
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/andybalholm/brotli v1.1.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect

View File

@@ -20,6 +20,8 @@ github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
@@ -126,6 +128,8 @@ github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofiber/fiber/v2 v2.52.5 h1:tWoP1MJQjGEe4GB5TUGOi7P2E0ZMMRx5ZTG4rT+yGMo=
github.com/gofiber/fiber/v2 v2.52.5/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ=
github.com/gofiber/fiber/v2 v2.52.9 h1:YjKl5DOiyP3j0mO61u3NTmK7or8GzzWzCFzkboyP5cw=
github.com/gofiber/fiber/v2 v2.52.9/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=

View File

@@ -67,7 +67,7 @@ func (u *userCertWatcher) Watch(ctx context.Context) {
}
// Check if the certificate will expire within 10 days
if expiredTime.Before(time.Now().Add(10 * 24 * time.Hour)) {
if expiredTime.Before(time.Now().Add(5 * 24 * time.Hour)) {
klog.Info("user cert expired, ", user.GetName())
err = createOrUpdateJob(ctx, kubeClient, namespace)
if err != nil {
@@ -90,14 +90,16 @@ func createOrUpdateJob(ctx context.Context, kubeClient kubernetes.Interface, nam
}
} else {
// check the existing job
if currentJob.Status.Succeeded == 0 || currentJob.Status.Failed > 0 {
if currentJob.Status.Active > 0 {
klog.Info("job is still running, skip creating a new one")
return nil
}
// If the job exists and has completed, delete it before creating a new one
klog.Info("delete existing job: ", currentJob.Name)
err = kubeClient.BatchV1().Jobs(namespace).Delete(ctx, currentJob.Name, metav1.DeleteOptions{})
err = kubeClient.BatchV1().Jobs(namespace).
Delete(ctx, currentJob.Name,
metav1.DeleteOptions{PropagationPolicy: ptr.To(metav1.DeletePropagationBackground)})
if err != nil {
return fmt.Errorf("failed to delete job: %w", err)
}
@@ -131,7 +133,7 @@ var jobDownloadUserCert = batchv1.Job{
"--header",
"X-FROM-CRONJOB: true",
"-qSO -",
"http://bfl.user-space-pengpeng9/bfl/backend/v1/re-download-cert",
"http://bfl/bfl/backend/v1/re-download-cert",
},
},
},

View File

@@ -199,8 +199,7 @@ var downloadPhases = []upgradePhase{
}
var upgradePhases = []upgradePhase{
{upgrade.NewVersionCompatibilityCheck, 0, 5},
{upgrade.NewPreCheck, 5, 5},
{upgrade.NewPreCheck, 0, 10},
{upgrade.NewInstallCLI, 10, 10},
{upgrade.NewInstallOlaresd, 20, 10},
{upgrade.NewImportImages, 30, 30},

View File

@@ -78,6 +78,8 @@ type state struct {
FRPEnable string `json:"frpEnable"`
ContainerMode *string `json:"containerMode,omitempty"`
Pressure []utils.NodePressure `json:"pressures,omitempty"`
}
var CurrentState state
@@ -340,6 +342,18 @@ func CheckCurrentStatus(ctx context.Context) error {
return err
}
pressure, err := utils.GetNodesPressure(ctx, kubeClient)
if err != nil {
klog.Error("get nodes pressure error, ", err)
} else {
// update node pressure of current node
if p, ok := pressure[*CurrentState.HostName]; ok && len(p) == 0 {
CurrentState.Pressure = p
} else {
CurrentState.Pressure = nil
}
}
if CurrentState.InstallFinishedTime != nil {
CurrentState.InstalledTime = pointer.Int64(CurrentState.InstallFinishedTime.Unix())
} else {

View File

@@ -5,12 +5,13 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/Masterminds/semver/v3"
"os"
"os/exec"
"strconv"
"strings"
"github.com/Masterminds/semver/v3"
"github.com/beclab/Olares/daemon/pkg/cli"
"github.com/beclab/Olares/daemon/pkg/commands"
"github.com/beclab/Olares/daemon/pkg/utils"
@@ -182,7 +183,7 @@ func (t *UpgradeTarget) IsValidRequest() error {
if CurrentState.TerminusVersion != nil {
current, err := semver.NewVersion(*CurrentState.TerminusVersion)
if err != nil {
return fmt.Errorf("invalid current version %s: %v", CurrentState.TerminusVersion, err)
return fmt.Errorf("invalid current version %s: %v", *CurrentState.TerminusVersion, err)
}
if !current.LessThan(&t.Version) {
return fmt.Errorf("target version should be greater than current version: %s", current)

View File

@@ -13,30 +13,29 @@ import (
type Operations string
const (
Install Operations = "install"
Initialize Operations = "initialize"
ChangeIp Operations = "changeIp"
Uninstall Operations = "uninstall"
CreateUpgradeTarget Operations = "createUpgradeTarget"
RemoveUpgradeTarget Operations = "removeUpgradeTarget"
DownloadCLI Operations = "downloadCLI"
DownloadWizard Operations = "downloadWizard"
VersionCompatibilityCheck Operations = "versionCompatibilityCheck"
UpgradePreCheck Operations = "PreCheck"
DownloadSpaceCheck Operations = "downloadSpaceCheck"
DownloadComponent Operations = "downloadComponent"
ImportImages Operations = "importImages"
InstallOlaresd Operations = "installOlaresd"
Upgrade Operations = "upgrade"
InstallCLI Operations = "installCLI"
Reboot Operations = "reboot"
Shutdown Operations = "shutdown"
ConnectWifi Operations = "connectWifi"
ChangeHost Operations = "changeHost"
UmountUsb Operations = "umountUsb"
CollectLogs Operations = "collectLogs"
MountSmb Operations = "mountSmb"
UmountSmb Operations = "umountSmb"
Install Operations = "install"
Initialize Operations = "initialize"
ChangeIp Operations = "changeIp"
Uninstall Operations = "uninstall"
CreateUpgradeTarget Operations = "createUpgradeTarget"
RemoveUpgradeTarget Operations = "removeUpgradeTarget"
DownloadCLI Operations = "downloadCLI"
DownloadWizard Operations = "downloadWizard"
UpgradePreCheck Operations = "PreCheck"
DownloadSpaceCheck Operations = "downloadSpaceCheck"
DownloadComponent Operations = "downloadComponent"
ImportImages Operations = "importImages"
InstallOlaresd Operations = "installOlaresd"
Upgrade Operations = "upgrade"
InstallCLI Operations = "installCLI"
Reboot Operations = "reboot"
Shutdown Operations = "shutdown"
ConnectWifi Operations = "connectWifi"
ChangeHost Operations = "changeHost"
UmountUsb Operations = "umountUsb"
CollectLogs Operations = "collectLogs"
MountSmb Operations = "mountSmb"
UmountSmb Operations = "umountSmb"
)
func (p Operations) Stirng() string {

View File

@@ -14,74 +14,13 @@ import (
"runtime"
"strings"
"github.com/Masterminds/semver/v3"
"github.com/beclab/Olares/daemon/pkg/commands"
"github.com/beclab/Olares/daemon/pkg/utils"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/klog/v2"
)
type versionCompatibilityCheck struct {
commands.Operation
}
var _ commands.Interface = &versionCompatibilityCheck{}
func NewVersionCompatibilityCheck() commands.Interface {
return &versionCompatibilityCheck{
Operation: commands.Operation{
Name: commands.VersionCompatibilityCheck,
},
}
}
func (i *versionCompatibilityCheck) Execute(ctx context.Context, p any) (res any, err error) {
target, ok := p.(state.UpgradeTarget)
if !ok {
err = errors.New("invalid param")
return
}
dynamicClient, err := utils.GetDynamicClient()
if err != nil {
return nil, fmt.Errorf("error getting kubernetes client: %v", err)
}
olaresVersion, err := utils.GetTerminusVersion(ctx, dynamicClient)
if err != nil {
return nil, fmt.Errorf("error getting olares version: %v", err)
}
currentVersion, err := semver.NewVersion(*olaresVersion)
if err != nil {
return nil, fmt.Errorf("error parsing current olares version %s: %v", *olaresVersion, err)
}
versionHintFile := filepath.Join(commands.TERMINUS_BASE_DIR, "versions", "v"+target.Version.Original(), "version.hint")
content, err := os.ReadFile(versionHintFile)
if err != nil {
return nil, fmt.Errorf("error reading version hint file %s: %v", versionHintFile, err)
}
versionHint := make(map[string]map[string]string)
if err := yaml.Unmarshal(content, &versionHint); err != nil {
return nil, fmt.Errorf("error parsing version hint file %s: %v", versionHintFile, err)
}
upgradeField, ok := versionHint["upgrade"]
if !ok {
return nil, fmt.Errorf("no upgrade field found in version hint file %s, content: %s", versionHintFile, content)
}
minVersionStr, ok := upgradeField["minVersion"]
if !ok || minVersionStr == "" {
return nil, fmt.Errorf("no minVersion field found in version hint file %s, content: %s", versionHintFile, content)
}
minVersion, err := semver.NewVersion(minVersionStr)
if err != nil {
return nil, fmt.Errorf("error parsing minVersion: %s in version hint file %s: %v", minVersionStr, versionHintFile, err)
}
if currentVersion.LessThan(minVersion) {
return nil, fmt.Errorf("minVersion %s is greater than current version %s", minVersionStr, *olaresVersion)
}
return newExecutionRes(true, nil), nil
}
type preCheck struct {
commands.Operation
}

View File

@@ -5,6 +5,8 @@ package utils
import (
"fmt"
"io"
"log"
"strings"
"github.com/jaypipes/ghw"
@@ -13,7 +15,7 @@ import (
)
func GetGpuInfo() (*string, error) {
gpu, err := ghw.GPU()
gpu, err := ghw.GPU(ghw.WithAlerter(log.New(io.Discard, "", 0))) // discard warnings
if err != nil {
klog.Errorf("Error getting GPU info: %v", err)
return nil, err

View File

@@ -140,6 +140,11 @@ func IsIpChanged(ctx context.Context, installed bool) (bool, error) {
return false, err
}
masterIpFromETCD, err := MasterNodeIp(installed)
if err != nil {
return false, err
}
for _, ip := range ips {
hostIps, err := nets.LookupHostIps()
if err != nil {
@@ -148,10 +153,19 @@ func IsIpChanged(ctx context.Context, installed bool) (bool, error) {
for _, hostIp := range hostIps {
if hostIp == ip.IP {
klog.V(8).Info("host ip is the same as internal ip of interface, ", hostIp, ", ", ip.IP)
if !installed {
// terminus not installed
return false, nil
if masterIpFromETCD == "" {
return false, nil
}
if masterIpFromETCD == ip.IP {
return false, nil
}
return true, nil
}
kubeClient, err := GetKubeClient()
@@ -162,8 +176,18 @@ func IsIpChanged(ctx context.Context, installed bool) (bool, error) {
_, nodeIp, nodeRole, err := GetThisNodeName(ctx, kubeClient)
if err != nil {
klog.Error("get this node name error, ", err)
return false, nil
klog.Warning("get this node name error, ", err, ", try to compare with etcd ip")
if masterIpFromETCD == "" {
klog.Info("master node ip not found, mybe it's a worker node")
return false, nil
}
if masterIpFromETCD == ip.IP {
return false, nil
}
klog.Info("master node ip from etcd is not the same as internal ip of interface, ", masterIpFromETCD, ", ", hostIp, ", ", ip.IP)
return true, nil
}
@@ -176,12 +200,13 @@ func IsIpChanged(ctx context.Context, installed bool) (bool, error) {
return false, nil
}
klog.Info("get node ip, ", nodeIp, ", ", hostIp, ", ", ip.IP)
klog.Info("node is master and node ip is not the same as internal ip of interface, ", nodeIp, ", ", hostIp, ", ", ip.IP)
return true, nil
}
}
}
} // end for host ips
} // end for interface ips
klog.Info("no host ip is the same as internal ip of interface, ", ips)
return true, nil
}
@@ -491,3 +516,22 @@ func GetUserspacePvcHostPath(ctx context.Context, user string, client kubernetes
return hostpath, nil
}
func GetNodesPressure(ctx context.Context, client kubernetes.Interface) (map[string][]NodePressure, error) {
nodes, err := client.CoreV1().Nodes().List(ctx, metav1.ListOptions{})
if err != nil {
klog.Error("list nodes error, ", err)
return nil, err
}
status := make(map[string][]NodePressure)
for _, node := range nodes.Items {
for _, condition := range node.Status.Conditions {
if condition.Type != corev1.NodeReady && condition.Status == corev1.ConditionTrue {
status[node.Name] = append(status[node.Name], NodePressure{Type: condition.Type, Message: condition.Message})
}
}
}
return status, nil
}

View File

@@ -1,6 +1,9 @@
package utils
import "k8s.io/apimachinery/pkg/runtime/schema"
import (
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
)
var (
UserSchemeGroupVersion = schema.GroupVersion{Group: "iam.kubesphere.io", Version: "v1alpha2"}
@@ -11,3 +14,8 @@ var (
Resource: "users",
}
)
type NodePressure struct {
Type corev1.NodeConditionType `json:"type"`
Message string `json:"message"`
}

View File

@@ -68,14 +68,13 @@ const side = {
{text: "Manage Olares", link:"/manual/larepass/manage-olares"},
],
},
{
text: "Manage files",
collapsed: true,
items: [
{text: "Common file operations", link:"/manual/larepass/manage-files"},
{text: "Sync and share", link:"/manual/larepass/sync-share"}
]
},
{text: "Manage files", link:"/manual/larepass/manage-files"},
// collapsed: true,
//items: [
// {text: "Common file operations", link:"/manual/larepass/manage-files"},
// {text: "Sync and share", link:"/manual/larepass/sync-share"}
// ]
// },
{
text: "Manage passwords",
collapsed: true,
@@ -106,17 +105,17 @@ const side = {
text: "Basic file operations",
link: "/manual/olares/files/add-edit-download",
},
{
text: "Sync and share",
link: "/manual/larepass/sync-share",
},
// {
// text: "Sync and share",
// link: "/manual/larepass/sync-share",
// },
{
text: "Mount SMB",
link: "/manual/olares/files/mount-SMB",
},
{text: "Mount cloud storage",
link: "/manual/olares/files/mount-cloud-storage",
},
// {text: "Mount cloud storage",
// link: "/manual/olares/files/mount-cloud-storage",
// },
],
},
{
@@ -512,47 +511,47 @@ const side = {
text: "Olares versioning",
link: "/developer/install/versioning",
},
],
},
// {
// text: "Additional installations",
// link: "/developer/install/additional-installations",
// collapsed: true,
// items: [
// { text: "Linux (via Docker)", link: "/developer/install/linux-via-docker-compose"},
// {
// text: "macOS",
// collapsed: true,
// items: [
// {
// text: "Using the script (recommended)",
// link: "/developer/install/mac",
// },
// {
// text: "Using Docker image",
// link: "/developer/install/mac-via-docker-image",
// },
// ],
// },
// {
// text: "Windows (WSL 2)",
// collapsed: true,
// items: [
// {
// text: "Using the script (recommended)",
// link: "/developer/install/windows",
// },
// {
// text: "Using Docker image",
// link: "/developer/install/windows-via-docker-image",
// },
// ],
// },
// { text: "PVE", link: "/developer/install/pve" },
// { text: "LXC", link: "/developer/install/lxc" },
// { text: "Raspberry Pi", link: "/developer/install/raspberry-pi" },
// ],
// },
{
text: "Additional installations",
link: "/developer/install/additional-installations",
collapsed: true,
items: [
{ text: "Linux (via Docker)", link: "/developer/install/linux-via-docker-compose"},
{
text: "macOS",
collapsed: true,
items: [
{
text: "Using the script (recommended)",
link: "/developer/install/mac",
},
{
text: "Using Docker image",
link: "/developer/install/mac-via-docker-image",
},
],
},
{
text: "Windows (WSL 2)",
collapsed: true,
items: [
{
text: "Using the script (recommended)",
link: "/developer/install/windows",
},
{
text: "Using Docker image",
link: "/developer/install/windows-via-docker-image",
},
],
},
{ text: "PVE", link: "/developer/install/pve" },
{ text: "LXC", link: "/developer/install/lxc" },
{ text: "Raspberry Pi", link: "/developer/install/raspberry-pi" },
],
},
],
},
{
text: "Develop Olares app",
link: "/developer/develop/",

View File

@@ -70,14 +70,13 @@ const side = {
{text: "管理 Olares", link:"/zh/manual/larepass/manage-olares"},
],
},
{
text: "管理文件",
collapsed: true,
items: [
{text: "常用文件操作", link:"/zh/manual/larepass/manage-files"},
{text: "同步与共享", link:"/zh/manual/larepass/sync-share"}
]
},
{text: "管理文件", link:"/zh/manual/larepass/manage-files"},
// collapsed: true,
// items: [
// {text: "常用文件操作", link:"/zh/manual/larepass/manage-files"},
// {text: "同步与共享", link:"/zh/manual/larepass/sync-share"}
// ]
// },
{
text: "管理密码",
collapsed: true,
@@ -108,18 +107,18 @@ const side = {
"text": "基本文件操作",
"link": "/zh/manual/olares/files/add-edit-download"
},
{
"text": "同步与共享",
"link": "/zh/manual/larepass/sync-share"
},
//{
// "text": "同步与共享",
// "link": "/zh/manual/larepass/sync-share"
// },
{
"text": "挂载 SMB",
"link": "/zh/manual/olares/files/mount-SMB"
},
{
"text": "挂载云存储",
"link": "/zh/manual/olares/files/mount-cloud-storage"
}
// {
// "text": "挂载云存储",
// "link": "/zh/manual/olares/files/mount-cloud-storage"
// }
]
},
{
@@ -518,45 +517,45 @@ const side = {
text: "版本说明",
link: "/zh/developer/install/versioning",
},
// {
// text: "其他安装方式",
// link: "/zh/developer/install/additional-installations",
// collapsed: true,
// items: [
// { text: "LinuxDocker 镜像)", link: "/zh/developer/install/linux-via-docker-compose" },
// {
// text: "macOS",
// collapsed: true,
// items: [
// {
// text: "使用脚本(推荐)",
// link: "/zh/developer/install/mac",
// },
// {
// text: "使用 Docker 镜像",
// link: "/zh/developer/install/mac-via-docker-image",
// },
// ],
// },
// {
// text: "Windows (WSL 2)",
// collapsed: true,
// items: [
// {
// text: "使用脚本(推荐)",
// link: "/zh/developer/install/windows",
// },
// {
// text: "使用 Docker 镜像",
// link: "/zh/developer/install/windows-via-docker-image",
// },
// ],
// },
// { text: "PVE", link: "/zh/developer/install/pve" },
// { text: "LXC", link: "/zh/developer/install/lxc" },
// { text: "树莓派", link: "/zh/developer/install/raspberry-pi" },
// ],
// },
{
text: "其他安装方式",
link: "/zh/developer/install/additional-installations",
collapsed: true,
items: [
{ text: "LinuxDocker 镜像)", link: "/zh/developer/install/linux-via-docker-compose" },
{
text: "macOS",
collapsed: true,
items: [
{
text: "使用脚本(推荐)",
link: "/zh/developer/install/mac",
},
{
text: "使用 Docker 镜像",
link: "/zh/developer/install/mac-via-docker-image",
},
],
},
{
text: "Windows (WSL 2)",
collapsed: true,
items: [
{
text: "使用脚本(推荐)",
link: "/zh/developer/install/windows",
},
{
text: "使用 Docker 镜像",
link: "/zh/developer/install/windows-via-docker-image",
},
],
},
{ text: "PVE", link: "/zh/developer/install/pve" },
{ text: "LXC", link: "/zh/developer/install/lxc" },
{ text: "树莓派", link: "/zh/developer/install/raspberry-pi" },
],
},
],
},
{

View File

@@ -119,10 +119,10 @@ As Olares evolves, the configuration specification of `OlaresManifest.yaml` may
Developers can use 1-3 digit version numbers to indicate the application's configuration version. Here are some examples of valid versions:
```Yaml
OlaresManifest.yaml.version: 1
OlaresManifest.yaml.version: 1.1.0
OlaresManifest.yaml.version: '2.2'
OlaresManifest.yaml.version: "3.0.122"
olaresManifest.version: 1
olaresManifest.version: 1.1.0
olaresManifest.version: '2.2'
olaresManifest.version: "3.0.122"
```
## Metadata

View File

@@ -10,4 +10,5 @@ This section provides in-depth information, command references, and instructions
- [Olares Home introduction](olares-home.md): Understand the structure of the base installation directory.
- [Olares environment variables reference](environment-variables.md): Find the right environment variables for you to customize the installation.
- [Olares CLI reference](./index.md): Uses the Olares CLI for advanced customization and troubleshooting during installation.
- [Olares versioning](versioning.md): Learn versioning rules, release types, branch management practices, and upgrade guidelines of Olares.
- [Olares versioning](versioning.md): Learn versioning rules, release types, branch management practices, and upgrade guidelines of Olares.
- [Additional installations](additional-installations.md): Try Olares on Docker, macOS, Windows, and PVE, and Raspberry Pi.

View File

@@ -15,11 +15,15 @@ Make sure your device meets the following requirements.
- CPU: At least 4 cores
- RAM: At least 8GB of available memory
- Storage: At least 64GB of available space (SSD recommended)
- Storage: At least 150GB of available SSD storage.
- Supported systems:
- Ubuntu 20.04 LTS or later
- Debian 11 or later
::: warning SSD required
The installation will likely fail if an HDD (mechanical hard drive) is used instead of an SSD.
:::
:::info Version compatibility
While these specific versions are confirmed to work, the process may still work on other versions. Adjustments may be necessary depending on your environment. If you meet any issues with these platforms, feel free to raise an issue on [GitHub](https://github.com/beclab/Olares/issues/new).
:::
@@ -53,6 +57,70 @@ cd ~/olares-config
:::
3. Save the `docker-compose.yaml` file.
Here is the updated and properly formatted Markdown content for installing GPU drivers and the NVIDIA Container Toolkit, ready to be included in your installation guide:
## Install GPU dependencies (for GPU-enabled machines)
1. Install GPU drivers for your system:
```bash
curl -o /tmp/keyring.deb -L https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb && \
sudo dpkg -i --force-all /tmp/keyring.deb
sudo apt update
sudo apt install nvidia-kernel-open-570
sudo apt install nvidia-driver-570
````
2. Install the NVIDIA Container Toolkit to enable Docker to access your GPU.
a. Configure the repository:
```bash
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \
sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo sed -i -e '/experimental/ s/^#//g' /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt-get update
```
b. Install the toolkit and restart docker:
```bash
sudo apt-get install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
```
c. Verify the installation:
```bash
sudo docker run --rm --runtime=nvidia --gpus all ubuntu nvidia-smi
```
If successful, you should see output similar to the following:
```
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 570.169 Driver Version: 570.169 CUDA Version: 12.8 |
|-----------------------------------------+------------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|=========================================+========================+======================|
| 0 NVIDIA GeForce RTX 4070 ... Off | 00000000:01:00.0 Off | N/A |
| N/A 41C P8 1W / 80W | 32MiB / 8188MiB | 0% Default |
| | | N/A |
+-----------------------------------------+------------------------+----------------------+
```
## Set up environment variables and start container
1. In the `olares-config` directory, use the following command to set the environment variables and start the Olares services:
@@ -122,7 +190,7 @@ To uninstall the container:
docker compose down
```
<!--@include: ./reusables.md{35,39}-->
<!--@include: ./reusables.md{39,43}-->

View File

@@ -8,17 +8,20 @@ LXC (Linux Containers) is a lightweight virtualization method that runs applicat
Currently, Olares on LXC has certain limitations. We recommend using it only for development or testing purposes.
:::
<!--@include: ./reusables.md{41,47}-->
<!--@include: ./reusables.md{45,51}-->
## System requirements
Make sure your device meets the following requirements.
- CPU: At least 4 cores
- RAM: At least 8GB of available memory
- Storage: At least 64GB of available space (SSD recommended)
- Storage: At least 150GB of available SSD storage.
- Supported systems:
- PVE 8.2.2
- Linux container: Debian 12 (for existing LXC containers on PVE)
::: warning SSD required
The installation will likely fail if an HDD (mechanical hard drive) is used instead of an SSD.
:::
:::info Version compatibility
While the specific versions are confirmed to work, the process may still work on other versions. Adjustments may be necessary depending on your environment. If you meet any issues with these platforms, feel free to raise an issue on [GitHub](https://github.com/beclab/Olares/issues/new).
@@ -144,10 +147,10 @@ To install Olares on an existing LXC container, skip to step 2 directly. Make su
Run the following installation command inside the LXC container:
<!--@include: ./reusables.md{4,33}-->
<!--@include: ./reusables.md{5,37}-->
<!--@include: ./activate-olares.md-->
<!--@include: ./log-in-to-olares.md-->
<!--@include: ./reusables.md{35,39}-->
<!--@include: ./reusables.md{39,43}-->

View File

@@ -13,7 +13,7 @@ Currently, Olares on Mac has certain limitations including:
We recommend using it only for development or testing purposes.
:::
<!--@include: ./reusables.md{41,47}-->
<!--@include: ./reusables.md{45,51}-->
## System requirements
Make sure your device meets the following requirements.
@@ -21,7 +21,10 @@ Make sure your device meets the following requirements.
- Architecture: AMD64 or ARM64
- CPU: At least 4 cores
- RAM: At least 8GB of available memory
- Storage: At least 64GB of available space (SSD recommended)
- Storage: At least 150GB of available SSD storage.
::: warning SSD required
The installation will fail if an HDD (mechanical hard drive) is used instead of an SSD.
:::
## Before you begin
Before you begin, ensure the following:
@@ -97,4 +100,4 @@ The `--rm` flag automatically deletes the container after it stops. If this happ
<!--@include: ./manage-olares-container.md-->
<!--@include: ./reusables.md{35,39}-->
<!--@include: ./reusables.md{39,43}-->

View File

@@ -12,14 +12,17 @@ Olares on Mac has certain limitations including:
We recommend using it only for development or testing purposes.
:::
<!--@include: ./reusables.md{41,47}-->
<!--@include: ./reusables.md{45,51}-->
## System compatibility
Make sure your Mac meets the following requirements.
- Architecture: X86-64 or ARM64
- RAM: 8 GB or above (available memory)
- Storage: 90 GB or above (available disk space)
- Storage: 150 GB or above of available space on SSD
- MacOS: Monterey (12) or later
::: warning SSD required
The installation will likely fail if an HDD (mechanical hard drive) is used instead of an SSD.
:::
## Before you begin
Ensure you have the following installed:
@@ -40,10 +43,10 @@ Ensure you have the following installed:
## Install Olares
In terminal, run the following command:
<!--@include: ./reusables.md{4,33}-->
<!--@include: ./reusables.md{4,37}-->
<!--@include: ./activate-olares.md-->
<!--@include: ./log-in-to-olares.md-->
<!--@include: ./reusables.md{35,39}-->
<!--@include: ./reusables.md{39,43}-->

View File

@@ -8,16 +8,20 @@ Proxmox Virtual Environment (PVE) is an open-source virtualization platform base
Currently, Olares on PVE has certain limitations. We recommend using it only for development or testing purposes.
:::
<!--@include: ./reusables.md{41,47}-->
<!--@include: ./reusables.md{45,51}-->
## System requirements
Make sure your device meets the following requirements.
- CPU: At least 4 cores
- RAM: At least 8GB of available memory
- Storage: At least 64GB of available space (SSD recommended)
- Storage: At least 150GB of available SSD storage.
- Supported Systems: PVE 8.2.2
::: warning SSD required
The installation will likely fail if an HDD (mechanical hard drive) is used instead of an SSD.
:::
:::info Version compatibility
While the specific version is confirmed to work, the process may still work on other versions. Adjustments may be necessary depending on your environment. If you meet any issues with these platforms, feel free to raise an issue on [GitHub](https://github.com/beclab/Olares/issues/new).
:::
@@ -26,10 +30,10 @@ While the specific version is confirmed to work, the process may still work on o
In PVE CLI, run the following command:
<!--@include: ./reusables.md{4,33}-->
<!--@include: ./reusables.md{5,37}-->
<!--@include: ./activate-olares.md-->
<!--@include: ./log-in-to-olares.md-->
<!--@include: ./reusables.md{35,39}-->
<!--@include: ./reusables.md{39,43}-->

View File

@@ -7,13 +7,17 @@ This guide explains how to install Olares on a Raspberry Pi.
:::warning Not recommended for production use
Currently, Olares on Raspberry Pi has certain limitations. We recommend using it only for development or testing purposes.
:::
<!--@include: ./reusables.md{41,47}-->
<!--@include: ./reusables.md{45,51}-->
## System requirements
Make sure your Raspbian device meets the following requirements.
- Hardware: Raspberry Pi 4B or Raspberry Pi 5 with 8GB memory
- Operating system: Raspbian 12
- Storage: 64GB (SSD recommended)
- Storage: At least 150GB of available SSD storage.
::: warning SSD required
The installation will likely fail if an HDD (mechanical hard drive) is used instead of an SSD.
:::
## Set up system environment
1. Configure the Raspbian environment to enable necessary features:
@@ -38,4 +42,4 @@ Run the following command:
<!--@include: ./log-in-to-olares.md-->
<!--@include: ./reusables.md{35,39}-->
<!--@include: ./reusables.md{39,43}-->

View File

@@ -42,10 +42,10 @@ You're almost ready to start using Olares! Before diving in, it's crucial to ens
- [Back up your mnemonic phrase](/manual/larepass/back-up-mnemonics.md)
:::info Having trouble with installation?
::: info Having trouble with installation?
If you encounter issues during the installation process, feel free to [submit a GitHub Issue](https://github.com/beclab/Olares/issues/new). Please include the following information when submitting:
- The platform or environment you're using (e.g., Ubuntu, Docker, WSL, etc.).
- The installation method (script installation or Docker image).
- Detailed error information (including logs, error messages, or screenshots).
:::
:::

View File

@@ -11,18 +11,23 @@ Currently, Olares on Windows has certain limitations including:
- Inability to add local nodes.
We recommend using it only for development or testing purposes.
:::
<!--@include: ./reusables.md{41,47}-->
<!--@include: ./reusables.md{44,51}-->
## System requirements
Make sure your Windows meets the following requirements.
- CPU: At least 4 cores
- RAM: At least 16GB of available memory
- Storage: At least 64GB of available space (SSD recommended)
- Storage: At least 150GB of available SSD storage.
- Supported systems:
- Windows 10 or 11
- Linux (on WSL 2): Ubuntu 20.04 LTS or later; Debian 11 or later
::: warning SSD required
The installation will likely fail if an HDD (mechanical hard drive) is used instead of an SSD.
:::
## Before you begin
Before you begin, ensure the following:
- [Docker Desktop](https://docs.docker.com/desktop/setup/install/windows-install/) is installed and running on your system.
@@ -52,7 +57,14 @@ Before you begin, ensure the following:
DXCore version: 10.0.26100.1-240331-1435.ge-release
Windows version: 10.0.26100.3475
```
2. Use the link provided to download the appropriate kernel file matching your version: `https://dc3p1870nn3cj.cloudfront.net/bzImage-<kernel-version>`.
2. Run `docker info` and look for the `Cgroup` version section as shown below. Make sure it is v2.
```powershell
...
Cgroup Driver: cgroupfs
Cgroup version: 2
```
3. Use the link provided to download the appropriate kernel file matching your version: `https://dc3p1870nn3cj.cloudfront.net/bzImage-<kernel-version>`.
For example, For kernel version `5.15.167.4`, download the file from `https://dc3p1870nn3cj.cloudfront.net/bzImage-5.15.167.4`.
Supported kernel versions (above `5.15.146.1`) are:
@@ -63,11 +75,11 @@ Before you begin, ensure the following:
- `linux-msft-wsl-6.6.75.1`
- `linux-msft-wsl-6.6.36.6`
- `linux-msft-wsl-6.6.36.3`
3. Set the default version of WSL to version 2:
4. Set the default version of WSL to version 2:
```bash
wsl --set-default-version 2
```
4. In the directory `C:\Users\<YourUsername>\`, create a file named `.wslconfig` with the following content:
5. In the directory `C:\Users\<YourUsername>\`, create a file named `.wslconfig` with the following content:
```txt
[wsl2]
kernel=c:\\path\\to\\your\\kernel\\bzImage-<version> # Note: Use double backslashes (\\) as path separators
@@ -81,7 +93,7 @@ Before you begin, ensure the following:
wsl --unregister docker-desktop-data # If this version exists
```
:::
5. Restart your computer to apply the changes.
6. Restart your computer to apply the changes.
## Prepare Docker
If you have installed Docker Desktop before modifying `.wslconfig`, remove docker desktop then restart Windows.
@@ -146,4 +158,4 @@ The `--rm` flag automatically deletes the container after it stops. If this happ
<!--@include: ./manage-olares-container.md-->
<!--@include: ./reusables.md{35,39}-->
<!--@include: ./reusables.md{39,43}-->

View File

@@ -12,16 +12,19 @@ Currently, Olares on Windows has certain limitations including:
We recommend using it only for development or testing purposes.
:::
<!--@include: ./reusables.md{41,47}-->
<!--@include: ./reusables.md{45,51}-->
## System compatibility
Make sure your Windows meets the following requirements.
- CPU: At least 4 cores
- RAM: At least 16GB of available memory
- Storage: At least 64GB of available space (SSD recommended)
- Storage: At least 150GB of available SSD storage.
- Supported systems:
- Windows 10 or 11
- Linux (on WSL 2): Ubuntu 20.04 LTS or later; Debian 11 or later
::: warning SSD required
The installation will likely fail if an HDD (mechanical hard drive) is used instead of an SSD.
:::
## Set up system environment
1. Enable the required Windows features for virtualization.
@@ -105,7 +108,7 @@ Make sure your Windows meets the following requirements.
You can get the IPv4 address in advance by running `ipconfig` in the Windows command line.
:::
<!--@include: ./reusables.md{7,9}-->
<!--@include: ./reusables.md{9,11}-->
:::info Errors during installation?
If an error occurs during installation, use the following command to uninstall first:
@@ -114,13 +117,14 @@ wsl --unregister ubuntu
```
After uninstalling, retry the installation by running the original installation command.
:::
<!--@include: ./reusables.md{20,33}-->
<!--@include: ./reusables.md{24,37}-->
<!--@include: ./activate-olares.md-->
<!--@include: ./log-in-to-olares.md-->
<!--@include: ./reusables.md{35,39}-->
<!--@include: ./reusables.md{39,43}-->
## FAQ

View File

@@ -9,7 +9,7 @@ hero:
actions:
- theme: brand
text: What is Olares?
link: /manual/docs-home
link: /manual/overview
- theme: alt
text: Star us on GitHub
link: https://github.com/beclab/olares

View File

@@ -87,8 +87,10 @@ Add and verify your own domain in Olares Space before binding it.
![domain added](/images/manual/tutorials/domain-added.png#bordered)
:::info
TXT verification typically completes within 30 minutes. NS record verification may take up to 2 hours. If the whole process exceeds 3 hours, check with your DNS provider.
:::tip
- TXT verification typically completes within 30 minutes. NS record verification may take up to 2 hours. If the whole process exceeds 3 hours, check with your DNS provider.
- Once verification is successful, do not modify the NS record. Doing so will cause the custom domain resolution to fail, making it inaccessible.
:::
Once TXT and NS records are verified, your domain is successfully added to Olares Space.
@@ -159,30 +161,22 @@ To use the domain, apply for an Olares ID under the organization.
After successful authorization, an Olares ID with the custom domain, `justtest1953@xxxx.cloud`, is successfully created.
## Step 6: Install and activate Olares
Almost there! Now you are all set to install and activate Olares with your Olares ID.
::: tip Install with environment variables
In the following examples, the domain name and username are preset with environment variables.
For Linux environment, you can also install with the one-line script without these variables, and enter the domain and the prefix of Olares ID manually.
For detailed instructions on all supported platforms, refer to [platform-specific installation guides](../get-started/install-olares.md).
:::
Almost there! Now you are all set to install and activate Olares with your Olares ID.
<tabs>
<template #Linux-and-macOS>
1. In the terminal, run the installation script with specified environment variables to start the installation:
1. In the terminal, run the following script to start the installation:
```bash {1,2}
export TERMINUS_OS_DOMAINNAME=xxxx.cloud \
&& export TERMINUS_OS_USERNAME=justtest1953 \
&& curl -sSfL https://olares.sh | bash -
```
- `export TERMINUS_OS_DOMAINNAME=xxxx.cloud`: Specify your custom domain. Replace `xxxx.cloud` with the actual one.
- `export TERMINUS_OS_USERNAME=justtest1953`: Specify the prefix of your Olares ID. Replace `justtest1953` with the actual one.
```bash {1,2}
curl -sSfL https://olares.sh | bash -
```
2. Wait for the installation to finish. Depending on your network, the process can take 2030 minutes. When the installation completes, you will see the wizard URL and login credentials:
2. At the end of the installation, enter your custom domain and Olares ID when prompted. In our case, it's `xxxx.cloud` for the domain, and `justtest1953` for Olares ID.
![Enter the domain](/images/manual/get-started/enter-olares-id.png)
3. Wait for the installation to finish. Depending on your network, the process can take 1030 minutes. When the installation completes, you will see the wizard URL and login credentials:
```bash
2024-12-17T21:00:58.086+0800 Olares is running at:
@@ -197,13 +191,15 @@ For detailed instructions on all supported platforms, refer to [platform-specifi
3. Open the Olares activation wizard in your browser using the given URL, and follow the on-screen instructions to complete the activation.
See [Install Olares](../get-started/install-olares.md) for more detailed steps.
</template>
<template #Windows>
:::warning System environment setup required
Before proceeding with the following steps, ensure that your Windows environment is properly set up.
If the setup is incomplete, the installation script will not work as expected. For detailed instructions, refer to the dedicated [installation guide for Windows](../get-started/install-olares.md).
If the setup is incomplete, the installation script will not work as expected. For detailed instructions, refer to the dedicated [installation guide for Windows](../../developer/install/windows.md).
:::
1. Click https://windows.olares.sh to download the installation script `publicInstall.latest.ps1`.

View File

@@ -12,8 +12,8 @@ An Olares ID consists of a local name and a domain. For example, in `alice123@ol
- `alice123`: Local name
- `olares.com`: Domain name
:::tip Olares ID with custom domain
To create an Olares ID with your custom domain, see [Set up a custom domain for your Olares](../best-practices/set-custom-domain.md).
:::tip Olares ID
To learn more about what is Olares ID and why you need one, see [Olares ID](../concepts/olares-id.md).
:::
## Download and install LarePass app
@@ -25,7 +25,9 @@ To get started with Olares, you'll need to download LarePass on your mobile devi
## Create an Olares ID
::: tip
This section focuses on creating individual Olares IDs. If you want to create an Olares ID for organizational uses, or use a custom domain, refer to [Set up a custom domain](../../space/host-domain.md).
This section is dedicated to helping first-time users quickly create a personal Olares ID for immediate use.
For advanced use cases, such as creating an Olares ID using your social account handle or setting up accounts for a team, refer to [Create accounts](../larepass/create-account.md).
:::
1. In the LarePass app, tap **Create an account**.
@@ -37,6 +39,14 @@ This section focuses on creating individual Olares IDs. If you want to create an
![Fast creation](/images/manual/get-started/create-olares-id.png)
:::tip `.cn` vs. `.com` domains
To ensure the best connectivity and performance, Olares automatically assigns a domain based on your phone's system language and region.
If your phone's system language is set to Chinese, LarePass will assign a `.cn` domain. While functional, this may result in slower performance or DNS resolution issues outside of mainland China due to its specific routing.
To resolve this, please enter **Advanced account creation** mode <i class="material-symbols-outlined">display_settings</i> from the top-right corner of the LarePass account creation page, and switch the default domain to `.com`.
:::
## Next step
Keep your newly created Olares ID and LarePass app handy you'll need them later.

View File

@@ -10,7 +10,7 @@ Make sure your device meets the following requirements.
- CPU: At least 4 cores
- RAM: At least 8GB of available memory
- Storage: At least 64GB of available space (SSD recommended)
- Storage: At least 150GB of available SSD storage. (The installation will fail if an HDD (mechanical hard drive) is used instead of an SSD.)
- Supported systems:
- Ubuntu 24.04 LTS or later
- Debian 11 or later

View File

@@ -25,10 +25,13 @@ Make sure your device meets the following requirements.
- CPU: At least 4 cores
- RAM: At least 8GB of available memory
- Storage: At least 64GB of available space (SSD recommended)
- Storage: At least 150GB of available SSD storage.
- Supported systems:
- Ubuntu 20.04 LTS or later
- Debian 11 or later
::: warning SSD required
The installation will likely fail if an HDD (mechanical hard drive) is used instead of an SSD.
:::
:::info Version compatibility
While these specific versions are confirmed to work, the process may still work on other versions. Adjustments may be necessary depending on your environment. If you meet any issues with these platforms, feel free to raise an issue on [GitHub](https://github.com/beclab/Olares/issues/new).

View File

@@ -52,7 +52,7 @@ Here are some suggested next steps:
{ text: 'Manage accounts', href: '../larepass/create-account' },
{ text: 'Enable VPN', href: '../larepass/private-network' },
{ text: 'Manage device', href: '../larepass/manage-device' },
{ text: 'Sync file', href: '../larepass/sync-share' },
// { text: 'Sync file', href: '../larepass/sync-share' },
{ text: 'Collect content', href: '../larepass/manage-knowledge'},
]"
buttonText="Learn more"

View File

@@ -20,9 +20,7 @@ Create and manage your Olares ID, connect integrations with other services, and
- [Manage integrations](integrations.md)
### Secure file access & sync
Access and sync your Olares files across devices.
- [Manage files with LarePass](manage-files.md)
- [Sync and share files](sync-share.md)
### Device & network management
Activate and manage Olares devices, and securely connect to Olares via LarePass VPN.

View File

@@ -56,7 +56,7 @@ OAuth-based integrations like Google Drive and Dropbox require initial setup via
4. Follow the login prompts to authorize your account.
Once authorized, you'll see the connected account in the integration list. You can now access the storage in Files.
Once authorized, you'll see the connected account in the integration list. You can select the storage for [Olares backup](../olares/settings/backup.md)
## Add a cloud storage using API-keys
@@ -67,10 +67,9 @@ Services like AWS S3 and Tencent Cloud COS require setup using API keys (Access
3. Select AWS S3 or Tencent COS.
4. Enter your Access Key, Secret Key, and other required credentials, then tap **Confirm**.
Once configured, you'll see the connected service in the integration list. And you can access the cloud storage through Files.
Alternatively, you can configure these integrations directly within [Olares Settings](/manual/olares/settings/integrations.md).
Once authorized, you'll see the connected account in the integration list. You can select the storage for [Olares backup](../olares/settings/backup.md)
## Disconnect integrations
::: warning

View File

@@ -78,22 +78,22 @@ If your Olares device moves to a different network:
### Set Wi-Fi via Bluetooth
If you can't connect your Olares to a wired network during activation, or if Olares is on a different wired network than your phone, LarePass won't be able to find it. This can prevent you from completing activation or device management. In such cases, use the **Bluetooth network configuration** feature to connect your Olares to your phone's Wi-Fi network.
If you can't connect your Olares to a wired network during activation, or if Olares is on a different wired network than your phone, LarePass won't be able to find it. This can prevent you from completing activation or device management. In such cases, use the **Bluetooth network setup** feature to connect your Olares to your phone's Wi-Fi network.
![Bluetooth network](/images/manual/larepass/bluetooth-network.png)
1. On the **Olares not found** page, tap the **Bluetooth network configuration** option. LarePass will use your phone's Bluetooth to scan for the nearby Olares device that match your current Olares ID.
2. When your device is found, tap **Network configuration**.
3. From the list of wireless networks available to your Olares, tap the Wi-Fi network your phone is connected to. If it's password-protected, enter the password and tap **Confirm**.
1. On the **Olares not found** page, tap the **Bluetooth network setup** option. LarePass will use your phone's Bluetooth to scan for the nearby Olares device.
2. When your device appears in the list, tap **Network setup**.
3. Select the Wi-Fi network your phone is currently connected to. If it's password-protected, enter the password and tap **Confirm**.
::: tip Note
If you select a Wi-Fi network different from your phone's, LarePass will still be unable to recognize your Olares device after it connects.
If you select a Wi-Fi network different from the one your phone is on, LarePass won't be able to detect your Olares device after it connects.
:::
4. Olares will begin the network switching process. You'll see a success message when it's complete. If you return to the Bluetooth network setup page, you'll see that Olares' IP address has changed to your phone's Wi-Fi subnet.
4. Olares will start switching the network.Once the process is complete, a success message will appear. If you return to the Bluetooth network setup page, you'll see that Olares' IP address has changed to your phone's Wi-Fi subnet.
::: tip Note
The process takes longer if your Olares was activated earlier as the network switch affects more services.
:::
5. Go back to the device scan page, and you will now be able to discover your Olares device. You can now proceed with [device activation](activate-olares.md) or device management as instructed in this document.
5. Go back to the device scan page and tap **Discover nearby Olares** to find your device. You can now proceed with [device activation](activate-olares.md) or device management as instructed in this document.
## Uninstall Olares

View File

@@ -12,14 +12,12 @@ Olares's built-in Files app offers users a secure and efficient solution for fil
## Understand the interface
The interface is similar to Windows Explorer or macOS Finder, allowing you to organize and access documents, images, videos, or any other files you own.
![Files](/images/manual/olares/files.png#bordered)
![Files](/images/manual/olares/files-1.png#bordered)
It consists of three main components:
* **Drive**: For storing files that don't require frequent synchronization or modifications.
* **Sync**: For syncing files and directories across devices.
* **Application**: For development and debugging purposes only.
* **CloudDrive**: For mounting and accessing your cloud storage services including Google Drive, AWS S3, Tencent Cloud Object Storage (COS)
---
<div>
@@ -27,19 +25,9 @@ It consists of three main components:
Learn the fundamentals of file management in Olares.
</div>
<div>
<h4><a href="../../larepass/sync-share">Sync and share files</a></h4>
Learn how to keep files updated across devices, and how to share files with other Olares member.
</div>
<div>
<h4><a href="./mount-SMB">Mount SMB</a></h4>
Learn how to mount and access SMB shared folders from NAS devices or network servers in Olares.
</div>
<div>
<h4><a href="./mount-cloud-storage">Mount cloud storage</a></h4>
Learn how to mount and access third party cloud storage services in Olares
</div>

View File

@@ -21,7 +21,12 @@ Before you start, it is recommended to familiarize yourself with a few concepts
| [Dependencies](../concepts/application.md#dependencies) | Prerequisite applications that must already be<br/> installed before a user can access an application <br/>that requires them. |
## Find applications
The Olares Market offers various ways to discover and browse applications:
The Olares Market offers various ways to discover and browse applications.
![Market](/images/manual/olares/market-discover.png#bordered)
### Browse by categories
On **Discover** page:
* **Featured Applications**: Curated by the editorial team, showcasing trending and seasonally relevant apps.
@@ -30,17 +35,23 @@ On **Discover** page:
* **Latest apps**: Recently added applications to the market.
You can also browse applications based on their functionality:
* **Productivity**: Apps for work scenarios and improving efficiency.
* **Utilities**: Tools for solving specific problems or completing tasks.
* **Entertainment**: Apps for leisure and enjoyment.
* **Social network**: Platforms for connecting with others.
* **Blockchain**: Applications related to blockchain technology.
* **Recommendation**: Decentralized content recommendation algorithms for Wise.
:::info
For information on using the recommendation feature in Wise, refer to [discover themed content](./wise/recommend).
:::
* **Creativity**: Apps for creating and publishing digital content, from AI-generated art and 3D models to blogs and design projects.
* **Productivity**: Apps for team collaboration, project management, data organization, and building custom AI-powered agents.
* **Lifestyle**: Self-hosted applications for managing your smart home, personal photo libraries, and AI identity.
* **Fun**: Selfhosted applications for entertainment and fun such as gaming, video streaming, and connecting with people.
* **Utilities**: Tools for system management, file sharing, data backup, and running local AI models.
* **Developer Tools** Toolchain for the software development lifecycle, including code hosting, CI/CD, observability, and database management.
### Search using keywords
To search an app in the market:
1. Open the Market app from the Dock or Launchpad.
2. In the **Manage** sub-memu on the left, click **Search**.
2. Enter the keywords. The relevant results will appear as you type.
![Search app](/images/manual/olares/search-app.png#bordered)
![Market](/images/manual/olares/market-discover.png#bordered)
## Install applications
1. Open the Market app from the Dock or Launchpad.
@@ -77,21 +88,19 @@ To ensure a shared service is running and accessible within the cluster, follow
1. Prepare an Olares Application Chart file (in `.zip`, `.tgz`, `.tar`, or `.gz` format).
2. Open the Market app from the Dock or Launchpad.
3. Click **My Olares** > **Custom** to see all custom applications.
4. Click **Upload custom chart** and select chart files.
3. Click **My Olares** > **Local** to see all custom applications.
4. Click **Upload custom chart** in the top right corner and select the chart file to install.
## Update applications
1. Open the Market app from the Dock or Launchpad.
2. Click for update notifications besides **My Olares** from the left sidebar.
If there is an available update, you should see a label marked with number.
3. Click **My Olares** > **Available updates** to see all updatable applications.
4. Click **Update all** to update all applications at once, or update each application individually.
2. In the left sidebar, click **Updates** under the **Manage** section. If there are available updates, a notification badge will display.
3. The **Available updates** panel will display the applications with available updates.Click **Update all** to update all applications at once, or update each application individually.
## Uninstall applications
### Uninstall from Market
1. Open the Market app from the Dock or Launchpad.
2. Click **My Olares** from the left sidebar to view all installed apps.
2. In the left sidebar, navigate to the **My Olares** section. Use the **Olares** or **Local** tabs to filter and fined your installed applications.
3. Click <i class="material-symbols-outlined">keyboard_arrow_down</i> next to the application's operation button, and select **Uninstall**.
### Uninstall from Launchpad
@@ -99,6 +108,15 @@ To ensure a shared service is running and accessible within the cluster, follow
2. Click and hold the app icon until all the apps begin to jiggle.
3. Click <i class="material-symbols-outlined">cancel</i> on the app icon to uninstall it.
## View app operation logs
The application operation log details the processes and statuses of app operations within Market, such as installation, download, update, and uninstallation. To access these logs:
1. Open the Market app from the Dock or Launchpad.
2. In the left sidebar, navigate to **My Olares**.
3. Click **Logs** in the top right corner.
You can also click the <i class="material-symbols-outlined">download</i> button to download the logs.
## FAQ

View File

@@ -4,30 +4,136 @@ description: Monitor your Olares system and application performance with compreh
---
# Monitor system and application status
The Dashboard app in Olares works similarly to Windows Explorer, providing a centralized view of your system's status without requiring technical expertise. From the main dashboard, you can view resource usage patterns and detailed metrics.
:::info
When applications in your Olares are exposed to the public internet, they generate FRP traffic costs from external access. To monitor these costs and traffic, see [VIew system status](../../space/manage-olares#view-system-status).
:::
The Dashboard app in Olares provides a centralized and intuitive view of your system's status, offering deep insights without requiring extensive technical expertise. From the dashboard, you can monitor key resource usage patterns and access detailed real-time metrics across your cluster.
## Access monitoring dashboards
View your system's status through these specialized dashboards:
- **Overview**: Shows current resource usage and system health.
- **Applications**: Displays running applications and their status.
## Overview
The Overview page provides a comprehensive, at-a-glance view of your Olares system's health and resource utilization. It is divided into key sections to help you monitor performance effectively:
- Cluster's physical resources
- User resource usage
- Usage ranking
### View physical resources
Monitor four fundamental metrics directly from **Overview**:
Monitor the fundamental resource metrics directly from the **Cluster's physical resource** dashboard:
- CPU utilization
- Memory consumption
- Disk usage
- Pod status
- GPU usage
- Network status
![Dashboard overview](/images/manual/olares/dashboard-overview.png#bordered)
### Access detailed metrics
For deeper analysis, click **More details** to view comprehensive monitoring data for the past 7 days.
### Access detailed resource panels
For a deeper analysis of any resource, simply click on its card on the **Cluster's physical resources** dashboard. This navigates you to a dedicated detail panel with comprehensive monitoring data and metrics.
#### CPU panel
The CPU panel provides an in-depth view of your Olares cluster's CPU performance and health.
To access it, click on the **CPU** card on the **Cluster's physical resources** dashboard.
![CPU panel](/images/manual/olares/dashboard-cpu.png#bordered)
This panel displays:
- A real-time CPU utilization graph.
- Node-specific CPU specifications (model, cores, threads).
- Breakdown of utilization rate (User, System, I/O wait).
- Current CPU temperature.
- Average load over 1, 5, and 15 minutes.
#### Memory panel
The Memory panel offers a clear, in-depth view of your Olares cluster's memory usage and allocation. To access it, click on the **Memory** card on the **Cluster's physical resources** dashboard.
This panel allows you to switch between **Physical memory** and **Swap** views using the dropdown menu.
![Memory panel](/images/manual/olares/dashboard-memory.png#bordered)
- When **Physical memory** is selected, it displays:
- A real-time memory utilization graph.
- A memory usage breakdown showing reserved, used, buffer, cache, and available memory, along with total memory and utilization rate.
- When **Swap** is selected, it displays:
- A real-time swap usage graph.
- Numerical swap in/out rates.
- Swap space summary (Total, Used, and Utilization rate).
#### Disk panel
The Disk panel offers a comprehensive view of your storage devices. Use this panel to monitor disk health, track storage consumption, and analyze space allocation in your Olares cluster.
To access it, click on the **Disk** card on the **Cluster's physical resources** dashboard.
![Disk panel](/images/manual/olares/dashboard-disk.png#bordered)
This panel displays:
- Overall storage status: Disk name, storage status, and a usage bar showing used, and available space.
- Detailed information: Key device specifications like total capacity, model, serial number, interface protocol, temperature, power-on time, and write volume.
For a detailed usage breakdown for a specific storage device, click **Occupancy analysis** in the top right corner.
The storage usage popup displays:
![Disk analysis](/images/manual/olares/dashboard-disk-analysis.png#bordered)
- A list of file systems (partitions) on the disk.
- For each file system, you can view storage metrics like total capacity, used space, available space, usage rate, and mount point.
#### Pods panel
The Pods panel offers a dynamic view of your application's deployment status.
To access it, click the **Pods** card on the **Cluster's physical resources** dashboard.
![Pods panel](/images/manual/olares/dashboard-pods.png#bordered)
This panel displays real-time graphs showing the number of running pods over time for different nodes in the cluster. (e.g., "Olares" and "Olares2").
#### GPU panel
The **GPU** panel provides in-depth information about your GPUs within the cluster. Use this panel to effectively monitor GPU health, resource allocation, and performance across your cluster.
To access it, click the GPU card on the **Cluster's physical resources** dashboard.
![GPU panel](/images/manual/olares/dashboard-gpu-overview.png#bordered)
This panel includes two tabs:
- **Graphics management tab**: View a list of all detected GPUs, including their GPU ID, model, GPU mode (e.g., Memory Slicing), host node, health status, computing power usage, VRAM usage rate, and power draw.
For a more granular view of a specific GPU, click **View details** next to its entry.
- **Task management tab**: Monitor tasks currently using your GPUs. It provides insights into the task name, status, GPU Mode, host node, computing power usage, and VRAM used, along with available operations.
#### Network panel
The Network panel provides comprehensive insights into your network interfaces. Use this panel to monitor network connectivity, traffic flow, and configuration for optimal system performance.
To access it, click the **Network** card on the **Overview** dashboard.
![Network panel](/images/manual/olares/dashboard-network.png#bordered)
The Network panel displays:
- Network port information: Details for each network port (e.g., wlo1), including its usage status, real-time upload and download speeds, and connection status.
- IP configuration: Information on IP acquisition method (e.g., DHCP), host node, and network configuration.
- IPv4 and IPv6 details: Comprehensive details for both IPv4 and IPv6, including address, subnet mask, gateway address, DNS, and network status.
#### Access detailed resource metrics
Click **More details** on the top right of the **Overview** dashboard to view dynamic monitoring data over a specific period of time.
Use the dropdown menu in the top right to change the time range, or click <i class="material-symbols-outlined">refresh</i> to update monitoring data.
@@ -46,7 +152,8 @@ The following metrics help you maintain optimal system performance:
| Pod status | Count of pods by state | Reflects application health |
![Physical resource monitoring](/images/manual/olares/physical-resource-monitoring.png#bordered)
### Check resource quota
### Check user resource quota
You can view your resource quota allocated by the Olares admin.
![Resource quota](/images/manual/olares/resource-quota.png#bordered)

View File

@@ -9,7 +9,7 @@ Olares' backup feature lets you create full and incremental backups for specifie
To add a backup task:
1. Go to **Settings Backup**, and click **Add backup task**.
1. Go to **Settings** **Backup**, and click **Add backup**.
2. Choose **Backup files** or **Backup applications**.
3. On the **Add backup task** page, configure the following options:

View File

@@ -13,6 +13,10 @@ A reverse proxy acts as a secure gateway between your Olares and the open web, e
## Change your reverse proxy option
To change your reverse proxy option:
![Change reverse proxy](/images/manual/olares/set-reverse-proxy.png#bordered)
1. Open Settings, then navigate to **Network** > **Reverse Proxy**.
2. Choose your preferred reverse proxy option. If you select Self-built FRP, youll need to provide the server address, port, and authentication method.

View File

@@ -34,34 +34,38 @@ For community applications, you can quickly obtain a simple and memorable URL by
4. Next to **Set custom Route ID**, click <i class="material-symbols-outlined">add</i>.
5. Enter a route ID that is more memorable and recognizable. For example, `jellyfin`.
![Custom route ID](/images/manual/olares/custom-route-id.png#bordered)
![Custom route ID](/images/manual/olares/custom-route-id.jpeg#bordered)
6. Click **Confirm**.
Now, you will be able to access Jellyfin from your new URL: `https://jellyfin.bob.olares.com`.
### Custom domain name
Instead of using the default Olares domain, you can use your own domain name to access your applications, making them more professional and easier to remember. To use Affine as an example:
Instead of using the default Olares domain, you can use your own domain name to access your applications, making them more professional and easier to remember. To configure a custom domain name for an app:
:::info
Only applications with the authentication level set to **Internal** or **Public** support custom third-party domains.
:::
1. Open the Settings app, and select **Application** from the left sidebar.
2. Click Affine on the right to view application details.
3. Go to **Entrances** > **Set up endpoint**.
4. Next to **Set custom domain**, click <i class="material-symbols-outlined">add</i>.
![Set third-party domain](/images/manual/olares/set-custom-domain.png#bordered)
5. Enter your custom domain, for example, `hello.coffee`, and click **Confirm**.
6. Click **Activation**, and follow the instructions to add a CNAME record on your domain hosting site. Then click **Confirm**.
![Activate third-party domain](/images/manual/olares/activate-custom-domain.png#bordered)
At this stage, the custom domain status will display as "Waiting for CNAME Activation". This means you need to wait for the DNS changes to propagate. The propagation time typically ranges from a few minutes to 48 hours, depending on your domain provider.
Olares will periodically check if the DNS record is correctly configured. Once the CNAME record is verified, the custom domain status will automatically update to "Activated". After activation, you can access Affine using the new URL: `hello.coffee`.
:::tip
To allow public access to your custom domain without login, update the access policies as below:
1. Navigate to **Settings** > **Application**, and click the target application.
2. Click **Entrance**, then under **Create access policies**, set **Authentication level** to **Public**.
3. Click **Submit** to apply changes.
2. Click the application you want to configure to enter its details page.
3. Go to **Entrances** > **Set up endpoint**, and click <i class="material-symbols-outlined">add</i> next to **Set custom domain**.
4. In the **Third-party domain** pop-up, enter your custom domain, and click **Confirm** to submit.
![Submit third-party domain](/images/manual/olares/add-custom-domain.jpeg#bordered)
::: tip Note
If you are using Olares Tunnel or Self-built FRP for reverse proxy, you must also upload a valid HTTPS certificate and its private key for your custom domain.
:::
![Set auth level to public](/images/manual/olares/set-auth-level-to-public.png){width=50%}
:::
5. Click the **Activation** button to open the activation instruction pop-up.
![Activate third-party domain](/images/manual/olares/activate-custom-domain.jpeg#bordered)
6. Follow the instructions in the pop-up to create a CNAME record with your domain hosting provider.
![Add CNAME](/images/manual/olares/add-cname.jpeg#bordered)
:::tip Disable Proxy status for Cloudflare Tunnel
If you are using Cloudflare Tunnel, disable the **Proxy status** option next to your DNS record. This allows Olares to receive in-time updates on your domain's resolution status.
:::
7. Click **Confirm** on the activation popup window to finish the activation.
At this stage, the custom domain status will display as "Waiting for CNAME Activation". You will need to wait for it to take effect. DNS propagation typically takes a few minutes or hours, depending on your domain provider.
Once the CNAME record is verified, the custom domain status will automatically update to "Activated".

View File

@@ -30,8 +30,6 @@ Olares supports manual configuration of AWS S3 and Tencent Cloud COS using API c
- Bucket name
4. Click **Next**. You will see a success message if the credentials are valid.
Your connected cloud storage will now appear under the **Cloud storage** section in Files.
Alternatively, you can configure this direction directly within [LarePass](../../larepass/integrations.md#add-a-cloud-storage-using-api-keys).

View File

@@ -3,7 +3,7 @@ outline: [2, 3]
description: Learn how to manage your Olares account, devices, security settings, and network access policies in My Olares.
---
# Account and device management
# My Olares overview
The **My Olares** page in **Settings** serves as your central hub for managing your Olares account, connected devices, security settings, and access policies.

View File

@@ -6,19 +6,7 @@ description: Learn how to configure VPN on Olares using Settings, covering VPN e
The [LarePass VPN](../../larepass/private-network.md) provides secure remote access to your Olares device, even when you're on a different network or at a remote location. Olares' Settings app offers advanced configurations to tailor VPN access to your specific needs. Here, you can enforce VPN connections, enable SSH access over VPN, or route traffic through custom ports.
## Enforce access using VPN
To ensure that all traffic to your private Olares applications is encrypted and routed securely, you can enforce VPN access. This ensures that connections to your Olares always go through the LarePass VPN, regardless of the network or device used. Enabling this mode will block accesses to Olares via reverse proxy.
To enable the enforced VPN mode:
1. Enable VPN connections on at least two devices using LarePass (typically a computer and a mobile phone) with LarePass installed. For detailed instructions, see [Enable VPN on LarePass](/manual/larepass/private-network.md).
2. Open Settings app from the Dock or Launchpad.
3. Click on your profile picture in the top-left corner, and scroll down to **Security** settings.
4. Turn on the switch for **Enforce VPN access to private entrance**.
When successful, you'll see a confirmation message at the bottom of the screen.
![VPN](/images/manual/olares/vpn.png#bordered)
## Allow SSH connections via VPN
This enables SSH access to your Olares device through the LarePass VPN, even when you are in a different network or working remotely.
@@ -26,13 +14,25 @@ This enables SSH access to your Olares device through the LarePass VPN, even whe
1. Open the Settings app, and select **System** > **VPN**.
2. Toggle on **Allow SSH Access via VPN**. Port **22** (SSH) is automatically added to the configuration.
![SSH via VPN](/images/manual/olares/ssh-via-vpn.png#bordered)
## Allow subnet routing
This feature allows you to access other devices in the same local network as your Olares through the VPN.
1. Open the Settings app, and select **System** > **VPN**.
2. Toggle on **Enable subnet routes**.
## Enforce access using VPN
To ensure that all traffic to your private Olares applications is encrypted and routed securely, you can enforce VPN access. This ensures that connections to your Olares always go through the LarePass VPN, regardless of the network or device used. Enabling this mode will block accesses to Olares via reverse proxy.
To enable the enforced VPN mode:
1. Enable VPN connections on at least two devices using LarePass (typically a computer and a mobile phone) with LarePass installed. For detailed instructions, see [Enable VPN on LarePass](/manual/larepass/private-network.md).
2. In Olares, navigate to **Settings** > **VPN**.
3. Toggle on **Enforce VPN access to private entrance**.
When successful, you'll see a confirmation message at the bottom of the screen.
## Configure ACL rules for port access
After enabling subnet routing, you can further configure ACL (Access Control List) rules to allow traffic to specific ports based on the services you want to access.
@@ -41,6 +41,4 @@ For example, to access a Windows server via Remote Desktop:
2. Enter `3389` (default port for Remote Desktop Protocol), and click **Confirm**.
3. Click **Apply** to apply changes.
![Add ACL port](/images/manual/olares/add-acl-port.png#bordered)
Now you can use Windows Remote Desktop to access the Windows server in the same LAN as Olares.

View File

@@ -6,11 +6,11 @@ description: Configure and manage your Olares hosts file to customize domain nam
The hosts file is a system configuration file that maps domain names to specific IP addresses. By editing this file, you can customize how Olares resolves domain names, bypass the default DNS resolution, and control access to certain websites or services.
## Add a host
To add a new domain name and IP address mapping in Olares:
![Add a host](/images/manual/olares/add-host.png#bordered)
1. Open Settings, and go to **System** > **Hosts**.
2. Select **Add hosts** in the top-right corner, and specify the domain name/IP address pair.
- **Host name**: Enter the domain name you want to map (e.g., `example.com`).
- **IP**: Enter the corresponding IP address (e.g., `93.184.216.34`).
![Add a host](/images/manual/olares/add-host.png#bordered)
3. Click **Confirm** to save the changes.
:::info DNS cache delay

View File

@@ -1,10 +1,7 @@
---
description: Learn about Olares, an open-source sovereign cloud OS for local AI. Discover how to self-host services, run AI applications, manage files, and collaborate securely with enterprise-grade features.
---
# Olares documentation<Badge type="warning">Dev</Badge>
::: warning Note on Dev version
This documentation provides a preview of features for an upcoming Olares version. As this is not a stable release, the features and user interface described here may be unstable, incomplete, and are subject to change.
:::
# Olares documentation
## What is Olares?
@@ -28,7 +25,7 @@ Olares comprises the following core components:
- [**Olares OS**](https://github.com/beclab/Olares): An open-source, self-hosted operating system that transforms edge devices into robust personal cloud.
- [**LarePass**](./larepass): A secure, cross-platform client that bridges you and your Olares system. It provides seamless access, unified identity management, fast file synchronization, and comprehensive device management across all your devices.
- [**LarePass**](./larepass/): A secure, cross-platform client that bridges you and your Olares system. It provides seamless access, unified identity management, fast file synchronization, and comprehensive device management across all your devices.
## Highlighted features

1354
docs/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@
"preview": "vitepress preview"
},
"devDependencies": {
"mermaid": "10.9.3",
"mermaid": "11.9.0",
"terser": "^5.14.2",
"vitepress": "1.6.3",
"vitepress-plugin-mermaid": "2.0.17"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Some files were not shown because too many files have changed in this diff Show More