Compare commits
103 Commits
fix/files_
...
ci/bump-ve
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f692d1ea02 | ||
|
|
fe86ef0190 | ||
|
|
ba13d6092b | ||
|
|
8180024d6d | ||
|
|
c05f82c4bb | ||
|
|
604b2191ce | ||
|
|
518d2a41ea | ||
|
|
bf292e2f55 | ||
|
|
896c6d76f9 | ||
|
|
ee4655d991 | ||
|
|
261bf0f9e0 | ||
|
|
48776c32bf | ||
|
|
9bbf270eb3 | ||
|
|
bab83ed0b3 | ||
|
|
62faa3e3b7 | ||
|
|
e9346f04c1 | ||
|
|
1df5121a4e | ||
|
|
2ecfc976d7 | ||
|
|
c38e00a825 | ||
|
|
8c801b8392 | ||
|
|
eaceeef30b | ||
|
|
339b375a89 | ||
|
|
b5b9d19bc3 | ||
|
|
0bcb2cd893 | ||
|
|
2b46e87baa | ||
|
|
d0351aed9c | ||
|
|
021338b4b7 | ||
|
|
d374133dd4 | ||
|
|
c330589424 | ||
|
|
a690b5a852 | ||
|
|
abc6bc01a6 | ||
|
|
a0513a8e6f | ||
|
|
b61a3233bb | ||
|
|
5b3072dc6f | ||
|
|
2cc580a453 | ||
|
|
3e63c3f34c | ||
|
|
d80fbfb5e5 | ||
|
|
cea8f8bd1b | ||
|
|
7cce5ec761 | ||
|
|
b705bb0814 | ||
|
|
7fcfb2139b | ||
|
|
f267639a82 | ||
|
|
42a10225cc | ||
|
|
39e3d453e2 | ||
|
|
96334c89af | ||
|
|
eb774e6e06 | ||
|
|
8be967ebf3 | ||
|
|
8f2a98745a | ||
|
|
e7303b0554 | ||
|
|
9aee9453fc | ||
|
|
c480beb4de | ||
|
|
8998dd48cf | ||
|
|
ed3713bd37 | ||
|
|
47bd343c6b | ||
|
|
931f2992f4 | ||
|
|
b3d8a2e718 | ||
|
|
0e2a5d7c0e | ||
|
|
3035453f8c | ||
|
|
267d92607c | ||
|
|
dce43cd081 | ||
|
|
3826c64e48 | ||
|
|
e398150e01 | ||
|
|
694c472aad | ||
|
|
62db7fe18a | ||
|
|
7e1674aa77 | ||
|
|
72d804b0c9 | ||
|
|
a91b20b7a0 | ||
|
|
fa92825ce9 | ||
|
|
0e04f416d7 | ||
|
|
e43055b0f3 | ||
|
|
f918614bd2 | ||
|
|
12f19b7d46 | ||
|
|
5c8f3ea2ff | ||
|
|
9b7635f244 | ||
|
|
a949e317ac | ||
|
|
f362396514 | ||
|
|
d4a1a44e39 | ||
|
|
95fdffb24f | ||
|
|
4c72114a4d | ||
|
|
e28371551b | ||
|
|
ef01c331e9 | ||
|
|
40b29d12d6 | ||
|
|
506bd3bc1d | ||
|
|
9d097f77b1 | ||
|
|
a71b536a80 | ||
|
|
8eb2d86f56 | ||
|
|
ea0404fe2b | ||
|
|
af8e3b172c | ||
|
|
e00018de59 | ||
|
|
6bba107fdd | ||
|
|
ffb96bcbfc | ||
|
|
a6e4a73af2 | ||
|
|
61d3dedbfd | ||
|
|
962e251691 | ||
|
|
b37adf2521 | ||
|
|
460603ae69 | ||
|
|
1197860c29 | ||
|
|
417c4b520b | ||
|
|
e1fa887e6c | ||
|
|
b2e84cfd21 | ||
|
|
e8f0054b4f | ||
|
|
cd6c89f724 | ||
|
|
3d3d85ca3e |
12
.github/workflows/check.yaml
vendored
12
.github/workflows/check.yaml
vendored
@@ -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:
|
||||
|
||||
4
.github/workflows/release-daily.yaml
vendored
4
.github/workflows/release-daily.yaml
vendored
@@ -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:
|
||||
|
||||
42
.github/workflows/release.yaml
vendored
42
.github/workflows/release.yaml
vendored
@@ -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
5
.gitignore
vendored
@@ -32,3 +32,8 @@ olares-cli-*.tar.gz
|
||||
cli/output
|
||||
daemon/output
|
||||
daemon/bin
|
||||
|
||||
docs/.vitepress/dist/
|
||||
docs/.vitepress/cache/
|
||||
node_modules
|
||||
.idea/
|
||||
@@ -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.
|
||||
|
||||
@@ -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)**: 用于存放数据库、消息队列等云原生组件的代码。
|
||||
|
||||
@@ -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)**: データベースやメッセージキューなどのクラウドネイティブコンポーネントのコードが含まれています。
|
||||
|
||||
@@ -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/
|
||||
@@ -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 |
@@ -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
|
||||
@@ -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: ""
|
||||
@@ -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 }}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
upgrade:
|
||||
minVersion: 1.12.0-1
|
||||
minVersion: 1.12.1-0
|
||||
|
||||
@@ -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 }}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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()...)
|
||||
|
||||
34
cli/go.mod
34
cli/go.mod
@@ -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
|
||||
|
||||
72
cli/go.sum
72
cli/go.sum
@@ -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=
|
||||
|
||||
@@ -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
|
||||
`)))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
`)))
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
21
cli/pkg/daemon/prepares.go
Normal file
21
cli/pkg/daemon/prepares.go
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
94
cli/pkg/upgrade/1_12_0_20250702.go
Normal file
94
cli/pkg/upgrade/1_12_0_20250702.go
Normal 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
|
||||
}
|
||||
50
cli/pkg/upgrade/1_12_0_20250723.go
Normal file
50
cli/pkg/upgrade/1_12_0_20250723.go
Normal 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)
|
||||
}
|
||||
112
cli/pkg/upgrade/1_12_0_20250730.go
Normal file
112
cli/pkg/upgrade/1_12_0_20250730.go
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
23
cli/pkg/upgrade/interfaces.go
Normal file
23
cli/pkg/upgrade/interfaces.go
Normal 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
|
||||
}
|
||||
54
cli/pkg/upgrade/modules.go
Normal file
54
cli/pkg/upgrade/modules.go
Normal 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,
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
4
cli/version/vendor.go
Normal file
@@ -0,0 +1,4 @@
|
||||
package version
|
||||
|
||||
var VENDOR = "main"
|
||||
var VENDOR_REPO_PATH = ""
|
||||
@@ -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:
|
||||
|
||||
@@ -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())
|
||||
|
||||
3
daemon/cmd/terminusd/version/vendor.go
Normal file
3
daemon/cmd/terminusd/version/vendor.go
Normal file
@@ -0,0 +1,3 @@
|
||||
package version
|
||||
|
||||
var VENDOR = "main"
|
||||
@@ -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
|
||||
|
||||
@@ -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=
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"), ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"`
|
||||
}
|
||||
|
||||
@@ -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}})
|
||||
|
||||
@@ -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)
|
||||
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
|
||||
const (
|
||||
DefaultContainerdConfigPath = "/etc/containerd/config.toml"
|
||||
DefaultContainerdRootPath = "/var/lib/containerd"
|
||||
)
|
||||
|
||||
func getConfig() (*serverconfig.Config, error) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user