Compare commits

...

103 Commits

Author SHA1 Message Date
eball
f692d1ea02 ci: bump version to 1.12.1 2025-07-30 21:01:30 +08:00
eball
fe86ef0190 Update release.yaml 2025-07-30 20:48:40 +08:00
eball
ba13d6092b hami: sync hami-core 2.6.0 (#1646) 2025-07-30 20:05:42 +08:00
dkeven
8180024d6d fix(upgrade): split olares version update and upgrade of settings chart (#1647)
* fix(upgrade): split olares version update and upgrade of settings chart

* feat: upgrade l4-proxy image to v0.3.2

* fix: update appservice tag

---------

Co-authored-by: hys <hysyeah@gmail.com>
2025-07-30 20:04:46 +08:00
dkeven
c05f82c4bb fix(cli): trucate file before untar (#1644) 2025-07-30 13:52:30 +08:00
Calvin W.
604b2191ce docs: optimize doc structure to fix redundant or out-dated topics (#1643)
* docs: update readme structure

* revert format change

* add personal cloud image for jp

* docs: optimize toc to remove redundant content

* Revert wrong pull
2025-07-30 13:44:01 +08:00
hysyeah
518d2a41ea app-service: fix user sync error (#1639)
* app-service: fix user sync error

* fix: update app-service tag

* Update appservice_deploy.yaml

---------

Co-authored-by: eball <liuy102@hotmail.com>
2025-07-30 02:56:23 +08:00
berg
bf292e2f55 feat: update system frontend and user service version (#1642) 2025-07-30 01:15:17 +08:00
eball
896c6d76f9 cli: fix the installation in oic on Windows (#1636) 2025-07-30 01:14:00 +08:00
Calvin W.
ee4655d991 docs: update screenshots for GPU management (#1641) 2025-07-29 21:33:24 +08:00
Calvin W.
261bf0f9e0 docs: update the new upgrade process using LarePass (#1640)
* docs: update the new upgrade process using LarePass

* optimize images
2025-07-29 21:33:19 +08:00
dkeven
48776c32bf fix(upgrade): switch upgrader for 0728 to 0729 (#1638) 2025-07-29 13:51:16 +08:00
dkeven
9bbf270eb3 fix(gpu): revert buggy code change from upstream (#1637) 2025-07-29 13:50:50 +08:00
eball
bab83ed0b3 Update release-daily.yaml 2025-07-29 10:03:37 +08:00
wiy
62faa3e3b7 system-frontend,user-service: remove studio from system-frontend and fix some bugs (#1635)
* system-frontend,user-service: remove studio from system-frontend and fix some bugs

* fix: remove studio server

---------

Co-authored-by: hys <hysyeah@gmail.com>
2025-07-29 00:26:54 +08:00
hysyeah
e9346f04c1 sys-event: fix publish user resource usage error (#1634) 2025-07-29 00:25:57 +08:00
dkeven
1df5121a4e feat(upgrade): add upgrade tasks for K3s and GPU plugin (#1633)
* feat: add task to upgrade k3s

* feat: add task to upgrade GPU plugin
2025-07-29 00:25:30 +08:00
dkeven
2ecfc976d7 fix(gpu): update hami version to avoid nil pointer panic (#1632) 2025-07-29 00:24:54 +08:00
Sai
c38e00a825 fix: market service bug in 0.4.13 (#1631)
fix bugs
- after account create, chart repo miss notify
- i18n data in app data
- rebuild app info when chart repo restart
- entrances, options data
2025-07-29 00:24:21 +08:00
Calvin W.
8c801b8392 docs: update user management docs (#1630) 2025-07-29 00:23:44 +08:00
dkeven
eaceeef30b feat: upgrade Kubernetes to v1.33.3 (#1629) 2025-07-29 00:23:11 +08:00
dkeven
339b375a89 fix(upgrade): wait for user to finish activation before upgrading (#1628) 2025-07-29 00:22:33 +08:00
salt
b5b9d19bc3 feat: add producer, consumer watch (#1627)
Co-authored-by: ubuntu <you@example.com>
2025-07-27 01:53:13 +08:00
wiy
0bcb2cd893 system-frontend: fix 1.12 files some bugs (#1626)
* feat(system-frontend): release new version to fix some bugs

* fix(system-frontend): fix some system-frontend bugs
2025-07-27 01:52:44 +08:00
aby913
2b46e87baa fix(backup): nats service check (#1625) 2025-07-26 00:28:43 +08:00
hysyeah
d0351aed9c node_exporter, app-service: exclude virtual disk like qemu;use new chart repo;set values fs_type (#1624)
node_exporter: exclude virtual disk like qemu;use new chart repo;set values fs_type
2025-07-26 00:28:08 +08:00
dkeven
021338b4b7 feat(daemon): make upgrade download progress more smooth (#1623) 2025-07-25 20:49:45 +08:00
eball
d374133dd4 lldap, authelia: sign a 2fa token from lldap after larepass signed (#1622) 2025-07-25 20:48:49 +08:00
dkeven
c330589424 feat(cli): inject rootfs type to global envs (#1620) 2025-07-25 20:47:07 +08:00
dkeven
a690b5a852 fix(ci): specify arch variant in goreleaser override config (#1621) 2025-07-25 17:50:32 +08:00
dkeven
abc6bc01a6 feat(gpu): force out app exclusively bound to GPU (#1619) 2025-07-25 17:49:23 +08:00
eball
a0513a8e6f fix: self-signed certificate with a long expiration (#1614)
* fix: self-signed certificate with a long expiration

* Update auth_backend_deploy.yaml
2025-07-25 00:36:11 +08:00
wiy
b61a3233bb notification-api,user-service,system-frontend: fix notification error & fix system-frontend bugs (#1617) 2025-07-25 00:16:41 +08:00
hysyeah
5b3072dc6f app-service: fix somebug and optimize image download speed (#1616)
app-service: optimize image download speed
2025-07-25 00:16:04 +08:00
dkeven
2cc580a453 feat(daemon): add API to confirm upgrade after download (#1615) 2025-07-25 00:05:18 +08:00
Sai
3e63c3f34c feat:add dynamic chart repository (#1613)
* add dynamic chart repository

* add image info to api install

* add entrance info in app data
2025-07-25 00:04:35 +08:00
dkeven
d80fbfb5e5 fix(cli): make the timer for renewing K8s certs persistent (#1612) 2025-07-25 00:03:29 +08:00
dkeven
cea8f8bd1b refactor(ci): merge archs in olaresd's goreleaser config (#1611) 2025-07-24 18:01:52 +08:00
dkeven
7cce5ec761 fix(daemon): optimize disk space and node health check before upgrade (#1610) 2025-07-24 15:55:43 +08:00
dkeven
b705bb0814 feat(cli): download wizard from different vendor path (#1609) 2025-07-24 15:55:21 +08:00
eball
7fcfb2139b Update deps-manifest.sh 2025-07-24 12:11:04 +08:00
eball
f267639a82 Update build.sh 2025-07-24 11:59:25 +08:00
eball
42a10225cc Update build.sh 2025-07-24 11:42:29 +08:00
eball
39e3d453e2 bfl, authelia: fix internal mode and get real ip (#1608) 2025-07-24 00:53:50 +08:00
hysyeah
96334c89af app-service,user-service: fix wehbook,uninstall bug; user-service nats auth error (#1607) 2025-07-24 00:52:51 +08:00
0x7fffff92
eb774e6e06 fix: make the affinity rule strict for tailscale (#1606)
fix: requires tailscale and headscale to run on the same node

Co-authored-by: 0x7fffff92 <0x7fffff92@example.com>
2025-07-24 00:52:11 +08:00
aby913
8be967ebf3 fix(backup): wise svc upgrade (#1605) 2025-07-24 00:51:33 +08:00
yyh
8f2a98745a fix(monitoring-server): update monitoring server role management (#1604) 2025-07-24 00:51:08 +08:00
dkeven
e7303b0554 feat: upgrade containerd to v2.1.3 (#1603) 2025-07-24 00:50:35 +08:00
Peng Peng
9aee9453fc notification,user-service,wizard: update notification (#1602)
* feat(notification): update notification to support sign second verification on LarePass

* system-frontend,wizard,user-service: fix some bugs and user-service update notification

---------

Co-authored-by: qq815776412 <815776412@qq.com>
2025-07-24 00:47:39 +08:00
Calvin W.
c480beb4de docs: update screenshots for install wizards and login (#1600)
* docs: update screenshots for install wizards and login

* optimize images
2025-07-23 19:31:51 +08:00
eball
8998dd48cf tapr: add the svc of postgres for the shared system app (#1599)
tapr: add the svc of the postgres for the shared system app
2025-07-23 19:31:04 +08:00
hysyeah
ed3713bd37 app-service: support v2 install;operate app by crd;user event publish to nats (#1597) 2025-07-23 00:57:30 +08:00
wiy
47bd343c6b vault-server,vault-admin,system-frontend: update system-frontend some bugs (#1596) 2025-07-23 00:56:57 +08:00
aby913
931f2992f4 fix(backup): add check disk space (#1595) 2025-07-23 00:56:27 +08:00
aby913
b3d8a2e718 fix(files): update global external data on mount (#1594) 2025-07-23 00:56:02 +08:00
eball
0e2a5d7c0e bfl: add files api routing to settings (#1593) 2025-07-23 00:55:29 +08:00
dkeven
3035453f8c feat: add vendor type to olares-cli/olaresd (#1592) 2025-07-23 00:55:01 +08:00
eball
267d92607c hami: fix null poimter in hami-core 2025-07-22 23:05:31 +08:00
dkeven
dce43cd081 fix(daemon): do not set download state again after completion (#1591) 2025-07-22 21:33:34 +08:00
salt
3826c64e48 fix: fix inotify race (#1590)
Co-authored-by: ubuntu <you@example.com>
2025-07-22 21:32:55 +08:00
dkeven
e398150e01 fix(daemon): do not clear upgrade state file when upgrading is in progress (#1589) 2025-07-22 21:32:28 +08:00
eball
694c472aad app-service: add workflow label to the namespace of workeflow (#1588) 2025-07-22 01:18:18 +08:00
eball
62db7fe18a bfl: remove token auth from ingress (#1587) 2025-07-22 00:24:07 +08:00
wiy
7e1674aa77 system-frontend&files-server: release new version to fix some bugs (#1586)
* feat(system-frontend): update system-frontend new version

* fix(files): add master node info

* feat(search): update search3 version to v0.0.59

---------

Co-authored-by: aby913 <aby913@163.com>
2025-07-22 00:23:30 +08:00
hysyeah
72d804b0c9 authelia, lldap: fix login failed after reset password within one second (#1585) 2025-07-22 00:23:02 +08:00
dkeven
a91b20b7a0 feat(daemon): optimize and add new params to the upgrade feature (#1584) 2025-07-22 00:22:38 +08:00
Peng Peng
fa92825ce9 feat: add intent sub pub on market and user-service (#1583)
* feat: add intent sub pub on market and user-service

* Update system-frontend.yaml
2025-07-20 22:03:07 +08:00
dkeven
0e04f416d7 Revert "feat(ci): retrieve and save uncompressed size of layers in image manifest (#1570) (#1582)
Revert "feat(ci): retrieve and save uncompressed size of layers in image manifest (#1570)"

This reverts commit d4a1a44e39.
2025-07-20 22:02:07 +08:00
Peng Peng
e43055b0f3 feat(docs): Remove knowledge, rsshub and argowoflow infomation from Readme (#1581)
Update README.md
2025-07-20 22:01:34 +08:00
Peng Peng
f918614bd2 feat: add notification support (#1579)
* feat: add notification support

* Update system-frontend.yaml

* Update check.yaml

* Update check.yaml

---------

Co-authored-by: eball <liuy102@hotmail.com>
2025-07-20 00:21:26 +08:00
eball
12f19b7d46 app-service: add runAsInternal option and multi-admin supported in v1 package (#1576)
app-service: add runAsInternal option and v1 package multi-admin supported
2025-07-19 12:14:17 +08:00
berg
5c8f3ea2ff system-frontend: move socket to sharedworker and fix some ui bugs (#1578)
* feat: update system-frontend version

* feat: update version
2025-07-19 09:27:24 +08:00
aby913
9b7635f244 fix(backup): replace node name for External path (#1577) 2025-07-19 09:26:52 +08:00
dkeven
a949e317ac perf(ci): use skopeo to upload image archive to cdn (#1572) 2025-07-19 09:26:24 +08:00
0x7fffff92
f362396514 fix: nftables only for owner (#1571)
* fix: nftables only for owner

* typo

---------

Co-authored-by: 0x7fffff92 <0x7fffff92@example.com>
2025-07-19 09:25:55 +08:00
dkeven
d4a1a44e39 feat(ci): retrieve and save uncompressed size of layers in image manifest (#1570) 2025-07-19 09:23:38 +08:00
Peng Peng
95fdffb24f feat(docs): update config to support search (#1573) 2025-07-18 21:52:25 +08:00
wiy
4c72114a4d dashboard&settings&desktop&backup&user-service: fix some bugs and add backup nats message (#1569)
* fix(backup): use nats to push messages

* feat: update user-service version and support backup nas

* dashboard&desktop&settings: fix some bugs

---------

Co-authored-by: aby913 <aby913@163.com>
Co-authored-by: icebergtsn <zyh2433219116@gmail.com>
2025-07-18 00:42:04 +08:00
dkeven
e28371551b feat(gpu): update metrics API for HAMi-WebUI and library for HAMi (#1568) 2025-07-18 00:41:21 +08:00
hysyeah
ef01c331e9 app-service, lldap: fix admin reset password;refresh token expiry (#1567) 2025-07-18 00:40:33 +08:00
dkeven
40b29d12d6 feat(ci): record cdn object file size in manifest (#1566) 2025-07-18 00:39:51 +08:00
dkeven
506bd3bc1d fix(daemon): filter out invalid IPs when getting host IP (#1563)
* fix(daemon): filter out invalid IPs when getting host IP

* fix: node ip check bug

* fix: remove log

* fix: check master node

---------

Co-authored-by: eball <liuy102@hotmail.com>
2025-07-18 00:37:38 +08:00
dkeven
9d097f77b1 feat(cli): adjust release line constraint and output order of upgrade path command (#1561)
* fix(cli): consider alpha & beta as release version on main line

* fix(cli): dont allow upgrade commands with incompatible base & cli release line

* feat(cli): support order sort option for upgrade path command
2025-07-18 00:36:57 +08:00
Calvin W.
a71b536a80 Docs: revert search provider to agolia (#1564)
* docs: revert search mode to agolia and fix formats

* update repo link

* update style reference page link
2025-07-17 15:22:30 +08:00
Calvin W.
8eb2d86f56 docs: fix use case link on main (#1565) 2025-07-17 15:22:06 +08:00
Calvin W.
ea0404fe2b docs: add readme for docs repo (#1562)
* docs: add readme for docs repo

* fix sentence style heading

* change search provider to local
2025-07-17 14:37:07 +08:00
Peng Peng
af8e3b172c feat: add docs to main (#1559) 2025-07-17 11:58:59 +08:00
wiy
e00018de59 system-frontend&market: release new version (#1558)
* feat: update market backend version

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

---------

Co-authored-by: icebergtsn <zyh2433219116@gmail.com>
2025-07-17 01:06:27 +08:00
hysyeah
6bba107fdd app-service: correct entrance status;workflow install (#1557) 2025-07-16 23:45:16 +08:00
dkeven
ffb96bcbfc fix(cli): check emptiness of user and domain before write release file (#1556) 2025-07-16 23:44:34 +08:00
salt
a6e4a73af2 fix: get ctime error (#1555)
Co-authored-by: ubuntu <you@example.com>
2025-07-16 23:43:48 +08:00
dkeven
61d3dedbfd fix(cli): bump helm version to v3.18.4 (#1554) 2025-07-16 19:04:30 +08:00
hysyeah
962e251691 bfl, studio, tapr, authelia: fit new user owner role (#1551)
* bfl, studio, tapr: fit new user owner role

* fix: tailscale index

* fix: l4 proxy version
2025-07-16 01:10:05 +08:00
eball
b37adf2521 daemon: change api cors module and signature validating (#1552) 2025-07-16 00:09:07 +08:00
salt
460603ae69 fix: invalid path clean watch error (#1550)
Update search3_server_deploy.yaml
2025-07-16 00:08:33 +08:00
lovehunter9
1197860c29 fix: files sync paste dir out bug (#1549) 2025-07-16 00:07:39 +08:00
dkeven
417c4b520b fix(cli): make sure hostname resolvable before running olaresd (#1548) 2025-07-16 00:06:47 +08:00
eball
e1fa887e6c bfl: change ingress default domain (#1547) 2025-07-16 00:06:10 +08:00
dkeven
b2e84cfd21 cli(refactor): new structure for upgrade (#1546) 2025-07-16 00:05:09 +08:00
wiy
e8f0054b4f fix(user-service): config redis host error (#1545)
* fix(user-service): config redis host error

* feat(user-service): update user password
fix(wizard): Fixed the issue of sub-account activation failure
feat(vault-server): update get olares name timeout to 60s
2025-07-16 00:04:22 +08:00
eball
cd6c89f724 Update checkjws.go 2025-07-15 22:21:12 +08:00
eball
3d3d85ca3e Update checkjws.go 2025-07-15 22:05:44 +08:00
1182 changed files with 43178 additions and 2144 deletions

View File

@@ -3,8 +3,12 @@ name: Lint and Test Charts
on:
push:
branches: [ "main", "release-*" ]
paths-ignore:
- 'docs/**'
pull_request_target:
branches: [ "main", "release-*" ]
paths-ignore:
- 'docs/**'
workflow_dispatch:
@@ -55,7 +59,7 @@ jobs:
steps:
- id: generate
run: |
v=1.12.0-$(echo $RANDOM)
v=1.12.1-$(echo $RANDOM$RANDOM)
echo "version=$v" >> "$GITHUB_OUTPUT"
upload-cli:
@@ -99,6 +103,12 @@ jobs:
runs-on: [self-hosted, linux, ARM64]
steps:
- name: Install skopeo (Ubuntu)
run: |
sudo apt-get update
sudo apt-get install -y skopeo
- name: 'Checkout source code'
uses: actions/checkout@v3
with:

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:
@@ -129,7 +129,7 @@ jobs:
release:
needs: [daily-version, upload-package]
needs: [daily-version, upload-package, release-cli]
runs-on: ubuntu-latest
steps:

View File

@@ -59,8 +59,46 @@ jobs:
export PATH=$PATH:/usr/local/bin:/home/ubuntu/.local/bin
bash build/image-manifest.sh && bash build/upload-images.sh .manifest/images.mf linux/arm64
push-deps:
needs: [release-daemon]
runs-on: ubuntu-latest
steps:
- name: "Checkout source code"
uses: actions/checkout@v3
# test
- env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: "us-east-1"
VERSION: ${{ github.event.inputs.tags }}
REPO_PATH: '${{ secrets.REPO_PATH }}'
run: |
bash build/deps-manifest.sh && bash build/upload-deps.sh
push-deps-arm64:
needs: [release-daemon]
runs-on: [self-hosted, linux, ARM64]
steps:
- name: "Checkout source code"
uses: actions/checkout@v3
# test
- env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: "us-east-1"
VERSION: ${{ github.event.inputs.tags }}
REPO_PATH: '${{ secrets.REPO_PATH }}'
run: |
export PATH=$PATH:/usr/local/bin:/home/ubuntu/.local/bin
bash build/deps-manifest.sh linux/arm64 && bash build/upload-deps.sh linux/arm64
upload-package:
needs: [push, push-arm64, release-daemon]
needs: [push, push-arm64, push-deps, push-deps-arm64, release-daemon]
runs-on: ubuntu-latest
steps:
@@ -85,7 +123,7 @@ jobs:
release:
runs-on: ubuntu-latest
needs: [upload-package]
needs: [upload-package, release-cli]
steps:
- name: 'Checkout source code'

5
.gitignore vendored
View File

@@ -32,3 +32,8 @@ olares-cli-*.tar.gz
cli/output
daemon/output
daemon/bin
docs/.vitepress/dist/
docs/.vitepress/cache/
node_modules
.idea/

View File

@@ -113,7 +113,7 @@ This section lists the main directories in the Olares repository:
* **[`apps`](./apps)**: Contains the code for system applications, primarily for `larepass`.
* **[`cli`](./cli)**: Contains the code for `olares-cli`, the command-line interface tool for Olares.
* **[`daemon`](./daemon)**: Contains the code for `olaresd`, the system daemon process.
* **`docs`**: Contains documentation for the project.
* **[`docs`](./docs)**: Contains documentation for the project.
* **[`framework`](./framework)**: Contains the Olares system services.
* **[`infrastructure`](./infrastructure)**: Contains code related to infrastructure components such as computing, storage, networking, and GPUs.
* **[`platform`](./platform)**: Contains code for cloud-native components like databases and message queues.

View File

@@ -115,7 +115,7 @@ Olares 代码库中的主要目录如下:
* **[`apps`](./apps)**: 用于存放系统应用,主要是 `larepass` 的代码。
* **[`cli`](./cli)**: 用于存放 `olares-cli`Olares 的命令行界面工具)的代码。
* **[`daemon`](./daemon)**: 用于存放 `olaresd`(系统守护进程)的代码。
* **`docs`**: 用于存放 Olares 项目的文档。
* **[`docs`**](./docs)**: 用于存放 Olares 项目的文档。
* **[`framework`](./framework)**: 用来存放 Olares 系统服务代码。
* **[`infrastructure`](./infrastructure)**: 用于存放计算存储网络GPU 等基础设施的代码。
* **[`platform`](./platform)**: 用于存放数据库、消息队列等云原生组件的代码。

View File

@@ -108,14 +108,13 @@ Olaresは以下のLinuxプラットフォームで動作検証を完了してい
自分のデバイスでOlaresを始めるには、[はじめにガイド](https://docs.olares.com/manual/get-started/)に従ってステップバイステップの手順を確認してください。
## プロジェクトナビゲーション
## プロジェクトナビゲーションx
このセクションでは、Olares リポジトリ内の主要なディレクトリをリストアップしています:
* **[`apps`](./apps)**: システムアプリケーションのコードが含まれており、主に `larepass` 用です。
* **[`cli`](./cli)**: Olares のコマンドラインインターフェースツールである `olares-cli` のコードが含まれています。
* **[`daemon`](./daemon)**: システムデーモンプロセスである `olaresd` のコードが含まれています。
* **`docs`**: プロジェクトのドキュメントが含まれています。
* **[`docs`](./docs)**: プロジェクトのドキュメントが含まれています。
* **[`framework`](./framework)**: Olares システムサービスが含まれています。
* **[`infrastructure`](./infrastructure)**: コンピューティング、ストレージ、ネットワーキング、GPU などのインフラストラクチャコンポーネントに関連するコードが含まれています。
* **[`platform`](./platform)**: データベースやメッセージキューなどのクラウドネイティブコンポーネントのコードが含まれています。

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,26 +0,0 @@
apiVersion: v2
name: studio
description: A Terminus app development tool
maintainers:
- name: bytetrade
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.3
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "4.9.1"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 749 KiB

View File

@@ -1,13 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: studio-server
namespace: user-space-{{ .Values.bfl.username }}
spec:
type: ExternalName
externalName: studio-server.os-framework.svc.cluster.local
ports:
- protocol: TCP
name: studio-server
port: 8080
targetPort: 8080

View File

@@ -1,42 +0,0 @@
bfl:
nodeport: 30883
nodeport_ingress_http: 30083
nodeport_ingress_https: 30082
username: 'test'
url: 'test'
nodeName: test
pvc:
userspace: test
userspace:
userData: test/Home
appData: test/Data
appCache: test
dbdata: test
docs:
nodeport: 30881
desktop:
nodeport: 30180
os:
portfolio:
appKey: '${ks[0]}'
appSecret: test
vault:
appKey: '${ks[0]}'
appSecret: test
desktop:
appKey: '${ks[0]}'
appSecret: test
message:
appKey: '${ks[0]}'
appSecret: test
rss:
appKey: '${ks[0]}'
appSecret: test
search:
appKey: '${ks[0]}'
appSecret: test
studio:
appKey: '${ks[0]}'
appSecret: test
kubesphere:
redis_password: ""

View File

@@ -1,4 +1,5 @@
{{- $namespace := printf "%s%s" "user-system-" .Values.bfl.username -}}
{{- $userspacenamespace := printf "%s%s" "user-space-" .Values.bfl.username -}}
{{- $zinc_files_secret := (lookup "v1" "Secret" $namespace "zinc-files-secrets") -}}
{{- $user_service_secret := (lookup "v1" "Secret" $namespace "user-service-secrets") -}}
@@ -50,7 +51,7 @@
{{ $user_service_redis_password = randAlphaNum 16 | b64enc }}
{{- end -}}
{{- $user_service_nats_secret := (lookup "v1" "Secret" $namespace "user-service-nats-secret") -}}
{{- $user_service_nats_secret := (lookup "v1" "Secret" $userspacenamespace "user-service-nats-secret") -}}
{{- $nats_password := "" -}}
{{ if $user_service_nats_secret -}}
{{ $nats_password = (index $user_service_nats_secret "data" "nats_password") }}
@@ -165,19 +166,6 @@ spec:
---
apiVersion: v1
kind: Service
metadata:
name: studio-svc
namespace: {{ .Release.Namespace }}
spec:
selector:
app: system-frontend
ports:
- protocol: TCP
port: 8080
targetPort: 87
---
apiVersion: v1
kind: Service
metadata:
name: files-fe-service
namespace: user-space-{{ .Values.bfl.username }}
@@ -246,11 +234,11 @@ metadata:
applications.app.bytetrade.io/group: 'true'
applications.app.bytetrade.io/author: bytetrade.io
annotations:
applications.app.bytetrade.io/icon: '{"dashboard":"https://file.bttcdn.com/appstore/dashboard/icon.png","control-hub":"https://file.bttcdn.com/appstore/control-hub/icon.png","profile":"https://file.bttcdn.com/appstore/profile/icon.png","headscale": "https://file.bttcdn.com/appstore/headscale/icon.png","settings": "https://file.bttcdn.com/appstore/settings/icon.png","studio":"https://file.bttcdn.com/appstore/devbox/icon.png","files":"https://file.bttcdn.com/appstore/files/icon.png","vault":"https://file.bttcdn.com/appstore/vault/icon.png","market":"https://file.bttcdn.com/appstore/appstore/icon.png"}'
applications.app.bytetrade.io/title: '{"dashboard": "Dashboard","control-hub":"Control Hub","profile":"Profile","headscale":"Headscale","settings":"Settings","studio":"Studio","files":"Files","vault":"Vault","market":"Market"}'
applications.app.bytetrade.io/version: '{"dashboard": "0.0.1","control-hub":"0.0.1","profile":"0.0.1","headscale":"0.0.1","settings":"0.0.1","studio":"0.0.1","files":"0.0.1","vault":"0.0.1","market":"0.0.1"}'
applications.app.bytetrade.io/icon: '{"dashboard":"https://file.bttcdn.com/appstore/dashboard/icon.png","control-hub":"https://file.bttcdn.com/appstore/control-hub/icon.png","profile":"https://file.bttcdn.com/appstore/profile/icon.png","headscale": "https://file.bttcdn.com/appstore/headscale/icon.png","settings": "https://file.bttcdn.com/appstore/settings/icon.png","files":"https://file.bttcdn.com/appstore/files/icon.png","vault":"https://file.bttcdn.com/appstore/vault/icon.png","market":"https://file.bttcdn.com/appstore/appstore/icon.png"}'
applications.app.bytetrade.io/title: '{"dashboard": "Dashboard","control-hub":"Control Hub","profile":"Profile","headscale":"Headscale","settings":"Settings","files":"Files","vault":"Vault","market":"Market"}'
applications.app.bytetrade.io/version: '{"dashboard": "0.0.1","control-hub":"0.0.1","profile":"0.0.1","headscale":"0.0.1","settings":"0.0.1","files":"0.0.1","vault":"0.0.1","market":"0.0.1"}'
applications.app.bytetrade.io/policies: '{"dashboard":{"policies":[{"entranceName":"dashboard","uriRegex":"/js/script.js", "level":"public"},{"entranceName":"dashboard","uriRegex":"/js/api/send", "level":"public"}]}}'
applications.app.bytetrade.io/entrances: '{"dashboard":[{"name":"dashboard","host":"dashboard-service","port":80,"title":"Dashboard","windowPushState":true}],"control-hub":[{"name":"control-hub","host":"control-hub-service","port":80,"title":"Control Hub","windowPushState":true}],"profile":[{"name":"profile", "host":"profile-service", "port":80,"title":"Profile","windowPushState":true}],"headscale":[{"name":"headscale", "host":"headscale-svc", "port":80,"title":"Headscale","invisible": true}],"settings":[{"name":"settings", "host":"settings-service", "port":80,"title":"Settings"}],"studio":[{"name":"studio","host":"studio-svc","port":8080,"title":"Studio","openMethod":"window"}],"files":[{"name":"files", "host":"files-fe-service", "port":80,"title":"Files","windowPushState":true}],"vault":[{"name":"vault", "host":"vault-service", "port":80,"title":"Vault","windowPushState":true}],"market":[{"name":"appstore", "host":"appstore-fe-service", "port":80,"title":"Market","windowPushState":true}]}'
applications.app.bytetrade.io/entrances: '{"dashboard":[{"name":"dashboard","host":"dashboard-service","port":80,"title":"Dashboard","windowPushState":true}],"control-hub":[{"name":"control-hub","host":"control-hub-service","port":80,"title":"Control Hub","windowPushState":true}],"profile":[{"name":"profile", "host":"profile-service", "port":80,"title":"Profile","windowPushState":true}],"headscale":[{"name":"headscale", "host":"headscale-svc", "port":80,"title":"Headscale","invisible": true}],"settings":[{"name":"settings", "host":"settings-service", "port":80,"title":"Settings"}],"files":[{"name":"files", "host":"files-fe-service", "port":80,"title":"Files","windowPushState":true}],"vault":[{"name":"vault", "host":"vault-service", "port":80,"title":"Vault","windowPushState":true}],"market":[{"name":"appstore", "host":"appstore-fe-service", "port":80,"title":"Market","windowPushState":true}]}'
spec:
replicas: 1
selector:
@@ -345,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.102
image: beclab/system-frontend:v1.3.116
imagePullPolicy: IfNotPresent
command:
- /bin/sh
@@ -458,7 +446,7 @@ spec:
value: os.market.{{ .Values.bfl.username}}
- name: NATS_SUBJECT_APPLICATION
value: os.application.{{ .Values.bfl.username}}
- name: NATS_SUBJECT_NOTIFICATION
- name: NATS_SUBJECT_USER_NOTIFICATION
value: os.notification.{{ .Values.bfl.username}}
- name: NATS_SUBJECT_FILES
value: os.files.{{ .Values.bfl.username}}
@@ -467,7 +455,7 @@ spec:
- name: NATS_SUBJECT_VAULT
value: os.vault.{{ .Values.bfl.username}}
- name: user-service
image: beclab/user-service:v0.0.21
image: beclab/user-service:v0.0.41
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3000
@@ -525,7 +513,7 @@ spec:
value: os.market.{{ .Values.bfl.username}}
- name: NATS_SUBJECT_APPLICATION
value: os.application.{{ .Values.bfl.username}}
- name: NATS_SUBJECT_NOTIFICATION
- name: NATS_SUBJECT_USER_NOTIFICATION
value: os.notification.{{ .Values.bfl.username}}
- name: NATS_SUBJECT_FILES
value: os.files.{{ .Values.bfl.username}}
@@ -533,13 +521,17 @@ spec:
value: os.knowledge.{{ .Values.bfl.username}}
- name: NATS_SUBJECT_VAULT
value: os.vault.{{ .Values.bfl.username}}
- name: NATS_SUBJECT_BACKUP
value: os.backup.{{ .Values.bfl.username}}
- name: NATS_SUBJECT_INTENT
value: os.intent.{{ .Values.bfl.username}}
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
key: redis_password
name: user-service-secrets
- name: REDIS_HOST
value: redis-cluster-proxy.user-system-guotest334
value: redis-cluster-proxy.user-system-{{ .Values.bfl.username }}
- name: REDIS_PORT
value: '6379'
@@ -1026,31 +1018,6 @@ status:
---
apiVersion: sys.bytetrade.io/v1alpha1
kind: ApplicationPermission
metadata:
name: studio
namespace: user-system-{{ .Values.bfl.username }}
spec:
app: studio
appid: studio
key: {{ .Values.os.studio.appKey }}
secret: {{ .Values.os.studio.appSecret }}
permissions:
- dataType: app
group: service.appstore
ops:
- InstallDevApp
- UninstallDevApp
version: v1
- dataType: legacy_api
group: api.intent
ops:
- POST
version: v2
status:
state: active
---
apiVersion: sys.bytetrade.io/v1alpha1
kind: ApplicationPermission
metadata:
name: settings
namespace: user-system-{{ .Values.bfl.username }}
@@ -2175,5 +2142,13 @@ spec:
permission:
sub: allow
pub: allow
- name: "backup.*"
permission:
sub: allow
pub: allow
- name: "intent.*"
permission:
sub: allow
pub: allow
user: user-service-{{ .Values.bfl.username }}

View File

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

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.1-0

View File

@@ -76,7 +76,7 @@ Create the name of the service account to use
{{- $caCertEnc = index $prevSecret "data" "ca.crt" }}
{{- else }}
{{- $altNames := list ( printf "%s-webhook.%s" (include "opentelemetry-operator.fullname" .) .Release.Namespace ) ( printf "%s-webhook.%s.svc" (include "opentelemetry-operator.fullname" .) .Release.Namespace ) -}}
{{- $tmpperioddays := 3650 }}
{{- $tmpperioddays := 36500 }}
{{- $ca := genCA "opentelemetry-operator-operator-ca" $tmpperioddays }}
{{- $cert := genSignedCert (include "opentelemetry-operator.fullname" .) nil $altNames $tmpperioddays $ca }}
{{- $certCrtEnc = b64enc $cert.Cert }}

View File

@@ -1,12 +1,14 @@
# chart-testing: ignore-file
{{ $cluster_id := randAlphaNum 16 }}
{{ $version := "#__VERSION__" }}
{{ if .Values.cluster_id }}
{{ $cluster_id = .Values.cluster_id }}
{{ end }}
{{ $cr := (lookup "sys.bytetrade.io/v1alpha1" "terminus.sys.bytetrade.io" "" "terminus") }}
{{ $cr := (lookup "sys.bytetrade.io/v1alpha1" "Terminus" "" "terminus") }}
{{ if $cr }}
{{ $cluster_id = (index $cr "metadata" "labels" "bytetrade.io/cluster-id") }}
{{ $version = (index $cr "spec" "version") }}
{{ end }}
---
@@ -22,7 +24,7 @@ metadata:
bytetrade.io/s3-sk: '{{ .Values.s3_sk }}'
spec:
name: terminus-1
version: #__VERSION__
version: {{ .Values.version | default $version }}
display: Terminus One
releaseServer:
serverType: github

View File

@@ -9,6 +9,21 @@ import json
CDN_URL = "https://dc3p1870nn3cj.cloudfront.net"
def get_file_size(objectid, fileid):
url = f"{CDN_URL}/{objectid}"
try:
response = requests.head(url)
response.raise_for_status()
content_length = response.headers.get('Content-Length')
if content_length:
return int(content_length)
else:
print(f"Content-Length header missing for {fileid} from {url}", file=sys.stderr)
sys.exit(1)
except requests.RequestException as e:
print(f"Error getting file size for {fileid} from {url}: {e}", file=sys.stderr)
sys.exit(1)
def download_checksum(name):
"""Downloads the checksum for a given name."""
url = f"{CDN_URL}/{name}.checksum.txt"
@@ -74,13 +89,17 @@ def main():
checksum_amd64 = download_checksum(url_amd64)
checksum_arm64 = download_checksum(url_arm64)
file_size_amd64 = get_file_size(url_amd64, fileid)
file_size_arm64 = get_file_size(url_arm64, fileid)
manifest_amd64_data[filename] = {
"type": "component",
"path": path,
"deps": deps,
"url_amd64": url_amd64,
"checksum_amd64": checksum_amd64,
"fileid": fileid
"fileid": fileid,
"size": file_size_amd64,
}
@@ -90,7 +109,8 @@ def main():
"deps": deps,
"url_arm64": url_arm64,
"checksum_arm64": checksum_arm64,
"fileid": fileid
"fileid": fileid,
"size": file_size_arm64,
}
except FileNotFoundError:
@@ -115,6 +135,9 @@ def main():
checksum_amd64 = download_checksum(name)
checksum_arm64 = download_checksum(f"arm64/{name}")
file_size_amd64 = get_file_size(url_amd64, line)
file_size_arm64 = get_file_size(url_arm64, line)
# Get the image manifest
image_manifest_amd64 = get_image_manifest(name)
image_manifest_arm64 = get_image_manifest(f"arm64/{name}")
@@ -127,6 +150,7 @@ def main():
"url_amd64": url_amd64,
"checksum_amd64": checksum_amd64,
"fileid": line,
"size": file_size_amd64,
"manifest": image_manifest_amd64
}
@@ -137,6 +161,7 @@ def main():
"url_arm64": url_arm64,
"checksum_arm64": checksum_arm64,
"fileid": line,
"size": file_size_arm64,
"manifest": image_manifest_arm64
}

View File

@@ -5,6 +5,22 @@ rm -rf ${BASE_DIR}/../.dist
DIST_PATH="${BASE_DIR}/../.dist/install-wizard"
export VERSION=$1
# vendor replace
if [[ "${REPO_PATH}" != "" && "$REPO_PATH" != "/" ]]; then
path="vendor${REPO_PATH}"
echo "replace vendor path: ${path}"
find ${BASE_DIR}/../$path -type f | while read l;
do
file=$(awk -F "$path" '{print $1$2}' <<< "$l")
if [[ "$file" != ".gitkeep" ]]; then
echo "replace [$file] with [$l]"
cp -f "$l" "$file"
fi
done
fi
DIST_PATH=${DIST_PATH} bash ${BASE_DIR}/package.sh
bash ${BASE_DIR}/image-manifest.sh
@@ -43,7 +59,6 @@ else
VERSION="debug"
fi
$TAR --exclude=wizard/tools --exclude=.git -zcvf ${BASE_DIR}/../install-wizard-${VERSION}.tar.gz .
popd

View File

@@ -20,6 +20,21 @@ function get_key(){
fi
}
# vendor replace
if [[ "${REPO_PATH}" != "" && "$REPO_PATH" != "/" ]]; then
path="vendor${REPO_PATH}"
echo "replace vendor path: ${path}"
find ${BASE_DIR}/../$path -type f | while read l;
do
file=$(awk -F "$path" '{print $1$2}' <<< "$l")
if [[ "$file" != ".gitkeep" ]]; then
echo "replace [$file] with [$l]"
cp -f "$l" "$file"
fi
done
fi
find $BASE_DIR/../ -type f -name Olares.yaml | while read f; do
echo "Processing $f"
declare -a bins

View File

@@ -17,8 +17,7 @@ cat $1|while read image; do
code=$(curl -o /dev/null -fsSLI -w "%{http_code}" https://dc3p1870nn3cj.cloudfront.net/$path$name.tar.gz)
if [ $code -eq 403 ]; then
set -ex
docker pull $image
docker save $image -o $name.tar
skopeo copy --insecure-policy docker://$image oci-archive:$name.tar
gzip $name.tar
md5sum $name.tar.gz > $checksum
@@ -51,8 +50,7 @@ cat $1|while read image; do
code=$(curl -o /dev/null -fsSLI -w "%{http_code}" https://dc3p1870nn3cj.cloudfront.net/$path$checksum)
if [ $code -eq 403 ]; then
set -ex
docker pull $image
docker save $image -o $name.tar
skopeo copy --insecure-policy docker://$image oci-archive:$name.tar
gzip $name.tar
md5sum $name.tar.gz > $checksum

View File

@@ -27,6 +27,14 @@ builds:
- -s
- -w
- -X github.com/beclab/Olares/cli/version.VERSION={{ .Version }}
- >-
{{- if index .Env "OLARES_VENDOR_TYPE" }}
-X github.com/beclab/Olares/cli/version.VENDOR={{ .Env.OLARES_VENDOR_TYPE }}
{{- end }}
- >-
{{- if index .Env "OLARES_VENDOR_REPO_PATH" }}
-X github.com/beclab/Olares/cli/version.VENDOR_REPO_PATH={{ .Env.OLARES_VENDOR_REPO_PATH }}
{{- end }}
dist: ./output
archives:
- id: olares-cli

View File

@@ -10,6 +10,7 @@ type CliDownloadWizardOptions struct {
KubeType string
BaseDir string
DownloadCdnUrl string
UrlOverride string
}
func NewCliDownloadWizardOptions() *CliDownloadWizardOptions {
@@ -21,6 +22,7 @@ func (o *CliDownloadWizardOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVarP(&o.BaseDir, "base-dir", "b", "", "Set Olares package base dir, defaults to $HOME/"+cc.DefaultBaseDir)
cmd.Flags().StringVar(&o.KubeType, "kube", "k3s", "Set kube type, e.g., k3s or k8s")
cmd.Flags().StringVar(&o.DownloadCdnUrl, "download-cdn-url", "", "Set the CDN accelerated download address in the format https://example.cdn.com. If not set, the default download address will be used")
cmd.Flags().StringVar(&o.UrlOverride, "url-override", "", "Set another URL for wizard download explicitly")
}
type CliDownloadOptions struct {

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,11 +1,18 @@
package os
import (
"log"
"encoding/json"
"fmt"
"github.com/Masterminds/semver/v3"
"github.com/beclab/Olares/cli/cmd/ctl/options"
"github.com/beclab/Olares/cli/pkg/phase"
"github.com/beclab/Olares/cli/pkg/pipelines"
"github.com/beclab/Olares/cli/pkg/upgrade"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"log"
"os"
"slices"
)
type UpgradeOsOptions struct {
@@ -31,6 +38,49 @@ func NewCmdUpgradeOs() *cobra.Command {
}
o.UpgradeOptions.AddFlags(cmd)
cmd.AddCommand(NewCmdUpgradePrecheck())
cmd.AddCommand(NewCmdGetUpgradePath())
return cmd
}
func NewCmdGetUpgradePath() *cobra.Command {
var baseVersionStr string
var latestFirst bool
cmd := &cobra.Command{
Use: "path",
Short: "Get the upgrade path (required intermediate versions) from base version to the latest upgradable version (as known to this release of olares-cli)",
RunE: func(cmd *cobra.Command, args []string) error {
var baseVersion *semver.Version
var err error
if baseVersionStr == "" {
baseVersionStr, err = phase.GetOlaresVersion()
if err != nil {
return errors.New("failed to get current Olares version, please specify the base version explicitly")
}
}
baseVersion, err = semver.NewVersion(baseVersionStr)
if err != nil {
return fmt.Errorf("invalid base version: %v", err)
}
path, err := upgrade.GetUpgradePathFor(baseVersion, nil)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
if latestFirst {
slices.Reverse(path)
}
encoder := json.NewEncoder(cmd.OutOrStdout())
encoder.SetIndent("", " ")
return encoder.Encode(path)
},
}
cmd.Flags().StringVarP(&baseVersionStr, "base-version", "b", baseVersionStr, "base version to be upgraded, defaults to the current Olares version if inside Olares cluster")
cmd.Flags().BoolVar(&latestFirst, "latest-first", true, "sort versions to put recent ones in the front")
return cmd
}

View File

@@ -10,12 +10,22 @@ import (
)
func NewDefaultCommand() *cobra.Command {
var showVendor bool
cmds := &cobra.Command{
Use: "olares-cli",
Short: "Olares Installer",
CompletionOptions: cobra.CompletionOptions{DisableDefaultCmd: true},
Version: version.VERSION,
Run: func(cmd *cobra.Command, args []string) {
if showVendor {
println(version.VENDOR)
} else {
cmd.Usage()
}
return
},
}
cmds.Flags().BoolVar(&showVendor, "vendor", false, "show the vendor type of olares-cli")
cmds.AddCommand(osinfo.NewCmdInfo())
cmds.AddCommand(os.NewOSCommands()...)

View File

@@ -22,6 +22,7 @@ require (
github.com/containerd/containerd v1.7.27
github.com/decentralized-identity/web5-go v0.25.0
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.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/google/uuid v1.6.0
@@ -46,16 +47,16 @@ require (
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.37.0
golang.org/x/term v0.31.0
golang.org/x/text v0.24.0
golang.org/x/crypto v0.39.0
golang.org/x/term v0.32.0
golang.org/x/text v0.26.0
gopkg.in/yaml.v2 v2.4.0
helm.sh/helm/v3 v3.18.1
k8s.io/api v0.33.0
k8s.io/apimachinery v0.33.0
k8s.io/cli-runtime v0.33.0
k8s.io/client-go v0.33.0
k8s.io/kubectl v0.33.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/utils v0.0.0-20241104100929-3ea5e8cea738
sigs.k8s.io/controller-runtime v0.21.0
sigs.k8s.io/kustomize/kyaml v0.19.0
@@ -93,7 +94,6 @@ require (
github.com/containerd/typeurl/v2 v2.1.1 // indirect
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
github.com/ebitengine/purego v0.8.4 // indirect
github.com/emicklei/go-restful/v3 v3.12.1 // indirect
@@ -191,9 +191,9 @@ 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.38.0 // indirect
golang.org/x/net v0.40.0 // indirect
golang.org/x/oauth2 v0.28.0 // indirect
golang.org/x/sync v0.14.0 // indirect
golang.org/x/sync v0.15.0 // indirect
golang.org/x/time v0.9.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect
@@ -202,13 +202,13 @@ require (
google.golang.org/protobuf v1.36.5 // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
k8s.io/apiextensions-apiserver v0.33.0 // indirect
k8s.io/apiserver v0.33.0 // indirect
k8s.io/component-base v0.33.0 // indirect
k8s.io/component-helpers v0.33.0 // 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/cri-api v0.27.1 // indirect
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect
oras.land/oras-go/v2 v2.5.0 // indirect
oras.land/oras-go/v2 v2.6.0 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
sigs.k8s.io/kustomize/api v0.19.0 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect

View File

@@ -538,8 +538,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
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.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
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/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=
@@ -549,8 +549,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
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.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
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/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=
@@ -564,8 +564,8 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY
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.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
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/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=
@@ -575,8 +575,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
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.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
golang.org/x/sync v0.15.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=
@@ -602,14 +602,14 @@ 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.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
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/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.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
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/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -622,8 +622,8 @@ golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapK
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.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
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=
@@ -678,38 +678,38 @@ 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=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
helm.sh/helm/v3 v3.18.1 h1:qLhXmtqXOHQb0Xv9HJolOLlah8RWbgyzt50xrtTWAlg=
helm.sh/helm/v3 v3.18.1/go.mod h1:43QHS1W97RcoFJRk36ZBhHdTfykqBlJdsWp3yhzdq8w=
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.0 h1:yTgZVn1XEe6opVpP1FylmNrIFWuDqe2H0V8CT5gxfIU=
k8s.io/api v0.33.0/go.mod h1:CTO61ECK/KU7haa3qq8sarQ0biLq2ju405IZAd9zsiM=
k8s.io/apiextensions-apiserver v0.33.0 h1:d2qpYL7Mngbsc1taA4IjJPRJ9ilnsXIrndH+r9IimOs=
k8s.io/apiextensions-apiserver v0.33.0/go.mod h1:VeJ8u9dEEN+tbETo+lFkwaaZPg6uFKLGj5vyNEwwSzc=
k8s.io/apimachinery v0.33.0 h1:1a6kHrJxb2hs4t8EE5wuR/WxKDwGN1FKH3JvDtA0CIQ=
k8s.io/apimachinery v0.33.0/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
k8s.io/apiserver v0.33.0 h1:QqcM6c+qEEjkOODHppFXRiw/cE2zP85704YrQ9YaBbc=
k8s.io/apiserver v0.33.0/go.mod h1:EixYOit0YTxt8zrO2kBU7ixAtxFce9gKGq367nFmqI8=
k8s.io/cli-runtime v0.33.0 h1:Lbl/pq/1o8BaIuyn+aVLdEPHVN665tBAXUePs8wjX7c=
k8s.io/cli-runtime v0.33.0/go.mod h1:QcA+r43HeUM9jXFJx7A+yiTPfCooau/iCcP1wQh4NFw=
k8s.io/client-go v0.33.0 h1:UASR0sAYVUzs2kYuKn/ZakZlcs2bEHaizrrHUZg0G98=
k8s.io/client-go v0.33.0/go.mod h1:kGkd+l/gNGg8GYWAPr0xF1rRKvVWvzh9vmZAMXtaKOg=
k8s.io/component-base v0.33.0 h1:Ot4PyJI+0JAD9covDhwLp9UNkUja209OzsJ4FzScBNk=
k8s.io/component-base v0.33.0/go.mod h1:aXYZLbw3kihdkOPMDhWbjGCO6sg+luw554KP51t8qCU=
k8s.io/component-helpers v0.33.0 h1:0AdW0A0mIgljLgtG0hJDdJl52PPqTrtMgOgtm/9i/Ys=
k8s.io/component-helpers v0.33.0/go.mod h1:9SRiXfLldPw9lEEuSsapMtvT8j/h1JyFFapbtybwKvU=
k8s.io/api v0.33.2 h1:YgwIS5jKfA+BZg//OQhkJNIfie/kmRsO0BmNaVSimvY=
k8s.io/api v0.33.2/go.mod h1:fhrbphQJSM2cXzCWgqU29xLDuks4mu7ti9vveEnpSXs=
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/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/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.0 h1:HiRb1yqibBSCqic4pRZP+viiOBAnIdwYDpzUFejs07g=
k8s.io/kubectl v0.33.0/go.mod h1:gAlGBuS1Jq1fYZ9AjGWbI/5Vk3M/VW2DK4g10Fpyn/0=
k8s.io/kubectl v0.33.2 h1:7XKZ6DYCklu5MZQzJe+CkCjoGZwD1wWl7t/FxzhMz7Y=
k8s.io/kubectl v0.33.2/go.mod h1:8rC67FB8tVTYraovAGNi/idWIK90z2CHFNMmGJZJ3KI=
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.5.0 h1:o8Me9kLY74Vp5uw07QXPiitjsw7qNXi8Twd+19Zf02c=
oras.land/oras-go/v2 v2.5.0/go.mod h1:z4eisnLP530vwIOUOJeBIj0aGI0L1C3d53atvCBqZHg=
oras.land/oras-go/v2 v2.6.0 h1:X4ELRsiGkrbeox69+9tzTu492FMUu7zJQW6eJU+I2oc=
oras.land/oras-go/v2 v2.6.0/go.mod h1:magiQDfG6H1O9APp+rOsvCPcW1GD2MM7vgnKY0Y+u1o=
sigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8=
sigs.k8s.io/controller-runtime v0.21.0/go.mod h1:OSg14+F65eWqIu4DceX7k/+QRAbTTvxeQSNSOQpukWM=
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=

View File

@@ -40,6 +40,7 @@ Description=Timer to renew K8S control plane certificates
[Timer]
OnCalendar=Mon *-*-* 03:00:00
Unit=k8s-certs-renew.service
Persistent=true
[Install]
WantedBy=multi-user.target
`)))

View File

@@ -23,8 +23,8 @@ import (
)
const (
DefaultK8sVersion = "v1.32.2"
DefaultK3sVersion = "v1.32.2-k3s"
DefaultK8sVersion = "v1.33.3"
DefaultK3sVersion = "v1.33.3-k3s"
DefaultKubernetesVersion = ""
DefaultKubeSphereVersion = "v3.3.0"
DefaultTokenMaxAge = 31536000

View File

@@ -256,13 +256,14 @@ type Frp struct {
}
func NewArgument() *Argument {
si := connector.GetSystemInfo()
arg := &Argument{
KsEnable: true,
KsVersion: DefaultKubeSphereVersion,
InstallPackages: false,
SKipPushImages: false,
ContainerManager: Containerd,
SystemInfo: connector.GetSystemInfo(),
SystemInfo: si,
Storage: &Storage{
StorageType: ManagedMinIO,
},
@@ -286,6 +287,7 @@ func NewArgument() *Argument {
arg.IsCloudInstance, _ = strconv.ParseBool(os.Getenv(ENV_TERMINUS_IS_CLOUD_VERSION))
arg.PublicNetworkInfo.PubliclyAccessible, _ = strconv.ParseBool(os.Getenv(ENV_PUBLICLY_ACCESSIBLE))
arg.IsOlaresInContainer = os.Getenv("CONTAINER_MODE") == "oic"
si.IsOIC = arg.IsOlaresInContainer
if err := arg.LoadReleaseInfo(); err != nil {
fmt.Printf("error loading release info: %v", err)
@@ -327,7 +329,7 @@ func (a *Argument) SaveReleaseInfo() error {
ENV_OLARES_VERSION: a.OlaresVersion,
}
if a.User != nil {
if a.User != nil && a.User.UserName != "" && a.User.DomainName != "" {
releaseInfoMap["OLARES_NAME"] = fmt.Sprintf("%s@%s", a.User.UserName, a.User.DomainName)
} else {
if util.IsExist(OlaresReleaseFile) {

View File

@@ -404,3 +404,14 @@ func (t *KillContainerdProcess) Execute(runtime connector.Runtime) error {
return nil
}
type RestartContainerd struct {
common.KubeAction
}
func (t *RestartContainerd) Execute(runtime connector.Runtime) error {
if _, err := runtime.GetRunner().SudoCmd("systemctl restart containerd", false, true); err != nil {
return errors.Wrap(errors.WithStack(err), "Failed to restart containerd")
}
return nil
}

View File

@@ -29,151 +29,27 @@ root = {{ .DataRoot }}
{{ else }}
root = "/var/lib/containerd"
{{- end }}
state = "/run/containerd"
[cgroup]
path = ""
[debug]
address = ""
format = ""
gid = 0
level = ""
uid = 0
[grpc]
address = "/run/containerd/containerd.sock"
gid = 0
max_recv_message_size = 16777216
max_send_message_size = 16777216
tcp_address = ""
tcp_tls_ca = ""
tcp_tls_cert = ""
tcp_tls_key = ""
uid = 0
[metrics]
address = ""
grpc_histogram = false
[ttrpc]
address = ""
uid = 0
gid = 0
[timeouts]
"io.containerd.timeout.shim.cleanup" = "5s"
"io.containerd.timeout.shim.load" = "5s"
"io.containerd.timeout.shim.shutdown" = "3s"
"io.containerd.timeout.task.state" = "2s"
[plugins]
[plugins."io.containerd.gc.v1.scheduler"]
deletion_threshold = 0
mutation_threshold = 100
pause_threshold = 0.02
schedule_delay = "0s"
startup_delay = "100ms"
[plugins."io.containerd.grpc.v1.cri"]
device_ownership_from_security_context = false
disable_apparmor = false
disable_cgroup = false
disable_hugetlb_controller = true
disable_proc_mount = false
disable_tcp_service = true
enable_selinux = false
enable_tls_streaming = false
enable_unprivileged_icmp = false
enable_unprivileged_ports = false
ignore_image_defined_volumes = false
max_concurrent_downloads = 3
max_container_log_line_size = 16384
netns_mounts_under_state_dir = false
restrict_oom_score_adj = false
selinux_category_range = 1024
stats_collect_period = 10
stream_idle_timeout = "4h0m0s"
stream_server_address = "127.0.0.1"
stream_server_port = "10010"
systemd_cgroup = false
tolerate_missing_hugetlb_controller = true
unset_seccomp_profile = ""
sandbox_image = "{{ .SandBoxImage }}"
[plugins."io.containerd.grpc.v1.cri".cni]
bin_dir = "/opt/cni/bin"
conf_dir = "/etc/cni/net.d"
max_conf_num = 1
conf_template = ""
[plugins."io.containerd.grpc.v1.cri".containerd]
[plugins."io.containerd.grpc.v1.cri".containerd]
default_runtime_name = "runc"
disable_snapshot_annotations = true
discard_unpacked_layers = false
ignore_rdt_not_enabled_errors = false
no_pivot = false
snapshotter = "{{ .FsType }}"
[plugins."io.containerd.grpc.v1.cri".containerd.default_runtime]
base_runtime_spec = ""
cni_conf_dir = ""
cni_max_conf_num = 0
container_annotations = []
pod_annotations = []
privileged_without_host_devices = false
runtime_engine = ""
runtime_path = ""
runtime_root = ""
runtime_type = ""
[plugins."io.containerd.grpc.v1.cri".containerd.default_runtime.options]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
base_runtime_spec = ""
cni_conf_dir = ""
cni_max_conf_num = 0
container_annotations = []
pod_annotations = []
privileged_without_host_devices = false
runtime_engine = ""
runtime_path = ""
runtime_root = ""
runtime_type = "io.containerd.runc.v2"
runtime_type = 'io.containerd.runc.v2'
sandboxer = 'podsandbox'
snapshotter = "{{ .FsType }}"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
BinaryName = ""
CriuImagePath = ""
CriuPath = ""
CriuWorkPath = ""
IoGid = 0
IoUid = 0
NoNewKeyring = false
NoPivotRoot = false
Root = ""
ShimCgroup = ""
SystemdCgroup = true
[plugins."io.containerd.grpc.v1.cri".containerd.untrusted_workload_runtime]
base_runtime_spec = ""
cni_conf_dir = ""
cni_max_conf_num = 0
container_annotations = []
pod_annotations = []
privileged_without_host_devices = false
runtime_engine = ""
runtime_path = ""
runtime_root = ""
runtime_type = ""
[plugins."io.containerd.grpc.v1.cri".containerd.untrusted_workload_runtime.options]
[plugins."io.containerd.grpc.v1.cri".image_decryption]
key_model = "node"
[plugins."io.containerd.grpc.v1.cri".registry]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
{{- if .Mirrors }}
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
@@ -201,84 +77,6 @@ state = "/run/containerd"
{{- end}}
{{- end}}
[plugins."io.containerd.internal.v1.opt"]
path = "/opt/containerd"
[plugins."io.containerd.internal.v1.restart"]
interval = "10s"
[plugins."io.containerd.internal.v1.tracing"]
sampling_ratio = 1.0
service_name = "containerd"
[plugins."io.containerd.metadata.v1.bolt"]
content_sharing_policy = "shared"
[plugins."io.containerd.monitor.v1.cgroups"]
no_prometheus = false
[plugins."io.containerd.runtime.v1.linux"]
no_shim = false
runtime = "runc"
runtime_root = ""
shim = "containerd-shim"
shim_debug = false
[plugins."io.containerd.runtime.v2.task"]
platforms = ["linux/amd64"]
sched_core = false
[plugins."io.containerd.service.v1.diff-service"]
default = ["walking"]
[plugins."io.containerd.service.v1.tasks-service"]
rdt_config_file = ""
[plugins."io.containerd.snapshotter.v1.aufs"]
root_path = ""
[plugins."io.containerd.snapshotter.v1.btrfs"]
root_path = ""
[plugins."io.containerd.snapshotter.v1.devmapper"]
async_remove = false
base_image_size = ""
discard_blocks = false
fs_options = ""
fs_type = ""
pool_name = ""
root_path = ""
[plugins."io.containerd.snapshotter.v1.native"]
root_path = ""
[plugins."io.containerd.snapshotter.v1.overlayfs"]
root_path = ""
upperdir_label = false
[plugins."io.containerd.snapshotter.v1.zfs"]
root_path = "{{ .ZfsRootPath }}"
[plugins."io.containerd.tracing.processor.v1.otlp"]
endpoint = ""
insecure = false
protocol = ""
[proxy_plugins]
[stream_processors]
[stream_processors."io.containerd.ocicrypt.decoder.v1.tar"]
accepts = ["application/vnd.oci.image.layer.v1.tar+encrypted"]
args = ["--decryption-keys-path", "/etc/containerd/ocicrypt/keys"]
env = ["OCICRYPT_KEYPROVIDER_CONFIG=/etc/containerd/ocicrypt/ocicrypt_keyprovider.conf"]
path = "ctd-decoder"
returns = "application/vnd.oci.image.layer.v1.tar"
[stream_processors."io.containerd.ocicrypt.decoder.v1.tar.gzip"]
accepts = ["application/vnd.oci.image.layer.v1.tar+gzip+encrypted"]
args = ["--decryption-keys-path", "/etc/containerd/ocicrypt/keys"]
env = ["OCICRYPT_KEYPROVIDER_CONFIG=/etc/containerd/ocicrypt/ocicrypt_keyprovider.conf"]
path = "ctd-decoder"
returns = "application/vnd.oci.image.layer.v1.tar+gzip"
`)))

View File

@@ -114,6 +114,7 @@ type SystemInfo struct {
LocalIp string `json:"local_ip"`
NatGateway string `json:"nat_gateway"`
PkgManager string `json:"pkg_manager"`
IsOIC bool `json:"is_oic,omitempty"`
}
func (s *SystemInfo) IsSupport() error {
@@ -217,7 +218,7 @@ func (s *SystemInfo) IsPveOrPveLxc() bool {
}
func (s *SystemInfo) IsWsl() bool {
return s.HostInfo.OsPlatform == common.WSL
return s.HostInfo.OsPlatform == common.WSL && !s.IsOIC
}
func (s *SystemInfo) IsRaspbian() bool {

View File

@@ -344,7 +344,7 @@ func Untar(src, dst string) error {
}
}
file, err := os.OpenFile(dstPath, os.O_CREATE|os.O_RDWR, os.FileMode(hdr.Mode))
file, err := os.OpenFile(dstPath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, os.FileMode(hdr.Mode))
if err != nil {
return err
}

View File

@@ -92,6 +92,12 @@ func (i *InstallTerminusdBinaryModule) Init() {
i.Name = "InstallOlaresdBinaryModule"
i.Desc = "Install olaresd"
updateHost := &task.LocalTask{
Name: "UpdateHosts",
Action: new(terminus.UpdateKubeKeyHosts),
Prepare: new(HostnameNotResolvable),
}
install := &task.RemoteTask{
Name: "InstallOlaresdBinary",
Desc: "Install olaresd using binary",
@@ -134,6 +140,7 @@ func (i *InstallTerminusdBinaryModule) Init() {
}
i.Tasks = []task.Interface{
updateHost,
install,
generateEnv,
generateService,

View File

@@ -0,0 +1,21 @@
package daemon
import (
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/core/connector"
"net"
)
type HostnameNotResolvable struct {
common.KubePrepare
}
func (p *HostnameNotResolvable) PreCheck(runtime connector.Runtime) (bool, error) {
ips, _ := net.LookupIP(runtime.GetSystemInfo().GetHostname())
for _, ip := range ips {
if ip.To4() != nil && ip.To4().String() == runtime.GetSystemInfo().GetLocalIp() {
return false, nil
}
}
return true, nil
}

View File

@@ -21,9 +21,11 @@ import (
_ "compress/bzip2"
"context"
"fmt"
cliversion "github.com/beclab/Olares/cli/version"
"io"
"math"
"net/http"
"net/url"
"os"
"os/exec"
"path"
@@ -330,7 +332,7 @@ func NewKubeBinary(name, arch, osType, osVersion, osPlatformFamily, version, pre
case installwizard:
component.Type = WIZARD
component.FileName = fmt.Sprintf("install-wizard-v%s.tar.gz", version)
component.Url = fmt.Sprintf("%s/install-wizard-v%s.tar.gz", component.getDownloadMirrors(downloadMirrors), version)
component.Url, _ = url.JoinPath(component.getDownloadMirrors(downloadMirrors), cliversion.VENDOR_REPO_PATH, fmt.Sprintf("install-wizard-v%s.tar.gz", version))
component.CheckSum = false
component.BaseDir = filepath.Join(prePath, fmt.Sprintf("v%s", version))
case cudakeyring: // + gpu

View File

@@ -1,6 +1,7 @@
package gpu
import (
"github.com/beclab/Olares/cli/pkg/container"
"time"
"github.com/beclab/Olares/cli/pkg/common"
@@ -174,7 +175,7 @@ func (m *RestartContainerdModule) Init() {
Prepare: &prepare.PrepareCollection{
new(ContainerdInstalled),
},
Action: new(RestartContainerd),
Action: new(container.RestartContainerd),
Parallel: false,
Retry: 1,
}

View File

@@ -290,24 +290,13 @@ type ConfigureContainerdRuntime struct {
}
func (t *ConfigureContainerdRuntime) Execute(runtime connector.Runtime) error {
if _, err := runtime.GetRunner().SudoCmd("nvidia-ctk runtime configure --runtime=containerd --set-as-default --config-source=command", false, true); err != nil {
if _, err := runtime.GetRunner().SudoCmd("nvidia-ctk runtime configure --runtime=containerd --set-as-default --config-source=file", false, true); err != nil {
return errors.Wrap(errors.WithStack(err), "Failed to nvidia-ctk runtime configure")
}
return nil
}
type RestartContainerd struct {
common.KubeAction
}
func (t *RestartContainerd) Execute(runtime connector.Runtime) error {
if _, err := runtime.GetRunner().SudoCmd("systemctl restart containerd", false, true); err != nil {
return errors.Wrap(errors.WithStack(err), "Failed to restart containerd")
}
return nil
}
type InstallPlugin struct {
common.KubeAction
}

View File

@@ -2,20 +2,19 @@ package images
import (
"fmt"
"github.com/distribution/reference"
"os"
"path/filepath"
"strings"
"time"
"github.com/containerd/containerd/pkg/cri/labels"
"github.com/containerd/containerd/reference/docker"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/core/cache"
"github.com/beclab/Olares/cli/pkg/core/connector"
"github.com/beclab/Olares/cli/pkg/core/logger"
"github.com/beclab/Olares/cli/pkg/manifest"
"github.com/beclab/Olares/cli/pkg/utils"
"github.com/containerd/containerd/pkg/cri/labels"
)
const MAX_IMPORT_RETRY int = 5
@@ -120,8 +119,13 @@ func (t *LoadImages) Execute(runtime connector.Runtime) (reserr error) {
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 %s -", imageFileName, loadParm)
loadCmd = fmt.Sprintf("gunzip -c %s | ctr -n k8s.io images import --index-name %s %s -", imageFileName, parsedRef, loadParm)
} else {
loadCmd = fmt.Sprintf("ctr -n k8s.io images import %s %s", imageFileName, loadParm)
}
@@ -157,12 +161,15 @@ func (a *PinImages) Execute(runtime connector.Runtime) error {
return nil
}
for _, ref := range manifests {
parsedRef, err := docker.ParseNormalizedNamed(ref)
parsedRef, err := reference.ParseNormalizedNamed(ref)
if err != nil {
logger.Warnf("parse image name %s error: %v, skip pinning", ref, err)
continue
}
if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("ctr -n k8s.io i label %s %s=%s", parsedRef.String(), labels.PinnedImageLabelKey, labels.PinnedImageLabelValue), false, false); err != nil {
if strings.Contains(err.Error(), "DEPRECATION") {
continue
}
// tolerate cases where some images are not found
// e.g., like in the cloud environment and some images are not in the ami
logger.Warnf("pin image %s error: %v", parsedRef.String(), err)

View File

@@ -42,5 +42,6 @@ K3S_KUBECONFIG_MODE=644
K3S_TOKEN={{ .Token }}
{{ end }}
GODEBUG=netdns=go
CATTLE_NEW_SIGNED_CERT_EXPIRATION_DAYS=36500
`)))

File diff suppressed because one or more lines are too long

View File

@@ -42,7 +42,7 @@ spec:
- --collector.netdev.address-info
- --collector.filesystem.ignored-mount-points=^/(dev|proc|sys|var/lib/docker/.+)($|/)
- --collector.filesystem.ignored-fs-types=^(autofs|binfmt_misc|cgroup|configfs|debugfs|devpts|devtmpfs|fusectl|hugetlbfs|mqueue|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|sysfs|tracefs)$
image: beclab/node-exporter:0.0.3
image: beclab/node-exporter:0.0.4
name: node-exporter
securityContext:
privileged: true

View File

@@ -8,11 +8,11 @@ import (
"github.com/beclab/Olares/cli/pkg/terminus"
)
func NewDownloadWizard(runtime *common.KubeRuntime) *pipeline.Pipeline {
func NewDownloadWizard(runtime *common.KubeRuntime, urlOverride string) *pipeline.Pipeline {
m := []module.Module{
&precheck.GreetingsModule{},
&terminus.InstallWizardDownloadModule{Version: runtime.Arg.OlaresVersion, DownloadCdnUrl: runtime.Arg.DownloadCdnUrl},
&terminus.InstallWizardDownloadModule{Version: runtime.Arg.OlaresVersion, DownloadCdnUrl: runtime.Arg.DownloadCdnUrl, UrlOverride: urlOverride},
}
return &pipeline.Pipeline{

View File

@@ -26,7 +26,7 @@ func DownloadInstallationWizard(opts *options.CliDownloadWizardOptions) error {
return fmt.Errorf("--download-cdn-url invalid")
}
p := download.NewDownloadWizard(runtime)
p := download.NewDownloadWizard(runtime, opts.UrlOverride)
if err := p.Start(); err != nil {
logger.Errorf("download wizard failed %v", err)
return err

View File

@@ -2,11 +2,10 @@ package pipelines
import (
"fmt"
"os"
"path"
"github.com/beclab/Olares/cli/pkg/upgrade"
"github.com/beclab/Olares/cli/pkg/utils"
"os"
"path"
"github.com/beclab/Olares/cli/cmd/ctl/options"
"github.com/beclab/Olares/cli/pkg/common"
@@ -40,9 +39,23 @@ func UpgradeOlaresPipeline(opts *options.UpgradeOptions) error {
return fmt.Errorf("error parsing target Olares version: %v", err)
}
if !targetVersion.GreaterThan(currentVersion) {
fmt.Printf("current version is: %s, no need to upgrade to %s\n", currentVersion.String(), opts.Version)
os.Exit(0)
upgradePath, err := upgrade.GetUpgradePathFor(currentVersion, targetVersion)
if err != nil {
return err
}
if len(upgradePath) > 1 {
fmt.Printf("unable to upgrade from %s to %s directly,\n", currentVersion, targetVersion)
if len(upgradePath) == 2 {
fmt.Printf("please upgrade to %s first!\n", upgradePath[0])
} else {
line := "please upgrade sequentially to:"
for _, u := range upgradePath[:len(upgradePath)-1] {
line += fmt.Sprintf(" %s", u)
}
line += " first!"
fmt.Println(line)
}
os.Exit(1)
}
arg := common.NewArgument()
@@ -59,9 +72,8 @@ func UpgradeOlaresPipeline(opts *options.UpgradeOptions) error {
manifest := path.Join(runtime.GetInstallerDir(), "installation.manifest")
runtime.Arg.SetManifest(manifest)
upgradeModule := &upgrade.UpgradeModule{
CurrentVersion: currentVersion,
TargetVersion: targetVersion,
upgradeModule := &upgrade.Module{
TargetVersion: targetVersion,
}
p := &pipeline.Pipeline{

View File

@@ -269,3 +269,14 @@ func getManagedMinIOAccessFlags(localIp string) (string, error) {
return fmt.Sprintf(" --storage minio --bucket http://%s:9000/%s --access-key %s --secret-key %s",
localIp, cc.OlaresDir, MinioRootUser, minioPassword), nil
}
func GetRootFSType() string {
if util.IsExist(JuiceFsServiceFile) {
return "jfs"
}
return "fs"
}
func init() {
common.TerminusGlobalEnvs["OLARES_FS_TYPE"] = GetRootFSType()
}

View File

@@ -96,7 +96,7 @@ func (u *PrepareAppValues) Execute(runtime connector.Runtime) error {
if err != nil {
return err
}
fsType := getRootFSType()
fsType := storage.GetRootFSType()
gpuType := getGpuType(u.KubeConf.Arg.GPU.Enable)
appValues := getAppSecrets(getAppPatches())

View File

@@ -33,6 +33,7 @@ type InstallWizardDownloadModule struct {
common.KubeModule
Version string
DownloadCdnUrl string
UrlOverride string
}
func (m *InstallWizardDownloadModule) Init() {
@@ -42,6 +43,7 @@ func (m *InstallWizardDownloadModule) Init() {
Action: &Download{
Version: m.Version,
DownloadCdnUrl: m.DownloadCdnUrl,
UrlOverride: m.UrlOverride,
},
Retry: 1,
}

View File

@@ -70,7 +70,7 @@ func (t *InstallOsSystem) Execute(runtime connector.Runtime) error {
},
"gpu": getGpuType(t.KubeConf.Arg.GPU.Enable),
"s3_bucket": t.KubeConf.Arg.Storage.StorageBucket,
"fs_type": getRootFSType(),
"fs_type": storage.GetRootFSType(),
common.HelmValuesKeyTerminusGlobalEnvs: common.TerminusGlobalEnvs,
common.HelmValuesKeyOlaresRootFSPath: storage.OlaresRootDir,
}
@@ -296,13 +296,6 @@ func cloudValue(cloudInstance bool) string {
return ""
}
func getRootFSType() string {
if util.IsExist(storage.JuiceFsServiceFile) {
return "jfs"
}
return "fs"
}
func getRedisPassword(client clientset.Client, runtime connector.Runtime) (string, error) {
secret, err := client.Kubernetes().CoreV1().Secrets(common.NamespaceKubesphereSystem).Get(context.Background(), "redis-secret", metav1.GetOptions{})
if err != nil {

View File

@@ -5,10 +5,12 @@ import (
"crypto/tls"
"encoding/json"
"fmt"
"github.com/beclab/Olares/cli/version"
"io/fs"
"io/ioutil"
"net"
"net/http"
"net/url"
"os"
"os/exec"
"path"
@@ -91,23 +93,24 @@ func (t *CheckKeyPodsRunning) Execute(runtime connector.Runtime) error {
logger.Debugf("skipping pod %s that's not on node %s", pod.Name, t.Node)
continue
}
if strings.HasPrefix(pod.Namespace, "user-space") ||
strings.HasPrefix(pod.Namespace, "user-system") ||
pod.Namespace == "os-platform" ||
pod.Namespace == "os-framework" {
if pod.Status.Phase != corev1.PodRunning {
return fmt.Errorf("pod %s/%s is not running", pod.Namespace, pod.Name)
if !strings.HasPrefix(pod.Namespace, "user-") && !strings.HasPrefix(pod.Namespace, "os-") {
continue
}
if pod.Status.Phase != corev1.PodRunning {
return fmt.Errorf("pod %s/%s is not running", pod.Namespace, pod.Name)
}
if len(pod.Status.ContainerStatuses) != len(pod.Spec.Containers) {
return fmt.Errorf("pod %s/%s has not started all containers yet", pod.Namespace, pod.Name)
}
for _, cStatus := range pod.Status.ContainerStatuses {
if cStatus.State.Terminated != nil && cStatus.State.Terminated.ExitCode != 0 {
return fmt.Errorf("container %s in pod %s/%s is terminated", cStatus.Name, pod.Namespace, pod.Name)
}
if len(pod.Status.ContainerStatuses) == 0 {
return fmt.Errorf("pod %s/%s has no container statuses yet", pod.Namespace, pod.Name)
if cStatus.State.Running == nil {
return fmt.Errorf("container %s in pod %s/%s is not running", cStatus.Name, pod.Namespace, pod.Name)
}
for _, cStatus := range pod.Status.ContainerStatuses {
if cStatus.State.Terminated != nil && cStatus.State.Terminated.ExitCode != 0 {
return fmt.Errorf("container %s in pod %s/%s is terminated", cStatus.Name, pod.Namespace, pod.Name)
}
if cStatus.State.Running == nil {
return fmt.Errorf("container %s in pod %s/%s is not running", cStatus.Name, pod.Namespace, pod.Name)
}
if !cStatus.Ready {
return fmt.Errorf("container %s in pod %s/%s is not ready", cStatus.Name, pod.Namespace, pod.Name)
}
}
}
@@ -154,19 +157,14 @@ type Download struct {
Version string
BaseDir string
DownloadCdnUrl string
UrlOverride string
}
func (t *Download) Execute(runtime connector.Runtime) error {
if t.KubeConf.Arg.OlaresVersion == "" {
if t.UrlOverride == "" && t.KubeConf.Arg.OlaresVersion == "" {
return errors.New("unknown version to download")
}
var fetchMd5 = fmt.Sprintf("curl -sSfL %s/install-wizard-v%s.md5sum.txt |awk '{print $1}'", t.DownloadCdnUrl, t.Version)
md5sum, err := runtime.GetRunner().Cmd(fetchMd5, false, false)
if err != nil {
return errors.New("get md5sum failed")
}
var osArch = runtime.GetSystemInfo().GetOsArch()
var osType = runtime.GetSystemInfo().GetOsType()
var osVersion = runtime.GetSystemInfo().GetOsVersion()
@@ -174,8 +172,21 @@ func (t *Download) Execute(runtime connector.Runtime) error {
var baseDir = runtime.GetBaseDir()
var prePath = path.Join(baseDir, "versions")
var wizard = files.NewKubeBinary("install-wizard", osArch, osType, osVersion, osPlatformFamily, t.Version, prePath, t.DownloadCdnUrl)
wizard.CheckMd5Sum = true
wizard.Md5sum = md5sum
if t.UrlOverride == "" {
md5URL, _ := url.JoinPath(t.DownloadCdnUrl, version.VENDOR_REPO_PATH, fmt.Sprintf("install-wizard-v%s.md5sum.txt", t.Version))
var fetchMd5 = fmt.Sprintf("curl -sSfL %s |awk '{print $1}'", md5URL)
md5sum, err := runtime.GetRunner().Cmd(fetchMd5, false, false)
if err != nil {
return errors.New("get md5sum failed")
}
wizard.CheckMd5Sum = true
wizard.Md5sum = md5sum
} else {
wizard.CheckMd5Sum = false
wizard.Url = t.UrlOverride
util.RemoveFile(wizard.Path())
}
if err := wizard.CreateBaseDir(); err != nil {
return errors.Wrapf(errors.WithStack(err), "create file %s base dir failed", wizard.FileName)

View File

@@ -0,0 +1,94 @@
package upgrade
import (
"fmt"
"github.com/Masterminds/semver/v3"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/core/connector"
"github.com/beclab/Olares/cli/pkg/core/logger"
"github.com/beclab/Olares/cli/pkg/core/task"
"os"
"strings"
)
type upgrader_1_12_0_20250702 struct {
upgraderBase
}
func (u upgrader_1_12_0_20250702) Version() *semver.Version {
return semver.MustParse("1.12.0-20250702")
}
func (u upgrader_1_12_0_20250702) PrepareForUpgrade() []task.Interface {
preTasks := []task.Interface{
&task.LocalTask{
Name: "UpdateSysctlReservedPorts",
Action: new(updateSysctlReservedPorts),
},
}
return append(preTasks, u.upgraderBase.PrepareForUpgrade()...)
}
type updateSysctlReservedPorts struct {
common.KubeAction
}
func (u *updateSysctlReservedPorts) Execute(runtime connector.Runtime) error {
const sysctlFile = "/etc/sysctl.conf"
const reservedPortsKey = "net.ipv4.ip_local_reserved_ports"
const expectedValue = "30000-32767,46800-50000"
content, err := os.ReadFile(sysctlFile)
if err != nil {
return fmt.Errorf("failed to read sysctl.conf: %v", err)
}
lines := strings.Split(string(content), "\n")
var foundKey bool
var needUpdate bool
var updatedLines []string
for _, line := range lines {
trimmedLine := strings.TrimSpace(line)
if strings.HasPrefix(trimmedLine, reservedPortsKey) {
foundKey = true
parts := strings.SplitN(trimmedLine, "=", 2)
if len(parts) == 2 {
currentValue := strings.TrimSpace(parts[1])
if currentValue != expectedValue {
logger.Infof("updating %s from %s to %s", reservedPortsKey, currentValue, expectedValue)
updatedLines = append(updatedLines, fmt.Sprintf("%s=%s", reservedPortsKey, expectedValue))
needUpdate = true
} else {
updatedLines = append(updatedLines, line)
}
} else {
updatedLines = append(updatedLines, line)
}
} else {
updatedLines = append(updatedLines, line)
}
}
if !foundKey {
logger.Infof("key %s not found in sysctl.conf, adding it", reservedPortsKey)
updatedLines = append(updatedLines, fmt.Sprintf("%s=%s", reservedPortsKey, expectedValue))
needUpdate = true
}
if needUpdate {
updatedContent := strings.Join(updatedLines, "\n")
if err := os.WriteFile(sysctlFile, []byte(updatedContent), 0644); err != nil {
return fmt.Errorf("failed to write updated sysctl.conf: %v", err)
}
if _, err := runtime.GetRunner().SudoCmd("sysctl -p", false, false); err != nil {
return fmt.Errorf("failed to reload sysctl: %v", err)
}
logger.Infof("updated and reloaded sysctl configuration")
} else {
logger.Debugf("%s already has the expected value: %s", reservedPortsKey, expectedValue)
}
return nil
}

View File

@@ -0,0 +1,50 @@
package upgrade
import (
"github.com/Masterminds/semver/v3"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/container"
"github.com/beclab/Olares/cli/pkg/core/connector"
"github.com/beclab/Olares/cli/pkg/core/task"
"github.com/beclab/Olares/cli/pkg/manifest"
)
type upgrader_1_12_0_20250723 struct {
upgraderBase
}
func (u upgrader_1_12_0_20250723) Version() *semver.Version {
return semver.MustParse("1.12.0-20250723")
}
func (u upgrader_1_12_0_20250723) PrepareForUpgrade() []task.Interface {
preTasks := []task.Interface{
&task.LocalTask{
Name: "UpgradeContainerd",
Action: new(upgradeContainerd),
},
&task.LocalTask{
Name: "RestartContainerd",
Action: new(container.RestartContainerd),
},
}
return append(preTasks, u.upgraderBase.PrepareForUpgrade()...)
}
type upgradeContainerd struct {
common.KubeAction
}
func (u *upgradeContainerd) Execute(runtime connector.Runtime) error {
m, err := manifest.ReadAll(u.KubeConf.Arg.Manifest)
if err != nil {
return err
}
action := &container.SyncContainerd{
ManifestAction: manifest.ManifestAction{
Manifest: m,
BaseDir: runtime.GetBaseDir(),
},
}
return action.Execute(runtime)
}

View File

@@ -0,0 +1,112 @@
package upgrade
import (
"fmt"
"github.com/Masterminds/semver/v3"
"github.com/beclab/Olares/cli/pkg/bootstrap/precheck"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/core/connector"
"github.com/beclab/Olares/cli/pkg/core/task"
"github.com/beclab/Olares/cli/pkg/core/util"
"github.com/beclab/Olares/cli/pkg/gpu"
k3stemplates "github.com/beclab/Olares/cli/pkg/k3s/templates"
"github.com/beclab/Olares/cli/pkg/manifest"
"github.com/beclab/Olares/cli/pkg/terminus"
"github.com/pkg/errors"
"os"
"path/filepath"
"strings"
)
type upgrader_1_12_0_20250730 struct {
upgraderBase
}
func (u upgrader_1_12_0_20250730) Version() *semver.Version {
return semver.MustParse("1.12.0-20250730")
}
func (u upgrader_1_12_0_20250730) PrepareForUpgrade() []task.Interface {
var preTasks []task.Interface
if util.IsExist(filepath.Join("/etc/systemd/system/", k3stemplates.K3sService.Name())) {
preTasks = append(preTasks,
&task.LocalTask{
Name: "UpgradeK3sBinary",
Action: new(upgradeK3sBinary),
},
&task.LocalTask{
Name: "UpdateK3sServiceEnv",
Action: new(injectK3sCertExpireTime),
},
&task.LocalTask{
Name: "RestartK3sService",
Action: &terminus.SystemctlCommand{
UnitNames: []string{common.K3s},
Command: "restart",
DaemonReloadPreExec: true,
},
},
&task.LocalTask{
Name: "WaitForKubeAPIServerUp",
Action: new(precheck.GetKubernetesNodesStatus),
Retry: 10,
Delay: 10,
})
}
return append(preTasks, u.upgraderBase.PrepareForUpgrade()...)
}
func (u upgrader_1_12_0_20250730) UpgradeSystemComponents() []task.Interface {
preTasks := []task.Interface{
&task.LocalTask{
Name: "UpgradeGPUPlugin",
Action: new(gpu.InstallPlugin),
},
}
return append(preTasks, u.upgraderBase.UpgradeSystemComponents()...)
}
type upgradeK3sBinary struct {
common.KubeAction
}
func (u *upgradeK3sBinary) Execute(runtime connector.Runtime) error {
m, err := manifest.ReadAll(u.KubeConf.Arg.Manifest)
if err != nil {
return err
}
binary, err := m.Get(common.K3s)
if err != nil {
return fmt.Errorf("get k3s binary info failed: %v", err)
}
path := binary.FilePath(runtime.GetBaseDir())
dst := filepath.Join(common.BinDir, common.K3s)
// replacing the binary does not interrupt the running k3s server
if err := runtime.GetRunner().SudoScp(path, dst); err != nil {
return errors.Wrap(errors.WithStack(err), fmt.Sprintf("upgrade k3s binary failed"))
}
if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("chmod +x %s", dst), false, false); err != nil {
return err
}
return nil
}
type injectK3sCertExpireTime struct {
common.KubeAction
}
func (u *injectK3sCertExpireTime) Execute(runtime connector.Runtime) error {
expireTimeEnv := "CATTLE_NEW_SIGNED_CERT_EXPIRATION_DAYS"
envFile := filepath.Join("/etc/systemd/system/", k3stemplates.K3sServiceEnv.Name())
content, err := os.ReadFile(envFile)
if err != nil && !os.IsNotExist(err) {
return fmt.Errorf("failed to read k3s service env file: %v", err)
}
if strings.Contains(string(content), expireTimeEnv) {
return nil
}
newContent := string(content) + fmt.Sprintf("\n%s=36500\n", expireTimeEnv)
err = os.WriteFile(envFile, []byte(newContent), 0644)
return err
}

View File

@@ -3,9 +3,10 @@ package upgrade
import (
"context"
"fmt"
"github.com/beclab/Olares/cli/pkg/core/task"
"github.com/beclab/Olares/cli/pkg/terminus"
"os"
"path"
"strings"
"time"
"github.com/beclab/Olares/cli/pkg/common"
@@ -20,11 +21,110 @@ import (
ctrl "sigs.k8s.io/controller-runtime"
)
type PrepareUserInfoForUpgrade struct {
// upgraderBase is the general-purpose upgrader implementation
// for upgrading across versions without any breaking changes.
// Other implementations of breakingUpgrader,
// targeted for versions with breaking changes,
// should use this as a base for injecting and/or rewriting specific tasks as needed
type upgraderBase struct{}
func (u upgraderBase) PrepareForUpgrade() []task.Interface {
return []task.Interface{
&task.LocalTask{
Name: "PrepareUserInfoForUpgrade",
Action: new(prepareUserInfoForUpgrade),
Retry: 5,
},
}
}
func (u upgraderBase) ClearAppChartValues() []task.Interface {
return []task.Interface{
&task.LocalTask{
Name: "ClearAppChartValues",
Action: new(terminus.ClearAppValues),
},
}
}
func (u upgraderBase) ClearBFLChartValues() []task.Interface {
return []task.Interface{
&task.LocalTask{
Name: "ClearBFLChartValues",
Action: new(terminus.ClearBFLValues),
},
}
}
func (u upgraderBase) UpdateChartsInAppService() []task.Interface {
return []task.Interface{
&task.LocalTask{
Name: "UpdateChartsInAppService",
Action: new(terminus.CopyAppServiceHelmFiles),
Retry: 5,
},
}
}
func (u upgraderBase) UpgradeUserComponents() []task.Interface {
return []task.Interface{
&task.LocalTask{
Name: "UpgradeUserComponents",
Action: new(upgradeUserComponents),
Retry: 5,
Delay: 15 * time.Second,
},
}
}
func (u upgraderBase) UpdateReleaseFile() []task.Interface {
return []task.Interface{
&task.LocalTask{
Name: "UpdateReleaseFile",
Action: new(terminus.WriteReleaseFile),
},
}
}
func (u upgraderBase) UpgradeSystemComponents() []task.Interface {
// this task updates the version in the CR
// so put this at last to make the whole pipeline
// reentrant
return []task.Interface{
&task.LocalTask{
Name: "UpgradeSystemComponents",
Action: new(upgradeSystemComponents),
Retry: 10,
Delay: 15 * time.Second,
},
}
}
func (u upgraderBase) UpdateOlaresVersion() []task.Interface {
return []task.Interface{
&task.LocalTask{
Name: "UpdateOlaresVersion",
Action: new(updateOlaresVersion),
},
}
}
func (u upgraderBase) PostUpgrade() []task.Interface {
return []task.Interface{
&task.LocalTask{
Name: "EnsurePodsUpAndRunningAgain",
Action: new(terminus.CheckKeyPodsRunning),
Delay: 15 * time.Second,
Retry: 60,
},
}
}
type prepareUserInfoForUpgrade struct {
common.KubeAction
}
func (p *PrepareUserInfoForUpgrade) Execute(runtime connector.Runtime) error {
func (p *prepareUserInfoForUpgrade) Execute(runtime connector.Runtime) error {
config, err := ctrl.GetConfig()
if err != nil {
return fmt.Errorf("failed to get rest config: %s", err)
@@ -63,7 +163,7 @@ func (p *PrepareUserInfoForUpgrade) Execute(runtime connector.Runtime) error {
return fmt.Errorf("failed to get user-space-%x: %v", user.Name, err)
}
usersToUpgrade = append(usersToUpgrade, user)
if role, ok := user.Annotations["bytetrade.io/owner-role"]; ok && role == "platform-admin" {
if role, ok := user.Annotations["bytetrade.io/owner-role"]; ok && role == "owner" {
adminUser = user.Name
}
}
@@ -79,11 +179,11 @@ func (p *PrepareUserInfoForUpgrade) Execute(runtime connector.Runtime) error {
return nil
}
type UpgradeUserComponents struct {
type upgradeUserComponents struct {
common.KubeAction
}
func (u *UpgradeUserComponents) Execute(runtime connector.Runtime) error {
func (u *upgradeUserComponents) Execute(runtime connector.Runtime) error {
config, err := ctrl.GetConfig()
if err != nil {
return fmt.Errorf("failed to get rest config: %s", err)
@@ -154,7 +254,7 @@ func (u *UpgradeUserComponents) Execute(runtime connector.Runtime) error {
}
var wizardNeedUpgrade bool
if wizardStatus, ok := user.Annotations["bytetrade.io/wizard-status"]; ok && wizardStatus == "completed" {
if wizardStatus, ok := user.Annotations["bytetrade.io/wizard-status"]; !ok || wizardStatus != "completed" {
wizardNeedUpgrade = true
}
@@ -178,11 +278,11 @@ func (u *UpgradeUserComponents) Execute(runtime connector.Runtime) error {
return nil
}
type UpgradeSystemComponents struct {
type upgradeSystemComponents struct {
common.KubeAction
}
func (u *UpgradeSystemComponents) Execute(runtime connector.Runtime) error {
func (u *upgradeSystemComponents) Execute(runtime connector.Runtime) error {
config, err := ctrl.GetConfig()
if err != nil {
return fmt.Errorf("failed to get rest config: %s", err)
@@ -223,66 +323,26 @@ func (u *UpgradeSystemComponents) Execute(runtime connector.Runtime) error {
return nil
}
type UpdateSysctlReservedPorts struct {
type updateOlaresVersion struct {
common.KubeAction
}
func (u *UpdateSysctlReservedPorts) Execute(runtime connector.Runtime) error {
const sysctlFile = "/etc/sysctl.conf"
const reservedPortsKey = "net.ipv4.ip_local_reserved_ports"
const expectedValue = "30000-32767,46800-50000"
content, err := os.ReadFile(sysctlFile)
func (u *updateOlaresVersion) Execute(runtime connector.Runtime) error {
config, err := ctrl.GetConfig()
if err != nil {
return fmt.Errorf("failed to read sysctl.conf: %v", err)
return fmt.Errorf("failed to get rest config: %s", err)
}
lines := strings.Split(string(content), "\n")
var foundKey bool
var needUpdate bool
var updatedLines []string
for _, line := range lines {
trimmedLine := strings.TrimSpace(line)
if strings.HasPrefix(trimmedLine, reservedPortsKey) {
foundKey = true
parts := strings.SplitN(trimmedLine, "=", 2)
if len(parts) == 2 {
currentValue := strings.TrimSpace(parts[1])
if currentValue != expectedValue {
logger.Infof("updating %s from %s to %s", reservedPortsKey, currentValue, expectedValue)
updatedLines = append(updatedLines, fmt.Sprintf("%s=%s", reservedPortsKey, expectedValue))
needUpdate = true
} else {
updatedLines = append(updatedLines, line)
}
} else {
updatedLines = append(updatedLines, line)
}
} else {
updatedLines = append(updatedLines, line)
}
actionConfig, settings, err := utils.InitConfig(config, common.NamespaceDefault)
if err != nil {
return err
}
ctx, cancelSettings := context.WithTimeout(context.Background(), 3*time.Minute)
defer cancelSettings()
settingsChartPath := path.Join(runtime.GetInstallerDir(), "wizard", "config", "settings")
if !foundKey {
logger.Infof("key %s not found in sysctl.conf, adding it", reservedPortsKey)
updatedLines = append(updatedLines, fmt.Sprintf("%s=%s", reservedPortsKey, expectedValue))
needUpdate = true
vals := map[string]interface{}{"version": u.KubeConf.Arg.OlaresVersion}
if err := utils.UpgradeCharts(ctx, actionConfig, settings, common.ChartNameSettings, settingsChartPath, "", common.NamespaceDefault, vals, true); err != nil {
return err
}
if needUpdate {
updatedContent := strings.Join(updatedLines, "\n")
if err := os.WriteFile(sysctlFile, []byte(updatedContent), 0644); err != nil {
return fmt.Errorf("failed to write updated sysctl.conf: %v", err)
}
if _, err := runtime.GetRunner().SudoCmd("sysctl -p", false, false); err != nil {
return fmt.Errorf("failed to reload sysctl: %v", err)
}
logger.Infof("updated and reloaded sysctl configuration")
} else {
logger.Debugf("%s already has the expected value: %s", reservedPortsKey, expectedValue)
}
return nil
}

View File

@@ -0,0 +1,23 @@
package upgrade
import (
"github.com/Masterminds/semver/v3"
"github.com/beclab/Olares/cli/pkg/core/task"
)
type upgrader interface {
PrepareForUpgrade() []task.Interface
ClearAppChartValues() []task.Interface
ClearBFLChartValues() []task.Interface
UpdateChartsInAppService() []task.Interface
UpgradeUserComponents() []task.Interface
UpdateReleaseFile() []task.Interface
UpgradeSystemComponents() []task.Interface
UpdateOlaresVersion() []task.Interface
PostUpgrade() []task.Interface
}
type breakingUpgrader interface {
upgrader
Version() *semver.Version
}

View File

@@ -0,0 +1,54 @@
package upgrade
import (
"github.com/beclab/Olares/cli/pkg/bootstrap/precheck"
"github.com/beclab/Olares/cli/pkg/manifest"
"github.com/Masterminds/semver/v3"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/core/task"
)
type Module struct {
common.KubeModule
manifest.ManifestModule
TargetVersion *semver.Version
}
func (m *Module) Init() {
m.Name = "UpgradeOlares"
u := getUpgraderByVersion(m.TargetVersion)
m.Tasks = append(m.Tasks, u.PrepareForUpgrade()...)
m.Tasks = append(m.Tasks, u.ClearAppChartValues()...)
m.Tasks = append(m.Tasks, u.ClearBFLChartValues()...)
m.Tasks = append(m.Tasks, u.UpdateChartsInAppService()...)
m.Tasks = append(m.Tasks, u.UpgradeSystemComponents()...)
m.Tasks = append(m.Tasks, u.UpgradeUserComponents()...)
m.Tasks = append(m.Tasks, u.UpdateReleaseFile()...)
m.Tasks = append(m.Tasks, u.UpdateOlaresVersion()...)
m.Tasks = append(m.Tasks, u.PostUpgrade()...)
}
type PrecheckModule struct {
common.KubeModule
}
func (m *PrecheckModule) Init() {
m.Name = "UpgradePrecheck"
checkers := []precheck.Checker{
new(precheck.MasterNodeReadyCheck),
new(precheck.RootPartitionAvailableSpaceCheck),
}
runPreChecks := &task.LocalTask{
Name: "UpgradePrecheck",
Action: &precheck.RunChecks{
Checkers: checkers,
},
}
m.Tasks = []task.Interface{
runPreChecks,
}
}

View File

@@ -1,181 +0,0 @@
package upgrade
import (
"time"
"github.com/beclab/Olares/cli/pkg/bootstrap/precheck"
"github.com/Masterminds/semver/v3"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/core/task"
"github.com/beclab/Olares/cli/pkg/terminus"
)
type UpgradeModule struct {
common.KubeModule
CurrentVersion *semver.Version
TargetVersion *semver.Version
}
var (
preTasks = []*upgradeTask{
{
Task: &task.LocalTask{
Name: "UpdateSysctlReservedPorts",
Action: new(UpdateSysctlReservedPorts),
},
Current: &explicitVersionMatcher{max: semver.New(1, 12, 0, "20250701", "")},
Target: anyVersion,
},
}
coreTasks = []*upgradeTask{
{
Task: &task.LocalTask{
Name: "PrepareUserInfoForUpgrade",
Action: new(PrepareUserInfoForUpgrade),
Retry: 5,
},
Current: atLeasVersion112,
Target: atLeasVersion112,
},
{
Task: &task.LocalTask{
Name: "ClearAppChartValues",
Action: new(terminus.ClearAppValues),
},
Current: atLeasVersion112,
Target: atLeasVersion112,
},
{
Task: &task.LocalTask{
Name: "ClearBFLChartValues",
Action: new(terminus.ClearBFLValues),
},
Current: atLeasVersion112,
Target: atLeasVersion112,
},
{
Task: &task.LocalTask{
Name: "UpdateChartsInAppService",
Action: new(terminus.CopyAppServiceHelmFiles),
Retry: 5,
},
Current: atLeasVersion112,
Target: atLeasVersion112,
},
{
Task: &task.LocalTask{
Name: "UpgradeUserComponents",
Action: new(UpgradeUserComponents),
Retry: 5,
Delay: 15 * time.Second,
},
Current: atLeasVersion112,
Target: atLeasVersion112,
},
{
Task: &task.LocalTask{
Name: "UpdateReleaseFile",
Action: new(terminus.WriteReleaseFile),
},
Current: atLeasVersion112,
Target: atLeasVersion112,
},
// this task updates the version in the CR
// so put this at last to make the whole pipeline
// reentrant
// maybe it should be put at the last of post tasks
// when post tasks are actually needed
{
Task: &task.LocalTask{
Name: "UpgradeSystemComponents",
Action: new(UpgradeSystemComponents),
Retry: 10,
Delay: 15 * time.Second,
},
Current: atLeasVersion112,
Target: atLeasVersion112,
},
{
Task: &task.LocalTask{
Name: "EnsurePodsUpAndRunningAgain",
Action: new(terminus.CheckKeyPodsRunning),
Delay: 15 * time.Second,
Retry: 60,
},
Current: atLeasVersion112,
Target: atLeasVersion112,
},
}
postTasks []*upgradeTask
)
func (m *UpgradeModule) Init() {
m.Name = "UpgradeOlares"
// calculate tasks based on version difference
tasks := m.calculateUpgradeTasks()
m.Tasks = tasks
}
func (m *UpgradeModule) calculateUpgradeTasks() []task.Interface {
var tasks []task.Interface
// for now, tasks are grouped into pre-upgrade/core-upgrade/post-upgrade tasks
// only for business logic compatibility
// they are still a normal sequence of tasks to be executed
// for the module layer
tasks = append(tasks, m.calculatePreUpgradeTasks()...)
tasks = append(tasks, m.calculateCoreUpgradeTasks()...)
tasks = append(tasks, m.calculatePostUpgradeTasks()...)
return tasks
}
func (m *UpgradeModule) getTasksToExecute(unfiltered []*upgradeTask) []task.Interface {
var filtered []task.Interface
for _, t := range unfiltered {
if t.Match(m.CurrentVersion, m.TargetVersion) {
filtered = append(filtered, t.Task)
}
}
return filtered
}
func (m *UpgradeModule) calculatePreUpgradeTasks() []task.Interface {
return m.getTasksToExecute(preTasks)
}
func (m *UpgradeModule) calculateCoreUpgradeTasks() []task.Interface {
return m.getTasksToExecute(coreTasks)
}
func (m *UpgradeModule) calculatePostUpgradeTasks() []task.Interface {
return m.getTasksToExecute(postTasks)
}
type PrecheckModule struct {
common.KubeModule
}
func (m *PrecheckModule) Init() {
m.Name = "UpgradePrecheck"
checkers := []precheck.Checker{
new(precheck.MasterNodeReadyCheck),
new(precheck.RootPartitionAvailableSpaceCheck),
}
runPreChecks := &task.LocalTask{
Name: "UpgradePrecheck",
Action: &precheck.RunChecks{
Checkers: checkers,
},
}
m.Tasks = []task.Interface{
runPreChecks,
}
}

View File

@@ -1,61 +1,168 @@
package upgrade
import (
"fmt"
"github.com/Masterminds/semver/v3"
"github.com/beclab/Olares/cli/pkg/core/task"
"github.com/beclab/Olares/cli/pkg/utils"
"github.com/beclab/Olares/cli/version"
"strings"
)
// versionMatcher checks if the specified version matches its condition
type versionMatcher interface {
Match(version *semver.Version) bool
}
type releaseLine string
// explicitVersionMatcher matches the specified version by a range of explicitly
// set version range by min/max version
// and additionally explicitly included/excluded versions
// if any type of condition is not set, that check is omitted
// i.e., if min is not set, there's no limit on the minimum version
// and if no condition is set, the matcher matches all non-nil versions
type explicitVersionMatcher struct {
min *semver.Version
max *semver.Version
include []*semver.Version
exclude []*semver.Version
}
var (
mainLine = releaseLine("main")
dailyLine = releaseLine("daily")
func (m *explicitVersionMatcher) Match(version *semver.Version) bool {
if version == nil {
return false
dailyUpgraders = []breakingUpgrader{
upgrader_1_12_0_20250702{},
upgrader_1_12_0_20250723{},
upgrader_1_12_0_20250730{},
}
for _, v := range m.include {
if v.Equal(version) {
mainUpgraders = []breakingUpgrader{}
)
func getReleaseLineOfVersion(v *semver.Version) releaseLine {
preRelease := v.Prerelease()
mainLinePrereleasePrefixes := []string{"alpha", "beta", "rc"}
if preRelease == "" {
return mainLine
}
for _, prefix := range mainLinePrereleasePrefixes {
if strings.HasPrefix(preRelease, prefix) {
return mainLine
}
}
return dailyLine
}
func check(base *semver.Version, target *semver.Version) error {
if base == nil {
return fmt.Errorf("base version is nil")
}
baseReleaseLine := getReleaseLineOfVersion(base)
cliVersion, err := utils.ParseOlaresVersionString(version.VERSION)
if err != nil {
return fmt.Errorf("invalid olares-cli version :\"%s\"", version.VERSION)
}
cliReleaseLine := getReleaseLineOfVersion(cliVersion)
if baseReleaseLine != cliReleaseLine {
return fmt.Errorf("incompatible base release line: %s and olares-cli release line: %s", baseReleaseLine, cliReleaseLine)
}
if target != nil {
if !target.GreaterThan(base) {
return fmt.Errorf("base version: %s, target version: %s, no need to upgrade", base, target)
}
targetReleaseLine := getReleaseLineOfVersion(target)
if targetReleaseLine != baseReleaseLine {
return fmt.Errorf("unable to upgrade to %s on %s release line from %s on %s release line", target, targetReleaseLine, base, baseReleaseLine)
}
switch targetReleaseLine {
case mainLine:
if !sameMajorLevelVersion(base, target) {
return fmt.Errorf("upgrade on %s rlease line can only be performed across same major level version", baseReleaseLine)
}
case dailyLine:
if !samePatchLevelVersion(base, target) {
return fmt.Errorf("upgrade on %s rlease line can only be performed across same patch version", baseReleaseLine)
}
}
if target.GreaterThan(cliVersion) {
return fmt.Errorf("target version: %s, cli version: %s, please upgrade olares-cli first!", target, cliVersion)
}
}
if base.GreaterThan(cliVersion) {
return fmt.Errorf("base version: %s, cli version: %s, please upgrade olares-cli first!", base, cliVersion)
}
return nil
}
func GetUpgradePathFor(base *semver.Version, target *semver.Version) ([]*semver.Version, error) {
if err := check(base, target); err != nil {
return nil, err
}
var path []*semver.Version
var releaseLineUpgraders []breakingUpgrader
var versionFilter func(v *semver.Version) bool
switch getReleaseLineOfVersion(base) {
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
}
return true
}
}
for _, v := range m.exclude {
if v.Equal(version) {
return false
for _, u := range releaseLineUpgraders {
v := u.Version()
if versionFilter(v) {
path = append(path, v)
}
}
if m.min != nil && version.LessThan(m.min) {
return false
if target != nil {
path = append(path, target)
}
if m.max != nil && version.GreaterThan(m.max) {
return false
return path, nil
}
func getUpgraderByVersion(target *semver.Version) upgrader {
for _, upgraders := range [][]breakingUpgrader{
dailyUpgraders,
mainUpgraders,
} {
for _, u := range upgraders {
if u.Version().Equal(target) {
return u
}
}
}
return true
return upgraderBase{}
}
// todo: do we need to check at least 1.12 in cli?
var anyVersion versionMatcher = &explicitVersionMatcher{}
var atLeasVersion112 versionMatcher = &explicitVersionMatcher{min: semver.New(1, 12, 0, "1", "")}
type upgradeTask struct {
Task task.Interface
Current versionMatcher
Target versionMatcher
func samePatchLevelVersion(a, b *semver.Version) bool {
return a.Major() == b.Major() && a.Minor() == b.Minor() && a.Patch() == b.Patch()
}
func (t *upgradeTask) Match(current, target *semver.Version) bool {
return t.Current.Match(current) && t.Target.Match(target)
func sameMajorLevelVersion(a, b *semver.Version) bool {
return a.Major() == b.Major()
}

View File

@@ -34,7 +34,7 @@ import (
const (
// CertificateValidity defines the validity for all the signed certificates generated by kubeadm
CertificateValidity = time.Hour * 24 * 365 * 10
CertificateValidity = time.Hour * 24 * 365 * 100
// CertificateBlockType is a possible value for pem.Block.Type.
CertificateBlockType = "CERTIFICATE"
rsaKeySize = 2048

View File

@@ -191,9 +191,11 @@ func CheckJWS(jws string, duration int64) (*CheckJWSResult, error) {
// Verify DID matches
if resolutionResult.Document.ID != kid {
return nil, fmt.Errorf("DID does not match")
}
sid := resolutionResult.Document.ID + resolutionResult.Document.VerificationMethod[0].ID
if sid != kid {
return nil, fmt.Errorf("DID does not match: expected %s, got % s", sid, kid)
}
}
// Get verification method
if len(resolutionResult.Document.VerificationMethod) == 0 || resolutionResult.Document.VerificationMethod[0].PublicKeyJwk == nil {
return nil, fmt.Errorf("invalid DID document: missing verification method")

4
cli/version/vendor.go Normal file
View File

@@ -0,0 +1,4 @@
package version
var VENDOR = "main"
var VENDOR_REPO_PATH = ""

View File

@@ -1,44 +1,35 @@
project_name: olaresd
builds:
- id: linux_amd64
env:
- CGO_ENABLED=1
main: ./cmd/terminusd/main.go
binary: olaresd
goarch:
- amd64
goos:
- linux
tags:
containers_image_openpgp
ldflags:
- -w
- -s
- -X 'github.com/beclab/Olares/daemon/cmd/terminusd/version.version=v{{ .Version }}'
- id: linux_arm64
env:
- env:
- CGO_ENABLED=0
# - CC=aarch64-linux-gnu-gcc
# - CXX=aarch64-linux-gnu-g++
main: ./cmd/terminusd/main.go
binary: olaresd
goarch:
- amd64
- arm64
goos:
- linux
overrides:
- goarch: amd64
goos: linux
goamd64: v1
env:
- CGO_ENABLED=1
tags:
containers_image_openpgp
ldflags:
- -w
- -s
- -X 'github.com/beclab/Olares/daemon/cmd/terminusd/version.version=v{{ .Version }}'
- >-
{{- if index .Env "OLARES_VENDOR_TYPE" }}
-X github.com/beclab/Olares/daemon/cmd/terminusd/version.VENDOR={{ .Env.OLARES_VENDOR_TYPE }}
{{- end }}
dist: output
archives:
- name_template: "olaresd-v{{ .Version }}-{{ .Os }}-{{ .Arch }}"
replacements:
linux: linux
amd64: amd64
arm64: arm64
files:
- none*
checksum:

View File

@@ -33,10 +33,12 @@ func main() {
port := 18088
var showVersion bool
var showVendor bool
klog.InitFlags(nil)
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
pflag.CommandLine.BoolVar(&showVersion, "version", false, "show olaresd version")
pflag.CommandLine.BoolVar(&showVendor, "vendor", false, "show the vendor type of olaresd")
pflag.Parse()
@@ -45,6 +47,11 @@ func main() {
return
}
if showVendor {
fmt.Println(version.VENDOR)
return
}
commands.Init()
mainCtx, cancel := context.WithCancel(context.Background())

View File

@@ -0,0 +1,3 @@
package version
var VENDOR = "main"

View File

@@ -20,8 +20,10 @@ require (
bytetrade.io/web3os/bfl v0.0.0-00010101000000-000000000000
github.com/Masterminds/semver/v3 v3.3.0
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2
github.com/beclab/Olares/cli v0.0.0-20250612062319-688c4b401082
github.com/beclab/Olares/cli v0.0.0-20250715142112-cd6c89f724b5
github.com/containerd/containerd v1.7.27
github.com/distribution/distribution/v3 v3.0.0
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
@@ -176,7 +178,7 @@ require (
golang.org/x/time v0.9.0 // indirect
golang.org/x/tools v0.26.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect
google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 // indirect
google.golang.org/grpc v1.68.1 // indirect

View File

@@ -24,8 +24,8 @@ 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/Olares/cli v0.0.0-20250612062319-688c4b401082 h1:HgUvoDR1IUx3GpFcM91KHL69dIslDzV00MN5thX3vBg=
github.com/beclab/Olares/cli v0.0.0-20250612062319-688c4b401082/go.mod h1:fJ/f0348rB+ssDIvsaPh0tPQmdFbtwY4R0qkfQuGXw0=
github.com/beclab/Olares/cli v0.0.0-20250715142112-cd6c89f724b5 h1:1wWOAV6O3D4cFaGCB3I0YTFjzYYWPj8FjnIVCvmNVZc=
github.com/beclab/Olares/cli v0.0.0-20250715142112-cd6c89f724b5/go.mod h1:fJ/f0348rB+ssDIvsaPh0tPQmdFbtwY4R0qkfQuGXw0=
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/beclab/bfl v0.3.36 h1:PgeSPGc+XoONiwFsKq9xX8rqcL4kVM1G/ut0lYYj/js=
@@ -71,10 +71,14 @@ github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5il
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/distribution/distribution/v3 v3.0.0 h1:q4R8wemdRQDClzoNNStftB2ZAfqOiN6UX90KJc4HjyM=
github.com/distribution/distribution/v3 v3.0.0/go.mod h1:tRNuFoZsUdyRVegq8xGNeds4KLjwLCRin/tTo6i1DhU=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8=
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/eball/zeroconf v0.2.1 h1:PZ89f6J2k2Z7q3oSzcZGFXJf97S7NPmj7H04ACw9v8c=
github.com/eball/zeroconf v0.2.1/go.mod h1:eIbIjGYo9sSMaKWLcveHEPRWdyblz7q9ih2R1HnNw5M=
github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw=
@@ -478,8 +482,8 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ=
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro=
google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 h1:BulPr26Jqjnd4eYDVe+YvyR7Yc2vJGkO5/0UxD0/jZU=
google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:hL97c3SYopEHblzpxRL4lSs523++l8DYxGM1FQiYmb4=
google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1:CkkIfIt50+lT6NHAVoRYEyAvQGFM7xEwXUUywFvEb3Q=
google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 h1:8ZmaLZE4XWrtU3MyClkYqqtl6Oegr3235h7jxsDyqCY=

View File

@@ -24,23 +24,31 @@ func init() {
handlers.RunCommand(handlers.PostTerminusInit, install.New))))
cmd.Post("/uninstall", handlers.RequireSignature(
handlers.WaitServerRunning(
handlers.RunCommand(handlers.PostTerminusUninstall, uninstall.New))))
handlers.RequireOwner(
handlers.WaitServerRunning(
handlers.RunCommand(handlers.PostTerminusUninstall, uninstall.New)))))
cmd.Post("/upgrade", handlers.RequireSignature(
handlers.WaitServerRunning(
handlers.RunCommand(handlers.RequestOlaresUpgrade, upgrade.NewCreateUpgradeTarget))))
handlers.RequireOwner(
handlers.WaitServerRunning(
handlers.RunCommand(handlers.RequestOlaresUpgrade, upgrade.NewCreateUpgradeTarget)))))
cmd.Delete("/upgrade", handlers.RequireSignature(
handlers.RunCommand(handlers.CancelOlaresUpgrade, upgrade.NewRemoveUpgradeTarget)))
handlers.RequireOwner(
handlers.RunCommand(handlers.CancelOlaresUpgrade, upgrade.NewRemoveUpgradeTarget))))
cmd.Post("/upgrade/confirm", handlers.RequireSignature(
handlers.RequireOwner(handlers.ConfirmOlaresUpgrade)))
cmd.Post("/reboot", handlers.RequireSignature(
handlers.WaitServerRunning(
handlers.RunCommand(handlers.PostReboot, reboot.New))))
handlers.RequireOwner(
handlers.WaitServerRunning(
handlers.RunCommand(handlers.PostReboot, reboot.New)))))
cmd.Post("/shutdown", handlers.RequireSignature(
handlers.WaitServerRunning(
handlers.RunCommand(handlers.PostShutdown, shutdown.New))))
handlers.RequireOwner(
handlers.WaitServerRunning(
handlers.RunCommand(handlers.PostShutdown, shutdown.New)))))
cmd.Post("/connect-wifi", handlers.RequireSignature(
handlers.WaitServerRunning(
@@ -50,34 +58,34 @@ func init() {
handlers.WaitServerRunning(
handlers.RunCommand(handlers.PostChangeHost, changehost.New))))
cmd.Post("/umount-usb", handlers.RequireSignature(
cmd.Post("/umount-usb", handlers.RequireLocal(
handlers.WaitServerRunning(
handlers.RunCommand(handlers.PostUmountUsb, umountusb.New))))
cmd.Post("/umount-usb-incluster", handlers.RequireSignature(
cmd.Post("/umount-usb-incluster", handlers.RequireLocal(
handlers.WaitServerRunning(
handlers.RunCommand(handlers.PostUmountUsbInCluster, umountusb.New))))
cmd.Post("/collect-logs", handlers.RequireSignature(
cmd.Post("/collect-logs", handlers.RequireLocal(
handlers.WaitServerRunning(
handlers.RunCommand(handlers.PostCollectLogs, collectlogs.New))))
cmd.Post("/mount-samba", handlers.RequireSignature(
cmd.Post("/mount-samba", handlers.RequireLocal(
handlers.WaitServerRunning(
handlers.RunCommand(handlers.PostMountSambaDriver, mountsmb.New))))
cmd.Post("/umount-samba", handlers.RequireSignature(
cmd.Post("/umount-samba", handlers.RequireLocal(
handlers.WaitServerRunning(
handlers.RunCommand(handlers.PostUmountSmb, umountsmb.New))))
cmd.Post("/umount-samba-incluster", handlers.RequireSignature(
cmd.Post("/umount-samba-incluster", handlers.RequireLocal(
handlers.WaitServerRunning(
handlers.RunCommand(handlers.PostUmountSmbInCluster, umountsmb.New))))
cmdv2 := cmd.Group("v2")
cmdv2.Post("/mount-samba", handlers.RequireSignature(
cmdv2.Post("/mount-samba", handlers.RequireLocal(
handlers.WaitServerRunning(
handlers.RunCommand(handlers.PostMountSambaDriverV2, mountsmb.New))))
klog.Info("command handlers initialized")
klog.V(8).Info("command handlers initialized")
}

View File

@@ -8,21 +8,21 @@ import (
func init() {
s := server.API
containerd := s.App.Group("containerd")
containerd.Get("/registries", handlers.RequireSignature(handlers.ListRegistries))
containerd.Get("/registries", handlers.RequireLocal(handlers.ListRegistries))
registry := containerd.Group("registry")
mirrors := registry.Group("mirrors")
mirrors.Get("/", handlers.RequireSignature(handlers.GetRegistryMirrors))
mirrors.Get("/:registry", handlers.RequireSignature(handlers.GetRegistryMirror))
mirrors.Put("/:registry", handlers.RequireSignature(handlers.UpdateRegistryMirror))
mirrors.Delete("/:registry", handlers.RequireSignature(handlers.DeleteRegistryMirror))
mirrors.Get("/", handlers.RequireLocal(handlers.GetRegistryMirrors))
mirrors.Get("/:registry", handlers.RequireLocal(handlers.GetRegistryMirror))
mirrors.Put("/:registry", handlers.RequireLocal(handlers.UpdateRegistryMirror))
mirrors.Delete("/:registry", handlers.RequireLocal(handlers.DeleteRegistryMirror))
image := containerd.Group("images")
image.Get("/", handlers.RequireSignature(handlers.ListImages))
image.Delete("/:image", handlers.RequireSignature(handlers.DeleteImage))
image.Post("/prune", handlers.RequireSignature(handlers.PruneImages))
image.Get("/", handlers.RequireLocal(handlers.ListImages))
image.Delete("/:image", handlers.RequireLocal(handlers.DeleteImage))
image.Post("/prune", handlers.RequireLocal(handlers.PruneImages))
klog.Info("containerd handlers initialized")
klog.V(8).Info("containerd handlers initialized")
}

View File

@@ -1,62 +1,28 @@
package handlers
import (
"fmt"
"github.com/beclab/Olares/daemon/pkg/cluster/state"
"net/http"
"github.com/Masterminds/semver/v3"
"github.com/beclab/Olares/daemon/pkg/cluster/state"
"github.com/beclab/Olares/daemon/pkg/commands"
"github.com/beclab/Olares/daemon/pkg/commands/upgrade"
"github.com/gofiber/fiber/v2"
"k8s.io/klog/v2"
)
type UpgradeReq struct {
Version string `json:"version"`
DownloadOnly bool `json:"downloadOnly,omitempty"` // false means download-and-upgrade
}
func (r *UpgradeReq) Check() error {
target, err := semver.NewVersion(r.Version)
if err != nil {
return fmt.Errorf("invalid target version %s: %v", r.Version, err)
}
if state.CurrentState.TerminusVersion != nil {
current, err := semver.NewVersion(*state.CurrentState.TerminusVersion)
if err != nil {
return fmt.Errorf("invalid current version %s: %v", *state.CurrentState.TerminusVersion, err)
}
if !current.LessThan(target) {
return fmt.Errorf("target version should be greater than current version: %s", *state.CurrentState.TerminusVersion)
}
}
return nil
}
func (h *Handlers) RequestOlaresUpgrade(ctx *fiber.Ctx, cmd commands.Interface) error {
var req UpgradeReq
var req state.UpgradeTarget
if err := h.ParseBody(ctx, &req); err != nil {
klog.Error("parse request error, ", err)
return h.ErrJSON(ctx, http.StatusBadRequest, err.Error())
}
if err := req.Check(); err != nil {
if err := req.IsValidRequest(); err != nil {
return h.ErrJSON(ctx, http.StatusBadRequest, err.Error())
}
upgradeReq := upgrade.UpgradeRequest{
Version: req.Version,
DownloadOnly: req.DownloadOnly,
}
if _, err := cmd.Execute(ctx.Context(), upgradeReq); err != nil {
if _, err := cmd.Execute(ctx.Context(), req); err != nil {
return h.ErrJSON(ctx, http.StatusBadRequest, err.Error())
}
if req.DownloadOnly {
return h.OkJSON(ctx, "successfully created download target")
}
return h.OkJSON(ctx, "successfully created upgrade target")
}
@@ -67,3 +33,28 @@ func (h *Handlers) CancelOlaresUpgrade(ctx *fiber.Ctx, cmd commands.Interface) e
return h.OkJSON(ctx, "successfully cancelled upgrade/download")
}
func (h *Handlers) ConfirmOlaresUpgrade(ctx *fiber.Ctx) error {
target, err := state.GetOlaresUpgradeTarget()
if err != nil {
return h.ErrJSON(ctx, http.StatusInternalServerError, err.Error())
}
if target == nil {
return h.ErrJSON(ctx, http.StatusNotFound, "upgrade target not found")
}
if target.DownloadOnly {
target.DownloadOnly = false
err = target.Save()
if err != nil {
return h.ErrJSON(ctx, http.StatusInternalServerError, err.Error())
}
if target.Downloaded {
err = state.CheckCurrentStatus(ctx.Context())
if err != nil {
klog.Warning("failed to refresh current status immediately after confirmation, ", err)
}
}
}
return h.OkJSON(ctx, "successfully confirmed upgrade")
}

View File

@@ -6,6 +6,7 @@ import (
"github.com/beclab/Olares/daemon/internel/client"
"github.com/beclab/Olares/daemon/pkg/cluster/state"
"github.com/beclab/Olares/daemon/pkg/commands"
"github.com/beclab/Olares/daemon/pkg/utils"
"github.com/gofiber/fiber/v2"
)
@@ -42,6 +43,33 @@ func (h *Handlers) RequireSignature(next func(ctx *fiber.Ctx) error) func(ctx *f
}
}
func (h *Handlers) RequireLocal(next func(ctx *fiber.Ctx) error) func(ctx *fiber.Ctx) error {
return func(ctx *fiber.Ctx) error {
return next(ctx)
}
}
func (h *Handlers) RequireOwner(next func(ctx *fiber.Ctx) error) func(ctx *fiber.Ctx) error {
return func(ctx *fiber.Ctx) error {
c, ok := ctx.Context().UserValue(client.ClIENT_CONTEXT).(client.Client)
if !ok {
return h.ErrJSON(ctx, http.StatusForbidden, "client not found")
}
// get owner from release file
envOlaresID, err := utils.GetOlaresNameFromReleaseFile()
if err != nil {
return h.ErrJSON(ctx, http.StatusInternalServerError, "failed to get Olares ID from release file")
}
if c.OlaresID() != envOlaresID {
return h.ErrJSON(ctx, http.StatusForbidden, "not the owner of this Olares")
}
return next(ctx)
}
}
func (h *Handlers) RunCommand(next func(ctx *fiber.Ctx, cmd commands.Interface) error,
cmdNew func() commands.Interface) func(ctx *fiber.Ctx) error {

View File

@@ -8,18 +8,18 @@ import (
func init() {
s := server.API
system := s.App.Group("system")
system.Get("/status", handlers.RequireSignature(handlers.GetTerminusState))
system.Get("/ifs", handlers.RequireSignature(handlers.GetNetIfs))
system.Get("/hosts-file", handlers.RequireSignature(handlers.GetHostsfile))
system.Post("/hosts-file", handlers.RequireSignature(handlers.PostHostsfile))
system.Get("/mounted-usb", handlers.RequireSignature(handlers.GetMountedUsb))
system.Get("/mounted-hdd", handlers.RequireSignature(handlers.GetMountedHdd))
system.Get("/mounted-smb", handlers.RequireSignature(handlers.GetMountedSmb))
system.Get("/mounted-path", handlers.RequireSignature(handlers.GetMountedPath))
system.Get("/mounted-usb-incluster", handlers.RequireSignature(handlers.GetMountedUsbInCluster))
system.Get("/mounted-hdd-incluster", handlers.RequireSignature(handlers.GetMountedHddInCluster))
system.Get("/mounted-smb-incluster", handlers.RequireSignature(handlers.GetMountedSmbInCluster))
system.Get("/mounted-path-incluster", handlers.RequireSignature(handlers.GetMountedPathInCluster))
system.Get("/status", handlers.RequireLocal(handlers.GetTerminusState))
system.Get("/ifs", handlers.RequireLocal(handlers.GetNetIfs))
system.Get("/hosts-file", handlers.RequireLocal(handlers.GetHostsfile))
system.Post("/hosts-file", handlers.RequireLocal(handlers.PostHostsfile))
system.Get("/mounted-usb", handlers.RequireLocal(handlers.GetMountedUsb))
system.Get("/mounted-hdd", handlers.RequireLocal(handlers.GetMountedHdd))
system.Get("/mounted-smb", handlers.RequireLocal(handlers.GetMountedSmb))
system.Get("/mounted-path", handlers.RequireLocal(handlers.GetMountedPath))
system.Get("/mounted-usb-incluster", handlers.RequireLocal(handlers.GetMountedUsbInCluster))
system.Get("/mounted-hdd-incluster", handlers.RequireLocal(handlers.GetMountedHddInCluster))
system.Get("/mounted-smb-incluster", handlers.RequireLocal(handlers.GetMountedSmbInCluster))
system.Get("/mounted-path-incluster", handlers.RequireLocal(handlers.GetMountedPathInCluster))
klog.Info("system handlers initialized")
klog.V(8).Info("system handlers initialized")
}

View File

@@ -6,8 +6,6 @@ import (
"github.com/beclab/Olares/daemon/internel/apiserver/handlers"
"github.com/beclab/Olares/daemon/internel/apiserver/server"
"github.com/beclab/Olares/daemon/internel/ble"
"github.com/gofiber/fiber/v2/middleware/cors"
"github.com/gofiber/fiber/v2/middleware/logger"
)
func NewServer(ctx context.Context, port int) *server.Server {
@@ -20,8 +18,5 @@ func NewServer(ctx context.Context, port int) *server.Server {
s := server.API
s.App.Use(cors.New())
s.App.Use(logger.New())
return s
}

View File

@@ -5,6 +5,8 @@ import (
"github.com/beclab/Olares/daemon/internel/ble"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/cors"
"github.com/gofiber/fiber/v2/middleware/logger"
"k8s.io/klog/v2"
)
@@ -15,7 +17,13 @@ type Server struct {
}
var API *Server = &Server{
App: fiber.New(),
App: func() *fiber.App {
a := fiber.New()
a.Use(cors.New())
a.Use(logger.New())
return a
}(),
}
func (s *Server) Start() error {

View File

@@ -7,15 +7,28 @@ const (
)
type Client interface {
OlaresID() string
}
var _ Client = &termipass{}
type termipass struct {
Client
jws string
jws string
olaresID string
}
// OlaresID implements Client.
func (c *termipass) OlaresID() string {
return c.olaresID
}
func NewTermipassClient(ctx context.Context, jws string) (Client, error) {
c := &termipass{jws: jws}
err, olaresID := c.validateJWS(ctx)
if err != nil {
return nil, err
}
return c, c.validateJWS(ctx)
c.olaresID = olaresID
return c, nil
}

View File

@@ -5,33 +5,20 @@ import (
"errors"
"strings"
"github.com/beclab/Olares/daemon/pkg/utils"
"k8s.io/klog/v2"
)
func (c *termipass) validateJWS(_ context.Context) error {
func (c *termipass) validateJWS(_ context.Context) (error, string) {
if strings.TrimSpace(c.jws) == "" {
klog.Error("jws is empty")
return errors.New("invalid jws")
return errors.New("invalid jws"), ""
}
// if state.CurrentState.TerminusState == state.TerminusRunning {
// client, err := utils.GetDynamicClient()
// if err != nil {
// klog.Error("get k8s client error, ", err)
// return err
// }
// jws, err := utils.GetAdminUserJws(ctx, client)
// if err != nil {
// return err
// }
// if c.jws != jws {
// return errors.New("invalid jws of admin user")
// }
// }
// TODO: validate jws on blockchain
return nil
if ok, olaresID := utils.ValidateJWS(c.jws); ok {
return nil, olaresID
} else {
klog.Error("jws validation failed")
return errors.New("invalid jws"), ""
}
}

View File

@@ -25,6 +25,8 @@ type upgradeWatcher struct {
// Internal retry state
retryCount int
nextRetryTime *time.Time
target *state.UpgradeTarget
cancel context.CancelFunc
}
func NewUpgradeWatcher() watcher.Watcher {
@@ -33,13 +35,18 @@ func NewUpgradeWatcher() watcher.Watcher {
}
func (w *upgradeWatcher) Watch(ctx context.Context) {
targetVersion, err := state.GetOlaresUpgradeTarget()
var err error
w.target, err = state.GetOlaresUpgradeTarget()
if err != nil {
klog.Errorf("failed to check upgrade target: %v", err)
return
}
if targetVersion == nil {
if w.target == nil {
if w.cancel != nil {
w.cancel()
w.cancel = nil
}
w.resetRetryState()
state.TerminusStateMu.Lock()
@@ -77,10 +84,11 @@ func (w *upgradeWatcher) Watch(ctx context.Context) {
return
}
currentVersion, err := semver.NewVersion(*currentVersionStr)
if err != nil || currentVersion.LessThan(targetVersion) {
state.CurrentState.UpgradingTarget = targetVersion.Original()
} else {
err = upgrade.RemoveUpgradeFiles()
if err != nil || currentVersion.LessThan(&w.target.Version) {
state.CurrentState.UpgradingTarget = w.target.Version.Original()
} else if !w.isUpgrading() {
w.target = nil
_, err = upgrade.NewRemoveUpgradeTarget().Execute(ctx, nil)
if err != nil {
klog.Error("failed to remove upgrade files: ", err)
}
@@ -92,10 +100,13 @@ func (w *upgradeWatcher) Watch(ctx context.Context) {
return
}
exeCtx, cancel := context.WithCancel(ctx)
w.cancel = cancel
go func() {
w.startUpgrading()
defer w.stopUpgrading()
if err := w.doUpgradeWithRetry(ctx); err != nil {
if err := w.doUpgradeWithRetry(exeCtx); err != nil {
klog.Errorf("upgrading error: %v", err)
}
}()
@@ -161,7 +172,7 @@ func (w *upgradeWatcher) getRetryCount() int {
}
func (w *upgradeWatcher) doUpgradeWithRetry(ctx context.Context) error {
err := doUpgrade(ctx)
err := w.doUpgrade(ctx)
if err != nil {
w.incrementRetry()
@@ -170,15 +181,6 @@ func (w *upgradeWatcher) doUpgradeWithRetry(ctx context.Context) error {
klog.Errorf("upgrade attempt %d failed: %v. Next retry scheduled for %v",
w.getRetryCount(), err, *w.nextRetryTime)
targetVersionDir := filepath.Join(commands.TERMINUS_BASE_DIR, "versions", "v"+state.CurrentState.UpgradingTarget)
prepareLogFile := filepath.Join(targetVersionDir, "install.log")
upgradeLogFile := filepath.Join(targetVersionDir, "upgrade.log")
for _, logFile := range []string{prepareLogFile, upgradeLogFile} {
if err := os.Remove(logFile); err != nil && !os.IsNotExist(err) {
klog.Errorf("failed to clear log file %s: %v", logFile, err)
}
}
}
return err
}
@@ -192,63 +194,65 @@ type upgradePhase struct {
var downloadPhases = []upgradePhase{
{upgrade.NewDownloadCLI, 0, 10},
{upgrade.NewDownloadWizard, 10, 20},
{upgrade.NewDownloadComponent, 30, 40},
{upgrade.NewDownloadSpaceCheck, 30, 10},
{upgrade.NewDownloadComponent, 40, 60},
}
var upgradePhases = []upgradePhase{
{upgrade.NewVersionCompatibilityCheck, 0, 5},
{upgrade.NewHealthCheck, 5, 5},
{upgrade.NewPreCheck, 5, 5},
{upgrade.NewInstallCLI, 10, 10},
{upgrade.NewImportImages, 20, 30},
{upgrade.NewInstallOlaresd, 50, 10},
{upgrade.NewInstallOlaresd, 20, 10},
{upgrade.NewImportImages, 30, 30},
{upgrade.NewUpgrade, 60, 35},
{upgrade.NewRemoveTarget, 95, 5},
}
func doUpgrade(ctx context.Context) (err error) {
downloadCompleted, err := state.IsUpgradeDownloadCompleted()
if err != nil {
return fmt.Errorf("failed to check download status: %v", err)
func (w *upgradeWatcher) doUpgrade(ctx context.Context) (err error) {
target := w.target
if target == nil {
return nil
}
if !downloadCompleted {
// Execute download phases
if err := doDownloadPhases(ctx); err != nil {
return err
targetVersionLogsDir := filepath.Join(commands.TERMINUS_BASE_DIR, "versions", "v"+target.Version.Original(), "logs")
prepareLogFile := filepath.Join(targetVersionLogsDir, "install.log")
upgradeLogFile := filepath.Join(targetVersionLogsDir, "upgrade.log")
for _, logFile := range []string{prepareLogFile, upgradeLogFile} {
if err := os.Remove(logFile); err != nil && !os.IsNotExist(err) {
klog.Errorf("failed to clear log file %s: %v", logFile, err)
}
} else {
klog.Info("download already completed, skipping download phases")
state.CurrentState.UpgradingDownloadState = state.Completed
state.CurrentState.UpgradingDownloadProgress = "100%"
state.CurrentState.UpgradingDownloadProgressNum = 100
}
if !target.Downloaded {
// Execute download phases
return doDownloadPhases(ctx, *target)
}
downloadOnly, err := state.IsUpgradeDownloadOnly()
if err != nil {
return fmt.Errorf("failed to check download-only status: %v", err)
}
klog.Info("download already completed, skipping download phases")
if downloadOnly {
if target.DownloadOnly {
state.CurrentState.UpgradingState = "WaitingForUserConfirm"
klog.Info("download completed, waiting for user request to remove upgrade.downloadonly file to proceed with upgrade")
return nil
}
return doUpgradePhases(ctx)
return doUpgradePhases(ctx, *target)
}
func doDownloadPhases(ctx context.Context) (err error) {
func doDownloadPhases(ctx context.Context, target state.UpgradeTarget) (err error) {
defer func() {
select {
case <-ctx.Done():
return
default:
}
if err != nil {
state.CurrentState.UpgradingDownloadState = state.Failed
state.CurrentState.UpgradingDownloadError = err.Error()
klog.Errorf("download phases failed: %v", err)
} else {
state.CurrentState.UpgradingDownloadState = state.Completed
state.CurrentState.UpgradingDownloadProgress = "100%"
state.CurrentState.UpgradingDownloadProgressNum = 100
state.CurrentState.UpgradingDownloadError = ""
if err := createUpgradeDownloadedFile(); err != nil {
klog.Errorf("failed to create upgrade.downloaded file: %v", err)
}
klog.Info("download phases completed successfully")
}
}()
@@ -260,7 +264,7 @@ func doDownloadPhases(ctx context.Context) (err error) {
phaseCMD := phase.newCMD()
state.CurrentState.UpgradingDownloadStep = string(phaseCMD.OperationName())
res, err := phaseCMD.Execute(ctx, state.CurrentState.UpgradingTarget)
res, err := phaseCMD.Execute(ctx, target)
if err != nil {
return fmt.Errorf("error: download phase %s: %v", phaseCMD.OperationName(), err)
}
@@ -289,11 +293,16 @@ func doDownloadPhases(ctx context.Context) (err error) {
refreshDownloadProgressFromPhase(phase, phaseProgress)
}
}
return nil
return markDownloaded()
}
func doUpgradePhases(ctx context.Context) (err error) {
func doUpgradePhases(ctx context.Context, target state.UpgradeTarget) (err error) {
defer func() {
select {
case <-ctx.Done():
return
default:
}
if err != nil {
state.CurrentState.UpgradingState = state.Failed
state.CurrentState.UpgradingError = err.Error()
@@ -309,7 +318,7 @@ func doUpgradePhases(ctx context.Context) (err error) {
phaseCMD := phase.newCMD()
state.CurrentState.UpgradingStep = string(phaseCMD.OperationName())
res, err := phaseCMD.Execute(ctx, state.CurrentState.UpgradingTarget)
res, err := phaseCMD.Execute(ctx, target)
if err != nil {
return fmt.Errorf("error: upgrade phase %s: %v", phaseCMD.OperationName(), err)
}
@@ -341,6 +350,21 @@ func doUpgradePhases(ctx context.Context) (err error) {
return nil
}
func markDownloaded() error {
target, err := state.GetOlaresUpgradeTarget()
if err != nil {
return err
}
if target == nil {
return fmt.Errorf("no target found to mark downloaded, possibly upgrade cancelled")
}
if !target.Downloaded {
target.Downloaded = true
return target.Save()
}
return nil
}
func refreshUpgradeProgressFromPhase(phase upgradePhase, phaseProgress int) {
spanProgress := math.Min(float64(phaseProgress)*float64(phase.progressSpan)/float64(commands.ProgressNumFinished), float64(phase.progressSpan))
newProgress := phase.progressOffset + int(math.Round(spanProgress))
@@ -360,7 +384,3 @@ func refreshDownloadProgressFromPhase(phase upgradePhase, phaseProgress int) {
state.CurrentState.UpgradingDownloadProgressNum = newProgress
state.CurrentState.UpgradingDownloadProgress = fmt.Sprintf("%d%%", state.CurrentState.UpgradingDownloadProgressNum)
}
func createUpgradeDownloadedFile() error {
return os.WriteFile(commands.UPGRADE_DOWNLOADED_FILE, []byte(""), 0644)
}

View File

@@ -120,7 +120,9 @@ func CheckCurrentStatus(ctx context.Context) error {
utils.ForceMountHdd(ctx)
// set default value
CurrentState.TerminusVersion = &commands.INSTALLED_VERSION
if CurrentState.TerminusVersion == nil {
CurrentState.TerminusVersion = &commands.INSTALLED_VERSION
}
CurrentState.DefaultFRPServer = os.Getenv("FRP_SERVER")
CurrentState.FRPEnable = os.Getenv("FRP_ENABLE")
container := os.Getenv("CONTAINER_MODE")
@@ -225,6 +227,7 @@ func CheckCurrentStatus(ctx context.Context) error {
if !slices.ContainsFunc(ips, func(i *nets.NetInterface) bool { return i.IP == hostIp }) {
// wrong host ip
klog.Warningf("host ip %s not in internal ips, try to fix it", hostIp)
if err = fix(); err != nil {
return err
}
@@ -233,6 +236,7 @@ func CheckCurrentStatus(ctx context.Context) error {
if conflict, err := nets.ConflictDomainIpInHostsFile(hostname); err != nil {
return err
} else if conflict {
klog.Warningf("domain %s conflict with internal ip, try to fix it", hostname)
if err = fix(); err != nil {
return err
}
@@ -351,15 +355,7 @@ func CheckCurrentStatus(ctx context.Context) error {
if err != nil {
return fmt.Errorf("error getting Olares upgrade target: %v", err.Error())
}
upgradeDownloadCompleted, err := IsUpgradeDownloadCompleted()
if err != nil {
return fmt.Errorf("error checking if upgrade download completed: %v", err.Error())
}
upgradeDownloadOnly, err := IsUpgradeDownloadOnly()
if err != nil {
return fmt.Errorf("error checking if upgrade download only: %v", err.Error())
}
if upgradeTarget != nil && upgradeDownloadCompleted && !upgradeDownloadOnly {
if upgradeTarget != nil && upgradeTarget.Downloaded && !upgradeTarget.DownloadOnly {
currentTerminusState = Upgrading
return nil
}

View File

@@ -149,7 +149,7 @@ func (u UpgradingValidator) ValidateOp(op commands.Interface) error {
commands.Shutdown, commands.Uninstall,
commands.ConnectWifi, commands.ChangeHost,
commands.CollectLogs, commands.MountSmb, commands.UmountSmb,
commands.RemoveUpgradeTarget:
commands.CreateUpgradeTarget, commands.RemoveUpgradeTarget:
return nil
}
@@ -204,7 +204,7 @@ func (r RunningValidator) ValidateOp(op commands.Interface) error {
case commands.ChangeIp, commands.Reboot, commands.Shutdown,
commands.Uninstall, commands.ConnectWifi, commands.ChangeHost,
commands.UmountUsb, commands.CollectLogs, commands.MountSmb, commands.UmountSmb,
commands.CreateUpgradeTarget:
commands.CreateUpgradeTarget, commands.RemoveUpgradeTarget:
return nil
}
@@ -232,7 +232,8 @@ func (s SystemErrorValidator) ValidateOp(op commands.Interface) error {
switch op.OperationName() {
case commands.ChangeIp, commands.Reboot, commands.Shutdown,
commands.Uninstall, commands.ConnectWifi, commands.ChangeHost,
commands.CollectLogs, commands.MountSmb, commands.UmountSmb:
commands.CollectLogs, commands.MountSmb, commands.UmountSmb,
commands.CreateUpgradeTarget, commands.RemoveUpgradeTarget:
return nil
}

View File

@@ -2,14 +2,15 @@ package state
import (
"context"
"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"
@@ -126,49 +127,6 @@ func IsTerminusInstalling() (bool, error) {
return running, err
}
func GetOlaresUpgradeTarget() (*semver.Version, error) {
b, err := os.ReadFile(commands.UPGRADE_TARGET_FILE)
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, err
}
target := strings.TrimSpace(string(b))
version, err := semver.NewVersion(target)
if err != nil {
klog.Errorf("invalid upgrade target %s: %s, removing", target, err)
err = os.Remove(commands.UPGRADE_TARGET_FILE)
if err != nil && !os.IsNotExist(err) {
return nil, err
}
return nil, nil
}
return version, nil
}
func IsUpgradeDownloadOnly() (bool, error) {
_, err := os.Stat(commands.UPGRADE_DOWNLOADONLY_FILE)
if err != nil {
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
return true, nil
}
func IsUpgradeDownloadCompleted() (bool, error) {
_, err := os.Stat(commands.UPGRADE_DOWNLOADED_FILE)
if err != nil {
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
return true, nil
}
func IsIpChangeRunning() (bool, error) {
running, err := isProcessRunning(commands.CHANGINGIP_PID_FILE)
if err != nil {
@@ -181,7 +139,7 @@ func IsIpChangeRunning() (bool, error) {
}
func GetMachineInfo(ctx context.Context) (osType, osInfo, osArch, osVersion, osKernel string, err error) {
cmd := exec.CommandContext(ctx, cli.TERMINUS_CLI, "info", "show")
cmd := exec.CommandContext(ctx, cli.TERMINUS_CLI, "osinfo", "show")
if output, err := cmd.Output(); err == nil {
lines := strings.Split(string(output), "\n")
@@ -207,3 +165,69 @@ func GetMachineInfo(ctx context.Context) (osType, osInfo, osArch, osVersion, osK
return
}
type UpgradeTarget struct {
Version semver.Version `json:"version"`
WizardURL string `json:"wizardURL"`
CliURL string `json:"cliURL"`
DownloadOnly bool `json:"downloadOnly"`
Downloaded bool `json:"downloaded"`
}
func (t *UpgradeTarget) IsValidRequest() error {
existingTarget, err := GetOlaresUpgradeTarget()
if err == nil && existingTarget != nil && !t.Version.Equal(&existingTarget.Version) {
return fmt.Errorf("different upgrade version: %s already exists, please cancel it first", existingTarget.Version)
}
if CurrentState.TerminusVersion != nil {
current, err := semver.NewVersion(*CurrentState.TerminusVersion)
if err != nil {
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)
}
}
return nil
}
func (t *UpgradeTarget) Save() error {
content, err := json.Marshal(t)
if err != nil {
return fmt.Errorf("failed to marshal target: %v", err)
}
err = os.WriteFile(commands.UPGRADE_TARGET_FILE, content, 0644)
if err != nil {
return fmt.Errorf("failed to write target file: %v", err)
}
return nil
}
func GetOlaresUpgradeTarget() (*UpgradeTarget, error) {
b, err := os.ReadFile(commands.UPGRADE_TARGET_FILE)
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, fmt.Errorf("failed to read upgrade target file: %v", err)
}
target := &UpgradeTarget{}
err = json.Unmarshal(b, target)
if err != nil {
vstr := strings.TrimSpace(string(b))
var v *semver.Version
v, err = semver.NewVersion(vstr)
if err == nil {
target.Version = *v
}
}
if err != nil {
klog.Errorf("invalid upgrade target file content(%v): %s, removing target file", err, string(b))
err = os.Remove(commands.UPGRADE_TARGET_FILE)
if err != nil && !os.IsNotExist(err) {
klog.Errorf("error removing invalid upgrade target file: %v", err)
}
return nil, nil
}
return target, nil
}

View File

@@ -16,22 +16,20 @@ var (
COMMAND_BASE_DIR = "" // deprecated shell command base dir
CDN_URL = "https://dc3p1870nn3cj.cloudfront.net"
OS_ROOT_DIR = "/olares"
INSTALLING_PID_FILE = "installing.pid"
UNINSTALLING_PID_FILE = "uninstalling.pid"
CHANGINGIP_PID_FILE = "changingip.pid"
UPGRADE_TARGET_FILE = "upgrade.target"
UPGRADE_DOWNLOADONLY_FILE = "upgrade.downloadonly"
UPGRADE_DOWNLOADED_FILE = "upgrade.downloaded"
PREV_IP_TO_CHANGE_FILE = ".prev_ip"
PREV_IP_CHANGE_FAILED = ".ip_change_failed"
INSTALL_LOCK = ".installed"
LOG_FILE = "install.log"
TERMINUS_BASE_DIR = ""
MOUNT_BASE_DIR = path.Join(OS_ROOT_DIR, "share")
PREPARE_LOCK = ".prepared"
REDIS_CONF = OS_ROOT_DIR + "/data/redis/etc/redis.conf"
EXPORT_POD_LOGS_DIR = "Home/pod_logs"
OS_ROOT_DIR = "/olares"
INSTALLING_PID_FILE = "installing.pid"
UNINSTALLING_PID_FILE = "uninstalling.pid"
CHANGINGIP_PID_FILE = "changingip.pid"
UPGRADE_TARGET_FILE = "upgrade.target"
PREV_IP_TO_CHANGE_FILE = ".prev_ip"
PREV_IP_CHANGE_FAILED = ".ip_change_failed"
INSTALL_LOCK = ".installed"
LOG_FILE = "install.log"
TERMINUS_BASE_DIR = ""
MOUNT_BASE_DIR = path.Join(OS_ROOT_DIR, "share")
PREPARE_LOCK = ".prepared"
REDIS_CONF = OS_ROOT_DIR + "/data/redis/etc/redis.conf"
EXPORT_POD_LOGS_DIR = "Home/pod_logs"
ProgressNumFinished = 100
)
@@ -47,8 +45,6 @@ func Init() {
UNINSTALLING_PID_FILE = filepath.Join(baseDir, UNINSTALLING_PID_FILE)
CHANGINGIP_PID_FILE = filepath.Join(baseDir, CHANGINGIP_PID_FILE)
UPGRADE_TARGET_FILE = filepath.Join(baseDir, UPGRADE_TARGET_FILE)
UPGRADE_DOWNLOADONLY_FILE = filepath.Join(baseDir, UPGRADE_DOWNLOADONLY_FILE)
UPGRADE_DOWNLOADED_FILE = filepath.Join(baseDir, UPGRADE_DOWNLOADED_FILE)
INSTALL_LOCK = filepath.Join(baseDir, INSTALL_LOCK)
PREPARE_LOCK = filepath.Join(baseDir, PREPARE_LOCK)
PREV_IP_TO_CHANGE_FILE = filepath.Join(baseDir, PREV_IP_TO_CHANGE_FILE)

View File

@@ -22,7 +22,8 @@ const (
DownloadCLI Operations = "downloadCLI"
DownloadWizard Operations = "downloadWizard"
VersionCompatibilityCheck Operations = "versionCompatibilityCheck"
UpgradeHealthCheck Operations = "upgradeHealthCheck"
UpgradePreCheck Operations = "PreCheck"
DownloadSpaceCheck Operations = "downloadSpaceCheck"
DownloadComponent Operations = "downloadComponent"
ImportImages Operations = "importImages"
InstallOlaresd Operations = "installOlaresd"

View File

@@ -4,8 +4,14 @@ import (
"context"
"errors"
"fmt"
"github.com/beclab/Olares/daemon/pkg/cluster/state"
"github.com/beclab/Olares/daemon/pkg/containerd"
"github.com/dustin/go-humanize"
v1 "k8s.io/cri-api/pkg/apis/runtime/v1"
"k8s.io/utils/strings/slices"
"os"
"path/filepath"
"runtime"
"strings"
"github.com/Masterminds/semver/v3"
@@ -13,7 +19,6 @@ import (
"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/sets"
"k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/klog/v2"
)
@@ -33,7 +38,7 @@ func NewVersionCompatibilityCheck() commands.Interface {
}
func (i *versionCompatibilityCheck) Execute(ctx context.Context, p any) (res any, err error) {
version, ok := p.(string)
target, ok := p.(state.UpgradeTarget)
if !ok {
err = errors.New("invalid param")
return
@@ -50,7 +55,7 @@ func (i *versionCompatibilityCheck) Execute(ctx context.Context, p any) (res any
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"+version, "version.hint")
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)
@@ -77,32 +82,73 @@ func (i *versionCompatibilityCheck) Execute(ctx context.Context, p any) (res any
return newExecutionRes(true, nil), nil
}
type healthCheck struct {
type preCheck struct {
commands.Operation
}
var _ commands.Interface = &healthCheck{}
var _ commands.Interface = &preCheck{}
func NewHealthCheck() commands.Interface {
return &healthCheck{
func NewPreCheck() commands.Interface {
return &preCheck{
Operation: commands.Operation{
Name: commands.UpgradeHealthCheck,
Name: commands.UpgradePreCheck,
},
}
}
func (i *healthCheck) Execute(ctx context.Context, _ any) (res any, err error) {
klog.Info("Starting upgrade health check")
func (i *preCheck) Execute(ctx context.Context, p any) (res any, err error) {
klog.Info("Starting upgrade pre check")
const minAvailableSpace = 100 * 1024 * 1024 * 1024 // 100GB in bytes
availableSpace, err := utils.GetDiskAvailableSpace("/")
if err != nil {
return nil, fmt.Errorf("error checking disk space: %s", err)
target, ok := p.(state.UpgradeTarget)
if !ok {
return nil, errors.New("invalid param")
}
klog.Infof("Root partition available space: %.2fGB", float64(availableSpace)/(1024*1024*1024))
if availableSpace < minAvailableSpace {
return nil, fmt.Errorf("insufficient disk space: %.2fGB available, minimum 100GB required",
float64(availableSpace)/(1024*1024*1024))
arch := "amd64"
if runtime.GOARCH == "arm" {
arch = "arm64"
}
componentManifestFilePath := filepath.Join(commands.TERMINUS_BASE_DIR, "versions", "v"+target.Version.Original(), "images", "installation.manifest."+arch)
components, err := unmarshalComponentManifestFile(componentManifestFilePath)
if err != nil {
return nil, fmt.Errorf("error parsing component manifest file %s: %v", componentManifestFilePath, err)
}
criImageService, err := containerd.NewCRIImageService()
if err != nil {
return nil, fmt.Errorf("error creating cri image service: %v", err)
}
images, err := criImageService.ListImages(ctx, &v1.ImageFilter{})
if err != nil {
return nil, fmt.Errorf("error listing images: %v", err)
}
var requiredSpace uint64
for _, component := range components {
if component.Type != "image" {
continue
}
var imageExists bool
for _, image := range images {
for _, repoTag := range image.RepoTags {
if strings.Contains(repoTag, component.FileID) {
imageExists = true
break
}
}
if imageExists {
break
}
}
if !imageExists {
// for now, the compressed layer and sha256 content hash in the manifest
// can not be used for us to compare and calculate a precise space requirement
// because the "docker save" command exports image in uncompressed format
// and dockerhub stores & distributes the image in compressed format
// so we just make a rough number based on the compressed image archive file
requiredSpace += component.Size * 3
}
}
klog.Infof("Required space for image import: %s", humanize.Bytes(requiredSpace))
if err := tryToUseDiskSpace(containerd.DefaultContainerdRootPath, requiredSpace); err != nil {
return nil, err
}
client, err := utils.GetKubeClient()
@@ -114,65 +160,152 @@ func (i *healthCheck) Execute(ctx context.Context, _ any) (res any, err error) {
return nil, fmt.Errorf("error listing nodes: %s", err)
}
for _, node := range nodes.Items {
roles := sets.NewString()
for k, v := range node.Labels {
switch {
case strings.HasPrefix(k, "node-role.kubernetes.io/"):
if role := strings.TrimPrefix(k, "node-role.kubernetes.io/"); len(role) > 0 {
roles.Insert(role)
}
case k == "kubernetes.io/role" && v != "":
roles.Insert(v)
}
}
if !roles.HasAny("control-plane", "master") {
continue
}
//roles := sets.NewString()
//for k, v := range node.Labels {
// switch {
// case strings.HasPrefix(k, "node-role.kubernetes.io/"):
// if role := strings.TrimPrefix(k, "node-role.kubernetes.io/"); len(role) > 0 {
// roles.Insert(role)
// }
//
// case k == "kubernetes.io/role" && v != "":
// roles.Insert(v)
// }
//}
//if !roles.HasAny("control-plane", "master") {
// continue
//}
if node.Spec.Unschedulable {
return nil, fmt.Errorf("node %s is unschedulable", node.Name)
return nil, fmt.Errorf("node %s: unschedulable", node.Name)
}
var readyConditionExists bool
for _, condition := range node.Status.Conditions {
if condition.Type == corev1.NodeReady {
switch condition.Type {
case corev1.NodeReady:
readyConditionExists = true
if condition.Status != corev1.ConditionTrue {
return nil, fmt.Errorf("node %s is not ready", node.Name)
return nil, fmt.Errorf("node %s: not ready", node.Name)
}
case corev1.NodeMemoryPressure, corev1.NodeDiskPressure,
corev1.NodePIDPressure, corev1.NodeNetworkUnavailable:
if condition.Status == corev1.ConditionTrue {
return nil, fmt.Errorf("node %s: %s", node.Name, condition.Type)
}
}
}
if !readyConditionExists {
return nil, fmt.Errorf("node %s's condition is unknown", node.Name)
return nil, fmt.Errorf("node %s: condition unknown", node.Name)
}
}
criticalNamespaces := []string{"os-platform", "os-framework"}
for _, namespace := range criticalNamespaces {
pods, err := client.CoreV1().Pods(namespace).List(ctx, metav1.ListOptions{})
if err != nil {
return nil, fmt.Errorf("error listing pods in namespace %s: %s", namespace, err)
pods, err := client.CoreV1().Pods(corev1.NamespaceAll).List(ctx, metav1.ListOptions{})
if err != nil {
return nil, fmt.Errorf("failed to list pods: %v", err)
}
for _, pod := range pods.Items {
if !strings.HasPrefix(pod.Namespace, "os-") {
continue
}
if pod.Status.Phase == corev1.PodSucceeded {
continue
}
for _, pod := range pods.Items {
if pod.Status.Phase == corev1.PodSucceeded {
continue
}
podStatus := utils.GetPodStatus(&pod)
podStatus := utils.GetPodStatus(&pod)
if podStatus != "Running" && podStatus != "Completed" {
klog.Errorf("Pod %s/%s is not healthy: %s", pod.Namespace, pod.Name, podStatus)
return nil, fmt.Errorf("pod %s/%s is not healthy: %s", pod.Namespace, pod.Name, podStatus)
}
if podStatus != "Running" && podStatus != "Completed" {
klog.Errorf("Pod %s/%s is not healthy: %s", namespace, pod.Name, podStatus)
return nil, fmt.Errorf("pod %s/%s is not healthy: %s", namespace, pod.Name, podStatus)
}
if !utils.IsPodReady(&pod) && pod.Status.Phase == corev1.PodRunning {
klog.Warningf("Pod %s/%s is running but not ready", namespace, pod.Name)
return nil, fmt.Errorf("pod %s/%s is running but not ready", namespace, pod.Name)
}
if !utils.IsPodReady(&pod) && pod.Status.Phase == corev1.PodRunning {
klog.Warningf("Pod %s/%s is running but not ready", pod.Namespace, pod.Name)
return nil, fmt.Errorf("pod %s/%s is running but not ready", pod.Namespace, pod.Name)
}
}
klog.Info("health checks passed for upgrade")
// if any user is in the progress of activation
// upgrade cannot start
dynamicClient, err := utils.GetDynamicClient()
if err != nil {
err = fmt.Errorf("failed to get dynamic client: %v", err)
klog.Error(err.Error())
return nil, err
}
users, err := utils.ListUsers(ctx, dynamicClient)
if err != nil {
err = fmt.Errorf("failed to list users: %v", err)
klog.Error(err.Error())
return nil, err
}
var activatingUsers []string
for _, user := range users {
status, ok := user.GetAnnotations()["bytetrade.io/wizard-status"]
if !ok || slices.Contains([]string{"", "wait_activate_vault", "completed"}, status) {
continue
}
activatingUsers = append(activatingUsers, user.GetName())
}
if len(activatingUsers) > 0 {
return nil, fmt.Errorf("waiting for user to finish activation: %s", strings.Join(activatingUsers, ", "))
}
klog.Info("pre checks passed for upgrade")
return newExecutionRes(true, nil), nil
}
type downloadSpaceCheck struct {
commands.Operation
}
var _ commands.Interface = &downloadSpaceCheck{}
func NewDownloadSpaceCheck() commands.Interface {
return &downloadSpaceCheck{
Operation: commands.Operation{
Name: commands.DownloadSpaceCheck,
},
}
}
func (i *downloadSpaceCheck) Execute(ctx context.Context, p any) (res any, err error) {
target, ok := p.(state.UpgradeTarget)
if !ok {
return nil, errors.New("invalid param")
}
klog.Info("Starting download space check")
arch := "amd64"
if runtime.GOARCH == "arm" {
arch = "arm64"
}
componentManifestFilePath := filepath.Join(commands.TERMINUS_BASE_DIR, "versions", "v"+target.Version.Original(), "images", "installation.manifest."+arch)
components, err := unmarshalComponentManifestFile(componentManifestFilePath)
if err != nil {
return nil, fmt.Errorf("error parsing component manifest file %s: %v", componentManifestFilePath, err)
}
var requiredSpace uint64
for name, component := range components {
path := filepath.Join(commands.TERMINUS_BASE_DIR, component.Path, name)
_, err := os.Stat(path)
if err == nil {
continue
}
if os.IsNotExist(err) {
requiredSpace += component.Size
continue
}
return nil, fmt.Errorf("failed to check existence of file %s: %v", path, err)
}
klog.Infof("Required space for download: %s", humanize.Bytes(requiredSpace))
if err := tryToUseDiskSpace(commands.TERMINUS_BASE_DIR, requiredSpace); err != nil {
return nil, err
}
klog.Info("Space check passed for download")
return newExecutionRes(true, nil), nil
}

View File

@@ -4,17 +4,10 @@ import (
"context"
"errors"
"fmt"
"os"
"github.com/beclab/Olares/daemon/pkg/cluster/state"
"github.com/beclab/Olares/daemon/pkg/commands"
)
type UpgradeRequest struct {
Version string `json:"version"`
DownloadOnly bool `json:"downloadOnly"`
}
type createUpgradeTarget struct {
commands.Operation
}
@@ -30,55 +23,17 @@ func NewCreateUpgradeTarget() commands.Interface {
}
func (i *createUpgradeTarget) Execute(ctx context.Context, p any) (res any, err error) {
req, ok := p.(UpgradeRequest)
req, ok := p.(state.UpgradeTarget)
if !ok {
return nil, errors.New("invalid param")
}
if err := checkVersionConflicts(req.Version); err != nil {
return nil, err
}
if err := createUpgradeTargetFile(req.Version); err != nil {
req.Downloaded = false
if err = req.Save(); err != nil {
return nil, fmt.Errorf("failed to create upgrade target: %v", err)
}
if req.DownloadOnly {
if err := createUpgradeDownloadOnlyFile(); err != nil {
return nil, fmt.Errorf("failed to create upgrade downloadonly file: %v", err)
}
} else {
if err := removeUpgradeDownloadOnlyFile(); err != nil && !os.IsNotExist(err) {
return nil, fmt.Errorf("failed to remove upgrade downloadonly file: %v", err)
}
}
state.StateTrigger <- struct{}{}
return NewExecutionRes(true, nil), nil
}
func checkVersionConflicts(version string) error {
if state.CurrentState.UpgradingState == state.InProgress {
return fmt.Errorf("system is currently upgrading")
}
upgradeTarget, err := state.GetOlaresUpgradeTarget()
if err == nil && upgradeTarget != nil && upgradeTarget.Original() != version {
return fmt.Errorf("different upgrade version %s already exists, please cancel it first", upgradeTarget.Original())
}
return nil
}
func createUpgradeTargetFile(version string) error {
return os.WriteFile(commands.UPGRADE_TARGET_FILE, []byte(version), 0755)
}
func createUpgradeDownloadOnlyFile() error {
return os.WriteFile(commands.UPGRADE_DOWNLOADONLY_FILE, []byte(""), 0755)
}
func removeUpgradeDownloadOnlyFile() error {
return os.Remove(commands.UPGRADE_DOWNLOADONLY_FILE)
}

View File

@@ -4,13 +4,12 @@ import (
"context"
"errors"
"fmt"
"github.com/beclab/Olares/daemon/pkg/cluster/state"
"os"
"path/filepath"
"runtime"
"github.com/Masterminds/semver/v3"
"github.com/beclab/Olares/daemon/pkg/commands"
"k8s.io/klog/v2"
)
type downloadCLI struct {
@@ -28,26 +27,11 @@ func NewDownloadCLI() commands.Interface {
}
func (i *downloadCLI) Execute(ctx context.Context, p any) (res any, err error) {
version, ok := p.(string)
target, ok := p.(state.UpgradeTarget)
if !ok {
return nil, errors.New("invalid param")
}
targetVersion, err := semver.NewVersion(version)
if err != nil {
return nil, fmt.Errorf("invalid target version %s: %v", version, err)
}
currentVersion, err := getCurrentCliVersion()
if err != nil {
// if we can't get the current version, assume we need to download
klog.Warningf("Failed to get current olares-cli version: %v, proceeding with download", err)
} else {
if !currentVersion.LessThan(targetVersion) {
return newExecutionRes(true, nil), nil
}
}
arch := "amd64"
if runtime.GOARCH == "arm" {
arch = "arm64"
@@ -58,8 +42,11 @@ func (i *downloadCLI) Execute(ctx context.Context, p any) (res any, err error) {
return nil, fmt.Errorf("failed to create components directory: %v", err)
}
downloadURL := fmt.Sprintf("%s/olares-cli-v%s_linux_%s.tar.gz", commands.CDN_URL, version, arch)
tarFile := filepath.Join(destDir, fmt.Sprintf("olares-cli-v%s.tar.gz", version))
downloadURL := target.CliURL
if downloadURL == "" {
downloadURL = fmt.Sprintf("%s/olares-cli-v%s_linux_%s.tar.gz", commands.CDN_URL, target.Version.Original(), arch)
}
tarFile := filepath.Join(destDir, fmt.Sprintf("olares-cli-v%s.tar.gz", target.Version.Original()))
if err := downloadFile(downloadURL, tarFile); err != nil {
return nil, fmt.Errorf("failed to download olares-cli: %v", err)
@@ -70,7 +57,7 @@ func (i *downloadCLI) Execute(ctx context.Context, p any) (res any, err error) {
}
binaryPath := filepath.Join(destDir, "olares-cli")
versionedPath := filepath.Join(destDir, fmt.Sprintf("olares-cli-v%s", version))
versionedPath := filepath.Join(destDir, fmt.Sprintf("olares-cli-v%s", target.Version.Original()))
if err := os.Rename(binaryPath, versionedPath); err != nil {
return nil, fmt.Errorf("failed to rename olares-cli binary: %v", err)
}

View File

@@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"github.com/beclab/Olares/daemon/pkg/cluster/state"
"io"
"os"
"path/filepath"
@@ -38,13 +39,12 @@ func NewDownloadComponent() commands.Interface {
}
func (i *downloadComponent) Execute(ctx context.Context, p any) (res any, err error) {
version, ok := p.(string)
target, ok := p.(state.UpgradeTarget)
if !ok {
return nil, errors.New("invalid param")
}
i.logFile = filepath.Join(commands.TERMINUS_BASE_DIR, "versions", "v"+version, "logs", "install.log")
i.progressKeywords = append(i.progressKeywords, progressKeyword{fmt.Sprintf("no need to upgrade to %s", version), commands.ProgressNumFinished})
i.logFile = filepath.Join(commands.TERMINUS_BASE_DIR, "versions", "v"+target.Version.Original(), "logs", "install.log")
if err := i.refreshProgress(); err != nil {
return nil, fmt.Errorf("could not determine whether component download is finished: %v", err)
}
@@ -60,7 +60,7 @@ func (i *downloadComponent) Execute(ctx context.Context, p any) (res any, err er
params := []string{
"download", "component",
"--version", version,
"--version", target.Version.Original(),
"--base-dir", commands.TERMINUS_BASE_DIR,
}
if commands.CDN_URL != "" {
@@ -76,7 +76,7 @@ func (i *downloadComponent) Execute(ctx context.Context, p any) (res any, err er
func (i *downloadComponent) watch(ctx context.Context) {
go func() {
defer close(i.progressChan)
ticker := time.NewTicker(2 * time.Second)
ticker := time.NewTicker(10 * time.Second)
defer ticker.Stop()
for {
select {
@@ -119,15 +119,18 @@ func (i *downloadComponent) refreshProgress() error {
updated := false
for line := range t.Lines {
for _, p := range i.progressKeywords {
var lineProgress int
var lineProgress, nextProgress int
if strings.Contains(line.Text, p.KeyWord) {
lineProgress = p.ProgressNum
} else {
lineProgress = parseComponentDownloadProgressByItemProgress(line.Text)
lineProgress, nextProgress = parseComponentDownloadProgressByItemProgress(line.Text)
}
if i.progress < lineProgress {
i.progress = lineProgress
updated = true
} else if i.progress+1 < nextProgress {
i.progress += 1
updated = true
}
}
}
@@ -139,10 +142,10 @@ func (i *downloadComponent) refreshProgress() error {
return nil
}
func parseComponentDownloadProgressByItemProgress(line string) int {
func parseComponentDownloadProgressByItemProgress(line string) (int, int) {
// filter out other item progress lines to avoid confusion
if !strings.Contains(line, "file") || !strings.Contains(line, "downloading") {
return 0
return 0, 0
}
return parseProgressFromItemProgress(line)
}

View File

@@ -4,25 +4,25 @@ import (
"context"
"errors"
"fmt"
"github.com/beclab/Olares/daemon/pkg/cli"
"github.com/beclab/Olares/daemon/pkg/cluster/state"
"github.com/beclab/Olares/daemon/pkg/commands"
"io"
"os"
"path/filepath"
"strings"
"time"
"github.com/beclab/Olares/daemon/pkg/cli"
"github.com/beclab/Olares/daemon/pkg/commands"
"github.com/nxadm/tail"
"k8s.io/klog/v2"
)
type downloadWizard struct {
commands.Operation
logFile string
assumeFinishedFiles []string
progressKeywords []progressKeyword
progress int
progressChan chan<- int
logFile string
progressKeywords []progressKeyword
progress int
progressChan chan<- int
}
var _ commands.Interface = &downloadWizard{}
@@ -40,17 +40,14 @@ func NewDownloadWizard() commands.Interface {
}
func (i *downloadWizard) Execute(ctx context.Context, p any) (res any, err error) {
version, ok := p.(string)
target, ok := p.(state.UpgradeTarget)
if !ok {
return nil, errors.New("invalid param")
}
version := target.Version.Original()
i.logFile = filepath.Join(commands.TERMINUS_BASE_DIR, "versions", "v"+version, "logs", "install.log")
i.assumeFinishedFiles = []string{
filepath.Join(commands.TERMINUS_BASE_DIR, "versions", "v"+version, "version.hint"),
filepath.Join(commands.TERMINUS_BASE_DIR, "versions", "v"+version, "installation.manifest"),
filepath.Join(commands.TERMINUS_BASE_DIR, "versions", "v"+version, "wizard"),
}
if err := i.refreshProgress(); err != nil {
return nil, fmt.Errorf("could not determine whether wizard download is finished: %v", err)
}
@@ -72,6 +69,9 @@ func (i *downloadWizard) Execute(ctx context.Context, p any) (res any, err error
if commands.CDN_URL != "" {
params = append(params, "--download-cdn-url", commands.CDN_URL)
}
if target.WizardURL != "" {
params = append(params, "--url-override", target.WizardURL)
}
if err = cmd.RunAsync_(ctx, cli.TERMINUS_CLI, params...); err != nil {
return nil, err
}
@@ -103,21 +103,6 @@ func (i *downloadWizard) watch(ctx context.Context) {
}
func (i *downloadWizard) refreshProgress() error {
allExisting := true
for _, f := range i.assumeFinishedFiles {
_, err := os.Stat(f)
if os.IsNotExist(err) {
allExisting = false
break
}
if err != nil {
return fmt.Errorf("could not stat file %s: %v", f, err)
}
}
if allExisting {
i.progress = commands.ProgressNumFinished
return nil
}
info, err := os.Stat(i.logFile)
if err != nil {
if os.IsNotExist(err) {

View File

@@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"github.com/beclab/Olares/daemon/pkg/cluster/state"
"io"
"os"
"path/filepath"
@@ -38,12 +39,12 @@ func NewImportImages() commands.Interface {
}
func (i *prepareImages) Execute(ctx context.Context, p any) (res any, err error) {
version, ok := p.(string)
target, ok := p.(state.UpgradeTarget)
if !ok {
return nil, errors.New("invalid param")
}
i.logFile = filepath.Join(commands.TERMINUS_BASE_DIR, "versions", "v"+version, "logs", "install.log")
i.logFile = filepath.Join(commands.TERMINUS_BASE_DIR, "versions", "v"+target.Version.Original(), "logs", "install.log")
if err := i.refreshProgress(); err != nil {
return nil, fmt.Errorf("could not determine whether images prepare is finished: %v", err)
}
@@ -59,7 +60,7 @@ func (i *prepareImages) Execute(ctx context.Context, p any) (res any, err error)
params := []string{
"prepare", "images",
"--version", version,
"--version", target.Version.Original(),
"--base-dir", commands.TERMINUS_BASE_DIR,
}
if err = cmd.RunAsync_(ctx, cli.TERMINUS_CLI, params...); err != nil {
@@ -115,15 +116,18 @@ func (i *prepareImages) refreshProgress() error {
updated := false
for line := range t.Lines {
for _, p := range i.progressKeywords {
var lineProgress int
var lineProgress, nextProgress int
if strings.Contains(line.Text, p.KeyWord) {
lineProgress = p.ProgressNum
} else {
lineProgress = parseImagePrepareProgressByItemProgress(line.Text)
lineProgress, nextProgress = parseImagePrepareProgressByItemProgress(line.Text)
}
if i.progress < lineProgress {
i.progress = lineProgress
updated = true
} else if i.progress+1 < nextProgress {
i.progress += 1
updated = true
}
}
}
@@ -135,10 +139,10 @@ func (i *prepareImages) refreshProgress() error {
return nil
}
func parseImagePrepareProgressByItemProgress(line string) int {
func parseImagePrepareProgressByItemProgress(line string) (int, int) {
// filter out other item progress lines to avoid confusion
if !strings.Contains(line, "imported image") {
return 0
return 0, 0
}
return parseProgressFromItemProgress(line)
}

View File

@@ -4,7 +4,7 @@ import (
"context"
"errors"
"fmt"
"github.com/Masterminds/semver/v3"
"github.com/beclab/Olares/daemon/pkg/cluster/state"
"github.com/beclab/Olares/daemon/pkg/commands"
"k8s.io/klog/v2"
"os"
@@ -27,26 +27,12 @@ func NewInstallCLI() commands.Interface {
}
func (i *installCLI) Execute(ctx context.Context, p any) (res any, err error) {
version, ok := p.(string)
target, ok := p.(state.UpgradeTarget)
if !ok {
return nil, errors.New("invalid param")
}
targetVersion, err := semver.NewVersion(version)
if err != nil {
return nil, fmt.Errorf("invalid target version %s: %v", version, err)
}
currentVersion, err := getCurrentCliVersion()
if err != nil {
klog.Warningf("Failed to get current olares-cli version: %v, proceeding with installation", err)
} else {
if !currentVersion.LessThan(targetVersion) {
return newExecutionRes(true, nil), nil
}
}
preDownloadedPath := filepath.Join(commands.TERMINUS_BASE_DIR, "pkg", "components", fmt.Sprintf("olares-cli-v%s", version))
preDownloadedPath := filepath.Join(commands.TERMINUS_BASE_DIR, "pkg", "components", fmt.Sprintf("olares-cli-v%s", target.Version.Original()))
if _, err := os.Stat(preDownloadedPath); err != nil {
klog.Warningf("Failed to find pre-downloaded binary path %s: %v", preDownloadedPath, err)
return newExecutionRes(false, nil), err

View File

@@ -4,13 +4,13 @@ import (
"context"
"errors"
"fmt"
"github.com/beclab/Olares/daemon/pkg/cluster/state"
"io"
"os"
"path/filepath"
"strings"
"time"
semver "github.com/Masterminds/semver/v3"
"github.com/beclab/Olares/daemon/pkg/cli"
"github.com/beclab/Olares/daemon/pkg/commands"
"github.com/nxadm/tail"
@@ -49,25 +49,21 @@ func NewInstallOlaresd() commands.Interface {
}
func (i *prepareOlaresd) Execute(ctx context.Context, p any) (res any, err error) {
version, ok := p.(string)
target, ok := p.(state.UpgradeTarget)
if !ok {
return nil, errors.New("invalid param")
}
targetVersion, err := semver.NewVersion(version)
if err != nil {
return nil, fmt.Errorf("invalid target version %s: %v", version, err)
}
currentVersion, err := getCurrentDaemonVersion()
if err != nil {
klog.Warningf("Failed to get current olaresd version: %v, proceeding with installation", err)
} else {
if !currentVersion.LessThan(targetVersion) {
if !currentVersion.LessThan(&target.Version) {
return newExecutionRes(true, nil), nil
}
}
i.logFile = filepath.Join(commands.TERMINUS_BASE_DIR, "versions", "v"+version, "logs", "install.log")
i.logFile = filepath.Join(commands.TERMINUS_BASE_DIR, "versions", "v"+target.Version.Original(), "logs", "install.log")
if err := i.refreshProgress(); err != nil {
return nil, fmt.Errorf("could not determine whether olaresd prepare is finished: %v", err)
}
@@ -83,7 +79,7 @@ func (i *prepareOlaresd) Execute(ctx context.Context, p any) (res any, err error
params := []string{
"prepare", "olaresd",
"--version", version,
"--version", target.Version.Original(),
"--base-dir", commands.TERMINUS_BASE_DIR,
}
if err = cmd.RunAsync_(ctx, cli.TERMINUS_CLI, params...); err != nil {

View File

@@ -2,9 +2,10 @@ package upgrade
import (
"context"
"fmt"
"github.com/beclab/Olares/daemon/pkg/cluster/state"
"os"
"github.com/beclab/Olares/daemon/pkg/cluster/state"
"github.com/beclab/Olares/daemon/pkg/commands"
)
@@ -23,35 +24,22 @@ func NewRemoveUpgradeTarget() commands.Interface {
}
func (i *removeUpgradeTarget) Execute(ctx context.Context, p any) (res any, err error) {
err = RemoveUpgradeFiles()
err = removeUpgradeTargetFile()
if err != nil {
return nil, err
}
state.CurrentState.UpgradingDownloadState = ""
state.CurrentState.UpgradingDownloadStep = ""
state.CurrentState.UpgradingDownloadProgress = ""
state.CurrentState.UpgradingDownloadProgressNum = 0
state.CurrentState.UpgradingDownloadError = ""
state.StateTrigger <- struct{}{}
err = state.CheckCurrentStatus(context.Background())
if err != nil {
return nil, fmt.Errorf("failed to refresh system state: %v", err)
}
return NewExecutionRes(true, nil), nil
}
func RemoveUpgradeFiles() error {
// attempt to remove all files whether they exist or not (idempotent)
files := []string{
commands.UPGRADE_TARGET_FILE,
commands.UPGRADE_DOWNLOADONLY_FILE,
commands.UPGRADE_DOWNLOADED_FILE,
func removeUpgradeTargetFile() error {
if err := os.Remove(commands.UPGRADE_TARGET_FILE); err != nil && !os.IsNotExist(err) {
return err
}
for _, file := range files {
if err := os.Remove(file); err != nil && !os.IsNotExist(err) {
return err
}
}
return nil
}

View File

@@ -1,6 +1,7 @@
package upgrade
import (
"github.com/distribution/distribution/v3/manifest/ocischema"
"math"
"regexp"
"strconv"
@@ -43,19 +44,34 @@ type progressKeyword struct {
// matches against "(x/y)"
var itemProcessProgressRE = regexp.MustCompile(`\((\d+)/(\d+)\)`)
func parseProgressFromItemProgress(line string) int {
func parseProgressFromItemProgress(line string) (int, int) {
matches := itemProcessProgressRE.FindAllStringSubmatch(line, 2)
if len(matches) != 1 || len(matches[0]) != 3 {
return 0
return 0, 0
}
indexStr, totalStr := matches[0][1], matches[0][2]
index, err := strconv.ParseFloat(indexStr, 64)
if index == 0 || err != nil {
return 0
return 0, 0
}
total, err := strconv.ParseFloat(totalStr, 64)
if total == 0 || err != nil {
return 0
return 0, 0
}
return int(math.Round((index / total) * 90.0))
cur := int(math.Round(index / total * 90))
var next int
if index < total {
next = int(math.Round((index + 1) / total * 90))
} else {
next = 99
}
return cur, next
}
type manifestComponent struct {
Type string `json:"type"`
Path string `json:"path"`
FileID string `json:"fileid"`
Size uint64 `json:"size"`
Manifest ocischema.Manifest `json:"manifest,omitempty"`
}

View File

@@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"github.com/beclab/Olares/daemon/pkg/cluster/state"
"io"
"os"
"path/filepath"
@@ -36,21 +37,23 @@ func NewUpgrade() commands.Interface {
{"ClearAppChartValues success", 10},
{"ClearBFLChartValues success", 15},
{"UpdateChartsInAppService success", 20},
{"UpgradeUserComponents success", 25},
{"UpdateReleaseFile success", 30},
{"UpgradeSystemComponents success", 35},
{"UpgradeSystemComponents success", 40},
{"UpgradeUserComponents success", 50},
{"UpdateReleaseFile success", 55},
{"UpdateOlaresVersion success", 60},
{"EnsurePodsUpAndRunningAgain", 70},
{"[Job] UpgradeOlares execute successfully", commands.ProgressNumFinished},
},
}
}
func (i *upgrade) Execute(ctx context.Context, p any) (res any, err error) {
version, ok := p.(string)
target, ok := p.(state.UpgradeTarget)
if !ok {
return nil, errors.New("invalid param")
}
i.logFile = filepath.Join(commands.TERMINUS_BASE_DIR, "versions", "v"+version, "logs", "upgrade.log")
i.logFile = filepath.Join(commands.TERMINUS_BASE_DIR, "versions", "v"+target.Version.Original(), "logs", "upgrade.log")
if err := i.refreshProgress(); err != nil {
return nil, fmt.Errorf("could not determine whether upgrade is finished: %v", err)
}
@@ -66,7 +69,7 @@ func (i *upgrade) Execute(ctx context.Context, p any) (res any, err error) {
params := []string{
"upgrade",
"--version", version,
"--version", target.Version.Original(),
"--base-dir", commands.TERMINUS_BASE_DIR,
}
if err = cmd.RunAsync_(ctx, cli.TERMINUS_CLI, params...); err != nil {
@@ -110,7 +113,7 @@ func (i *upgrade) refreshProgress() error {
}
filesize := info.Size()
tailsize := min(filesize, 4096)
tailsize := min(filesize, 8192)
t, err := tail.TailFile(i.logFile,
tail.Config{Follow: false, Location: &tail.SeekInfo{Offset: -tailsize, Whence: io.SeekEnd}})

View File

@@ -1,12 +1,17 @@
package upgrade
import (
"encoding/json"
"errors"
"fmt"
"github.com/beclab/Olares/daemon/cmd/terminusd/version"
"github.com/dustin/go-humanize"
"io"
"net/http"
"os"
"os/exec"
"strings"
"syscall"
"github.com/Masterminds/semver/v3"
)
@@ -34,25 +39,12 @@ func getCurrentCliVersion() (*semver.Version, error) {
}
func getCurrentDaemonVersion() (*semver.Version, error) {
cmd := exec.Command("olaresd", "--version")
output, err := cmd.Output()
v, err := semver.NewVersion(*version.RawVersion())
if err != nil {
return nil, fmt.Errorf("failed to execute olaresd --version: %v", err)
return nil, fmt.Errorf("invalid version of olaresd: %v", err)
}
// parse version from output
// expected format: "olaresd version: v${VERSION}"
parts := strings.Split(string(output), " ")
if len(parts) != 3 {
return nil, fmt.Errorf("unexpected version output format: %s", string(output))
}
version, err := semver.NewVersion(strings.TrimPrefix(strings.TrimSpace(parts[2]), "v"))
if err != nil {
return nil, fmt.Errorf("invalid version format: %v", err)
}
return version, nil
return v, nil
}
func downloadFile(url, filepath string) error {
@@ -97,3 +89,53 @@ func copyFile(src, dst string) error {
_, err = io.Copy(destFile, sourceFile)
return err
}
func unmarshalComponentManifestFile(path string) (map[string]manifestComponent, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
decoder := json.NewDecoder(f)
ret := make(map[string]manifestComponent)
if err := decoder.Decode(&ret); err != nil {
return nil, err
}
return ret, nil
}
// checks:
// 1. whether available space is enough
// 2. if the path is at the same partition with K8s root, whether disk space remains more than 10% after use
func tryToUseDiskSpace(path string, size uint64) error {
fs := syscall.Statfs_t{}
err := syscall.Statfs(path, &fs)
if err != nil {
return fmt.Errorf("failed to statfs path %s: %v", path, err)
}
kfs := syscall.Statfs_t{}
err = syscall.Statfs("/var/lib", &fs)
if err != nil {
return fmt.Errorf("failed to statfs K8s root path %s: %v", path, err)
}
total := fs.Blocks * uint64(fs.Bsize)
available := fs.Bavail * uint64(fs.Bsize)
var ksize uint64
if fs.Fsid == kfs.Fsid {
ksize = uint64(float64(total) * 0.11)
}
if available > size+ksize {
return nil
}
errStr := fmt.Sprintf("insufficient disk space, available: %s, required: %s", humanize.Bytes(available), humanize.Bytes(size))
if ksize > 0 {
errStr += fmt.Sprintf(", reserved for K8s: %s", humanize.Bytes(ksize))
}
return errors.New(errStr)
}

View File

@@ -15,6 +15,7 @@ import (
const (
DefaultContainerdConfigPath = "/etc/containerd/config.toml"
DefaultContainerdRootPath = "/var/lib/containerd"
)
func getConfig() (*serverconfig.Config, error) {

View File

@@ -108,6 +108,21 @@ func GetInternalIpv4Addr(opts ...any) (internalAddrs []*NetInterface, err error)
}
func GetHostIp() (addr string, err error) {
addrs, err := LookupHostIps()
if err != nil {
return
}
if len(addrs) == 0 {
err = errors.New("host ip not found")
return
}
addr = addrs[0]
return
}
func LookupHostIps() (addrs []string, err error) {
hostname, err := os.Hostname()
if err != nil {
klog.Error("get hostname error, ", err)
@@ -122,13 +137,20 @@ func GetHostIp() (addr string, err error) {
for _, ip := range ips {
ipv4 := ip.To4()
if ipv4 != nil {
addr = ipv4.String()
return
if ipv4 != nil && ipv4.IsGlobalUnicast() {
addr := ipv4.String()
addrs = append(addrs, addr)
}
}
err = errors.New("host ip not found")
if len(addrs) == 0 {
// lookup in hosts file
if ip, e := GetHostIpFromHostsFile(hostname); e == nil && len(ip) > 0 {
addrs = append(addrs, ip)
} else {
err = errors.New("host ip not found")
}
}
return
}

View File

@@ -7,16 +7,16 @@ import (
"k8s.io/klog/v2"
)
func ValidateJWS(token string) bool {
func ValidateJWS(token string) (bool, string) {
checkJWS, err := jws.CheckJWS(token, 20*60*1000)
if err != nil {
klog.Errorf("failed to check JWS: %v", err)
return false
return false, ""
}
if checkJWS == nil {
klog.Error("JWS validation failed: JWS is nil")
return false
return false, ""
}
// Convert to JSON with indentation
@@ -26,5 +26,5 @@ func ValidateJWS(token string) bool {
}
klog.Infof("JWS validation successful: %s", string(bytes))
return true
return true, checkJWS.OlaresID
}

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