Compare commits

...

256 Commits

Author SHA1 Message Date
dkeven
92771e650c fix(cli): bind config item to the effective command 2026-02-03 16:06:07 +08:00
eball
7dd688c645 app-service: add support for selecting GPU types in application installation (#2470)
* fix: failed release upgrade

* fix: helm upgrade do not use atomic param and allow upgrade failed release

* feat: add icon filed to nats event

* fix: v2 app stop

* fix: check k8s request before into installing state

* fix: add spec ports

* set appservice image tag to 0.4.77

* feat: add support for selecting GPU types in application installation (#2458)

* fix: failed release upgrade

* fix: helm upgrade do not use atomic param and allow upgrade failed release

* feat: add clickhouse support

* appservice image tag to 0.4.76

* feat: add icon filed to nats event

* chores: get all node gpu types

* feat: add support for selecting GPU types in application installation

* feat: enhance GPU type selection logic in application installation

* feat: replace hardcoded GPU type with constant for supported GPU selection

* feat: update app config methods to include selected GPU type and enhance validation for NVIDIA GPUs

* feat: update supported GPU handling to include default options and improve validation logic

* feat: update GPU resource handling to unset previous limits before setting new ones

* feat: refactor permission parsing to use exported function and update related calls

---------

Co-authored-by: hys <hysyeah@gmail.com>

* app-service: add support for selecting GPU types in application installation

---------

Co-authored-by: hys <hysyeah@gmail.com>
2026-02-03 13:02:54 +08:00
eball
7d12b792ea ci: bump version to 1.12.6 (#2471) 2026-02-03 13:02:39 +08:00
Power-One-2025
c37cb9e15d docs: fix a link issue (#2469) 2026-02-03 11:33:32 +08:00
Power-One-2025
c79c2fc253 fix a link issue 2026-02-03 11:22:14 +08:00
berg
32fe6513e6 desktop, settings, files, vault: fix multiple known issues (#2467)
feat: update login, system frontend, user service version
2026-02-02 23:05:05 +08:00
eball
12ec558b27 authelia: add user regulation for TOTP authentication attempts (#2466) 2026-02-02 21:37:46 +08:00
dkeven
375dfceacb fix(cli): unify config setting for release command (#2465) 2026-02-02 17:52:46 +08:00
dkeven
91aef38583 fix(cli): set node port range in minikube to allow smb service (#2460) 2026-02-02 11:19:54 +08:00
berg
e21d76da24 settings, user service: update wallpaper style (#2463)
feat: update system frontend and user service version
2026-02-02 11:19:25 +08:00
eball
9cba48e84f bfl: enhance user login background handling with style support (#2464)
* fix: myapps api add rawAppName field

* update bfl api image tag to v0.4.39

* feat: enhance user login background handling with style support (#2462)

* bfl: enhance user login background handling with style support

---------

Co-authored-by: hys <hysyeah@gmail.com>
2026-02-02 11:18:59 +08:00
salt
f0b8dbe888 feat: search upgrade to v0.1.6 (#2459)
Co-authored-by: ubuntu <you@example.com>
2026-02-02 11:18:42 +08:00
berg
cfb74ce1d2 settings: add settings new version and update provider api (#2456)
feat: add settings new version and update provider api
2026-01-28 23:53:53 +08:00
dkeven
5639d4844b refactor(cli): unify config of command line options and envs (#2453) 2026-01-28 23:53:11 +08:00
hysyeah
f74fcec59e appservice: v2 app stop (#2455)
* fix: failed release upgrade

* fix: helm upgrade do not use atomic param and allow upgrade failed release

* feat: add icon filed to nats event

* fix: v2 app stop

* fix: check k8s request before into installing state

* fix: add spec ports

* set appservice image tag to 0.4.77
2026-01-28 21:16:43 +08:00
simon
ddbb13533d download-server:add download err category && modify aria2 max concurrent (#2445)
download server
2026-01-27 11:47:55 +08:00
Meow33
b65a3e3514 docs: add storage expansion via CLI (#2409)
* docs: add storage expansion method

* docs: add guide to access Olares terminal

* Update zh.ts

* fix formatting and file directory

---------

Co-authored-by: yajing wang <413741312@qq.com>
2026-01-26 17:10:23 +08:00
Power-One-2025
1f110184bd docs: update free backup storage info for Olares Space (#2428) 2026-01-23 10:58:14 +08:00
hysyeah
90eed09f10 cli: upgrade l4-bfl-proxy to v0.3.10 (#2442) 2026-01-22 23:18:34 +08:00
hysyeah
44ccf86032 l4: skip invalid expose port (#2441)
fix: skip invalid expose port (#2434)
2026-01-22 21:45:56 +08:00
hysyeah
67425162c2 appservice: add clickhouse support (#2440)
* fix: failed release upgrade

* fix: helm upgrade do not use atomic param and allow upgrade failed release

* feat: add clickhouse support

* appservice image tag to 0.4.76
2026-01-22 21:43:04 +08:00
eball
8a786c7c5a daemon: change pcap open timeout to 1 millisecond to prevent close hang (#2439) 2026-01-22 21:42:33 +08:00
hysyeah
c026e82615 tapr: add clickhouse support (#2437)
* feat: add clickhouse support

* fix: dependabot alerts

* middleware-operator 0.2.32
2026-01-22 21:42:13 +08:00
dkeven
e29c7f264e feat(gpu): supports dynamic detection of hot plugged-in GPUs (#2435) 2026-01-22 21:41:26 +08:00
wiy
c98c855099 feat(olares-app): update version to v1.8.2 (#2433)
* feat(olares-app): update version to v1.8.2

* feat(olares-app): update version to v1.8.2
2026-01-22 00:06:13 +08:00
hysyeah
4ae552f33f bfl: myapps api add rawAppName (#2432)
* fix: myapps api add rawAppName field

* update bfl api image tag to v0.4.39
2026-01-22 00:05:42 +08:00
hysyeah
f2aad6d9f6 cli: feat amdgpu install (#2430) 2026-01-22 00:05:01 +08:00
dkeven
02bc4fafd5 feat(cli): collect nginx logs stored temporarily in some containers (#2429) 2026-01-22 00:04:29 +08:00
Power-One-2025
3091e40ff0 docs/update/olares-space-storage-info 2026-01-21 11:29:53 +08:00
eball
8d34cc995d daemon: modify mDNS registration method (#2427)
daemon: update zeroconf dependency to v0.2.5 and modify mDNS registration method
2026-01-19 23:28:29 +08:00
Yajing
a19e81a4a0 docs: refactor local access guide (#2419)
* docs: refactor local access guide

* Apply suggestions from code review

Co-authored-by: Meow33 <supermonkey03@163.com>

* address comments

---------

Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-19 21:59:08 +08:00
hysyeah
ee3f2a7df2 tapr: add max retry for delete action (#2426)
* tapr: upgrade pod template and image for PGCluster reconciliation (#2213)

* tapr: upgrade pod template and image for PGCluster reconciliation

* fix(ci): specify working directory in github action for tapr (#2215)

---------

Co-authored-by: dkeven <82354774+dkeven@users.noreply.github.com>

* tapr: upgrade pod template and image for PGCluster reconciliation

* fix(kvrocks): update init container image and pull policy configuration (#2331)

* tapr: change kvrocks running as root by default

* fix: add max retry for delete action

* tapr: update middleware-operator image tag to 0.2.31

---------

Co-authored-by: eball <liuy102@hotmail.com>
Co-authored-by: dkeven <82354774+dkeven@users.noreply.github.com>
2026-01-19 20:31:35 +08:00
eball
73ea65b004 hami: revert hami-core latest update (#2424) 2026-01-19 19:26:28 +08:00
wiy
4ef2e7124a feat(olares-app): update olares-app version to v1.7.7 (#2423) 2026-01-19 14:06:43 +08:00
wiy
ef46f91ec7 feat(olares-app): update new version to v1.7.6 (#2422)
fix(share): fixed the error message that appeared after exceeding the upload limit.
2026-01-16 23:57:38 +08:00
hysyeah
0f5a346d86 authelia: fix target url parse method (#2421) 2026-01-16 23:57:12 +08:00
salt
caa799e902 feat: optimize highlight segment order (#2420)
Co-authored-by: ubuntu <you@example.com>
2026-01-16 15:42:12 +08:00
Power-One-2025
2be5f6d108 docs: add lobechat tutorial (#2368)
* docs/feat/add-lobechat-tutorial

* docs/feat/fix-images

* docs/feat/lobechat-fixlink

* docs/feat/iterate-content

* docs/update/more-content

* docs/updaate/refine

* docs/feat/lobechat-refine

* docs/feat/add-lobechat-index

* docs/updates/fix-link

* Update docs/use-cases/lobechat.md

Co-authored-by: Meow33 <supermonkey03@163.com>

* Update docs/use-cases/lobechat.md

Co-authored-by: Meow33 <supermonkey03@163.com>

* Update docs/use-cases/lobechat.md

Co-authored-by: Meow33 <supermonkey03@163.com>

* Update docs/use-cases/lobechat.md

Co-authored-by: Meow33 <supermonkey03@163.com>

* docs/update/address-comments

* Apply suggestions from code review

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>

* docs/update/address-comment

* docs/update/conflict

* refine edit

* docs/updates/image-size-opt

* docs/update/resize

* Apply suggestions from code review

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>

* docs/update/add-faq

---------

Co-authored-by: Meow33 <supermonkey03@163.com>
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-15 23:29:06 +08:00
salt
05f3c8ffdc fix: fix meaningless word highlight (#2418)
Co-authored-by: ubuntu <you@example.com>
2026-01-15 19:30:06 +08:00
berg
c0e242b05c settings: update search origin (#2417)
feat: update system frontend version
2026-01-15 19:29:07 +08:00
Power-One-2025
7929e420b1 docs: add stirling-pdf tutorial (#2369) 2026-01-15 16:10:05 +08:00
Power-One-2025
66de213f43 docs/update/image-size-opt 2026-01-15 15:56:25 +08:00
Power-One-2025
2166cec66f docs/update/fixtoc 2026-01-15 15:37:44 +08:00
Power-One-2025
1a0f9727c4 Merge branch 'main' into docs/add-stirling-pdf-tutorial 2026-01-15 11:07:46 +08:00
hysyeah
810253fe94 kubeblocks: skip check pod spec,status image (#2414)
fix: skip check pod spec,status image
2026-01-14 23:57:45 +08:00
wiy
23429a6193 olares-app, login: update version to v1.7.4 (#2413) 2026-01-14 23:57:01 +08:00
salt
49e40f316f fix: fix english highight missing (#2412)
Co-authored-by: ubuntu <you@example.com>
2026-01-14 23:56:37 +08:00
eball
1e7b655826 daemon: handle missing auth token for WebSocket connections (#2411) 2026-01-14 23:56:09 +08:00
dkeven
adea16ce7e feat(gpu): update gpu plugin version to v2.6.8 (#2410) 2026-01-14 23:55:48 +08:00
Power-One-2025
c2222859a5 docs: add PDFMathTranslate tutorial (#2378)
* docs/feat/draft

* docs/update/more-content

* docs/updates/refine

* docs/update/fix-build-conflict

* docs/update/fix-broken-link

* Update docs/use-cases/pdfmathtranslate.md

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>

* Update docs/use-cases/pdfmathtranslate.md

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>

* Update docs/use-cases/pdfmathtranslate.md

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>

* Update docs/use-cases/pdfmathtranslate.md

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>

* Update docs/use-cases/pdfmathtranslate.md

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>

* Update docs/use-cases/pdfmathtranslate.md

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>

* Update docs/use-cases/pdfmathtranslate.md

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>

* docs/updates/compress-images

* Update docs/use-cases/pdfmathtranslate.md

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>

* Update docs/use-cases/pdfmathtranslate.md

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>

* Update docs/use-cases/pdfmathtranslate.md

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>

* Update docs/use-cases/pdfmathtranslate.md

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>

* docs/update/comments

* docs/update/refine

* Update docs/use-cases/pdfmathtranslate.md

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>

* Update docs/use-cases/pdfmathtranslate.md

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>

* Update docs/use-cases/pdfmathtranslate.md

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>

* Update docs/use-cases/pdfmathtranslate.md

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>

* Update docs/use-cases/pdfmathtranslate.md

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>

* docs/update/comment

* Update docs/use-cases/pdfmathtranslate.md

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>

* docs/update/fix-link

* Update docs/use-cases/pdfmathtranslate.md

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>

* docs/update/comment

---------

Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-14 23:17:55 +08:00
yyh
e7dde2ff51 user-service: update mtranserverv2 (#2408)
fix(user-service): update mtranserverv2
2026-01-13 23:57:31 +08:00
lovehunter9
d06c1e8a99 fix: files check disk space for upload link and copy (#2407) 2026-01-13 23:57:01 +08:00
dkeven
131faacce0 feat(cli): sync kubeconfig for the original user invoking sudo (#2406) 2026-01-13 23:56:08 +08:00
Meow33
8133704761 docs: add CLI docs for user, upgrade, and disk commands (#2383)
* docs: add CLI docs for user, upgrade, and disk commands

* docs: update based on comments

* docs: fix typo

* docs: refine formatting and add description for argument

* docs: resolve conflicts
2026-01-13 17:30:57 +08:00
Power-One-2025
09e61aecad docs/update/address-comment 2026-01-12 15:49:11 +08:00
Power-One-2025
bc5fd5fd82 Merge branch 'main' into docs/add-stirling-pdf-tutorial 2026-01-12 15:38:50 +08:00
Power-One-2025
1367355661 docs/update/address-comments 2026-01-12 15:36:38 +08:00
eball
2a506be19a ci: bump version to 1.12.5 (#2405) 2026-01-12 15:00:44 +08:00
Power-One-2025
30195f1513 Update docs/use-cases/stirling-pdf.md
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-12 14:42:28 +08:00
Power-One-2025
88b140ccc2 Update docs/use-cases/stirling-pdf.md
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-12 14:42:14 +08:00
Power-One-2025
39947f464c Update docs/use-cases/stirling-pdf.md
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-12 14:41:31 +08:00
Power-One-2025
698bdf96ed docs: remove outdated environment variables (#2394) 2026-01-12 14:05:52 +08:00
wiy
69e6ac35f8 feat(olares-app): file upload add total_size parameter (#2404)
* feat(olares-app): file upload add total_size parameter

* fix: infisical update

---------

Co-authored-by: aby913 <aby913@163.com>
2026-01-12 14:01:09 +08:00
salt
f41e66b39a feat: search3 upgrade to v0.1.2 for juicefs watch (#2403)
Co-authored-by: ubuntu <you@example.com>
2026-01-12 14:00:32 +08:00
dkeven
1a36faaf6d feat(cli): add upgrader for main line version 1.12.4 (#2402) 2026-01-12 13:59:24 +08:00
Yajing
cbdd08d237 docs: add faqs and refactor help docs (#2376)
* docs: add faqs and refactor help docs

* align zh-cn
2026-01-10 12:56:33 +08:00
dkeven
2fd9d23371 feat(cli): optimize and unify pod readiness check logic (#2393) 2026-01-09 16:10:12 +08:00
hysyeah
f1714534db appservice: delay create nats conn (#2392)
* fix: failed release upgrade

* fix: helm upgrade do not use atomic param and allow upgrade failed release

* fix: delay create nats conn (#2391)

* set appservice image tag and add readiness probe
2026-01-09 15:59:35 +08:00
lovehunter9
9bc66369df fix: files sync reconnection error msg and upload chuck access token (#2390) 2026-01-09 15:22:31 +08:00
Meow33
ba85b0f60d docs/remove outdated env variables 2026-01-09 14:45:07 +08:00
aby913
7c2624d418 market: skip systemenv check in the cloud, add nsfw trigger in settings (#2387)
market: fix systemenv in public, add nsfw trigger in settings
2026-01-08 23:36:40 +08:00
hysyeah
7eb21516d0 authelia,lldap: distinguish error message in firstfactor authentication (#2389) 2026-01-08 23:35:52 +08:00
berg
266aef8616 system frontend: add the NSFW feature (#2388)
* market: fix sync app state on nats, add log levels

* feat: update system frontend to v1.6.42

---------

Co-authored-by: aby913 <aby913@163.com>
2026-01-08 23:35:09 +08:00
aby913
3755bede0c backup: folder set to UID 1000 (#2386)
* backup: backup folder set to UID 1000

* backup: folder set to UID 1000
2026-01-08 23:33:01 +08:00
hysyeah
cca39eed7e appservice: fix inorder nats event (#2384)
* fix: failed release upgrade

* fix: helm upgrade do not use atomic param and allow upgrade failed release

* fix: push all nats event to queue  (#2374)

* fix: push all nats event to queue and via one connection

* fix: wrap yaml decode error

* update appservice image tag to 0.4.74
2026-01-08 23:31:25 +08:00
dkeven
b27b90b9a8 fix(bfl): add backend cluster API handler for stats report (#2382)
* fix(bfl): add backend cluster API handler for stats report (#2381)

* chore(bfl): update image version to v0.4.38
2026-01-08 23:30:37 +08:00
eball
119ec75234 cli: enhance CUDA library handling for WSL with strace detection (#2380) 2026-01-08 23:30:05 +08:00
aby913
8739bfc040 market: fix sync app state on nats, add log levels, nsfw label (#2379)
market: fix sync app state on nats, add log levels
2026-01-08 00:54:34 +08:00
Yajing
6304739725 docs: merge 1.12.3 docs to main (#2377) 2026-01-07 19:25:30 +08:00
yajing wang
f8f452b27f fix formatting 2026-01-07 19:12:03 +08:00
yajing wang
36acf0384d fix conflicts 2026-01-07 17:09:41 +08:00
Meow33
aa5b073b5c docs: update based on comments 2026-01-07 16:58:44 +08:00
Meow33
18dfae6c87 docs: add steam guide zh cn 2026-01-07 16:58:42 +08:00
Meow33
a54445db8b docs: address comments 2026-01-07 16:58:20 +08:00
Meow33
375e2c4f63 Apply suggestions from code review
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-07 16:58:20 +08:00
Meow33
c366b56de9 docs: update based on suggestions 2026-01-07 16:58:20 +08:00
Meow33
85d90a36ed docs: update based on suggestions 2026-01-07 16:58:20 +08:00
Meow33
172c5342d8 docs: update file search guide 2026-01-07 16:58:20 +08:00
Yajing
dcc0ab1cd2 Update docs/zh/manual/olares/wise/index.md 2026-01-07 16:58:20 +08:00
Yajing
b078f80b5a fix wording 2026-01-07 16:58:20 +08:00
Meow33
854e25096f docs: update based on comments 2026-01-07 16:58:20 +08:00
Meow33
78949de2b6 docs: update based on comments 2026-01-07 16:58:20 +08:00
Meow33
bd72cb8067 docs: update based on comments 2026-01-07 16:58:20 +08:00
Meow33
3b9f0d33a3 docs: update based on suggestions 2026-01-07 16:58:20 +08:00
Meow33
3e782c6cea Apply suggestions from code review
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-07 16:58:20 +08:00
Meow33
28c2979db0 docs: update based on suggestions 2026-01-07 16:58:20 +08:00
Meow33
fc8ade657d docs: update based on comments 2026-01-07 16:58:20 +08:00
Meow33
74c80a9c7e Apply suggestions from code review
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-07 16:58:20 +08:00
Meow33
51a06f8964 docs: update relevant docs 2026-01-07 16:58:18 +08:00
Meow33
0c50d93d77 docs: refactor guide for gpu management 2026-01-07 16:57:42 +08:00
Power-One-2025
17b8d2d96e docs/updates/comment 2026-01-07 16:57:42 +08:00
Power-One-2025
5b5e5d289c docs/updates/comment 2026-01-07 16:57:42 +08:00
Power-One-2025
b113f66c4f Update docs/manual/olares/market/clone-apps.md
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-07 16:57:42 +08:00
Power-One-2025
bbbe3ecf9b docs/update/comment 2026-01-07 16:57:42 +08:00
Power-One-2025
b7ff5db985 docs/update/comments 2026-01-07 16:57:42 +08:00
Power-One-2025
f39e359ef8 Update docs/manual/olares/market/purchase-paid-apps.md
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-07 16:57:42 +08:00
Power-One-2025
4a80ef6148 Update docs/.vitepress/en.ts
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-07 16:57:42 +08:00
Power-One-2025
c4af7a5783 docs/updates/comment 2026-01-07 16:57:42 +08:00
Power-One-2025
5c498fbe18 Update docs/manual/olares/market/purchase-paid-apps.md
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-07 16:57:42 +08:00
Power-One-2025
4fbe32b141 docs/update/comment 2026-01-07 16:57:42 +08:00
Power-One-2025
46fc840302 docs/update/address-comments 2026-01-07 16:57:42 +08:00
Power-One-2025
5677026de0 Update docs/manual/olares/market/clone-apps.md
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-07 16:57:42 +08:00
Power-One-2025
4d95152e0a Update docs/manual/olares/market/clone-apps.md
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-07 16:57:42 +08:00
Power-One-2025
9560985965 Update docs/manual/olares/market/clone-apps.md
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-07 16:57:42 +08:00
Power-One-2025
1b6d90c2a5 Update docs/manual/olares/market/purchase-paid-apps.md
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-07 16:57:42 +08:00
Power-One-2025
2c73b3b7f8 Update docs/manual/olares/market/purchase-paid-apps.md
Co-authored-by: Yajing <110797546+fnalways@users.noreply.github.com>
2026-01-07 16:57:42 +08:00
Power-One-2025
22c52398ed docs/update/fix-comment 2026-01-07 16:57:42 +08:00
Power-One-2025
d1e55515d4 docs/updates/fix-note-style 2026-01-07 16:57:42 +08:00
Power-One-2025
5db251520d docs/updates/fix-comments 2026-01-07 16:57:42 +08:00
Power-One-2025
d2b630c7b4 docs/update/fix-links 2026-01-07 16:57:40 +08:00
Power-One-2025
0debd332a8 docs/updates/fix-toc 2026-01-07 16:54:40 +08:00
Power-One-2025
9a2c58e3fa docs/updates/market-comments-fix 2026-01-07 16:54:38 +08:00
Meow33
b8842cfe61 docs: update based on suggestions 2026-01-07 16:54:02 +08:00
Meow33
70e170b71a docs: update larepass upgrade descriptions 2026-01-07 16:54:02 +08:00
Power-One-2025
e975e4aec8 docs/update/files-index-update 2026-01-07 16:54:02 +08:00
Power-One-2025
9d6d242625 docs/update/refine-images 2026-01-07 16:54:02 +08:00
Power-One-2025
86d7b985a2 docs/update/preview-edit-files 2026-01-07 16:54:01 +08:00
Power-One-2025
31a2b3ee28 docs/updates/add-images 2026-01-07 16:54:01 +08:00
Power-One-2025
9aa7e0b108 docs/update/add-image-share 2026-01-07 16:54:01 +08:00
Power-One-2025
9092f28458 docs/updates/files-comments-fix 2026-01-07 16:54:01 +08:00
Yajing
f925268cd4 fix typo
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:54:01 +08:00
yajing wang
e1c19f7327 update intro & screenshots 2026-01-07 16:54:01 +08:00
Yajing
5e925e0cb6 Apply suggestions
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:54:01 +08:00
yajing wang
6a0885d37d fix lint 2026-01-07 16:54:00 +08:00
yajing wang
3e46af80e1 docs: add play games directly on olares device 2026-01-07 16:53:12 +08:00
yajing wang
74c48b81fb docs: update windows use case 2026-01-07 16:52:03 +08:00
Power-One-2025
56aed6b683 Update docs/zh/manual/olares/settings/gpu-resource.md 2026-01-07 16:52:03 +08:00
Meow33
cbfcf3d3aa docs: update screenshots 2026-01-07 16:52:03 +08:00
Meow33
fd23e52723 docs: update based on suggestions 2026-01-07 16:52:03 +08:00
Meow33
b48368b934 docs: update guide for manage gpu usage 2026-01-07 16:52:03 +08:00
Meow33
ca9ce45353 docs: update based on suggestions 2026-01-07 16:52:03 +08:00
Meow33
fa148969c5 docs: update en version based on suggestions and update translation 2026-01-07 16:52:03 +08:00
Meow33
21c1884bb8 docs: update tutorials for Wise 2026-01-07 16:52:03 +08:00
Meow33
b517d08981 docs: update based on suggestions 2026-01-07 16:52:03 +08:00
Meow33
73e2cd0eb4 docs: update based on suggestions 2026-01-07 16:52:03 +08:00
Meow33
a631db1e9e docs: add guide for search under settings 2026-01-07 16:52:03 +08:00
Meow33
f3b59b9b3e docs: add larepass upgrade restart prompt 2026-01-07 16:52:03 +08:00
Power-One-2025
910bf02b48 Update docs/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:52:03 +08:00
Power-One-2025
dcc909a06e Update docs/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:52:03 +08:00
Power-One-2025
1238ad01f1 Update docs/zh/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:52:03 +08:00
Power-One-2025
77ee176f5e Update docs/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:52:03 +08:00
Power-One-2025
1d9c3f7b4a Update docs/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:52:03 +08:00
Power-One-2025
8a52737f89 docs/update/refine-description 2026-01-07 16:52:03 +08:00
Power-One-2025
bd7c46a663 docs/update/table-line-wrap 2026-01-07 16:52:03 +08:00
Power-One-2025
9ee4af9040 docs/update/add-faq-resume-app 2026-01-07 16:52:03 +08:00
Power-One-2025
fc86bbadc2 docs/update/image 2026-01-07 16:52:03 +08:00
Power-One-2025
52118b1126 docs/updates/clond-apps-images 2026-01-07 16:52:01 +08:00
Power-One-2025
76be9e82c0 docs/updates/resize-image 2026-01-07 16:51:21 +08:00
Power-One-2025
478d9f28c8 Update docs/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:51:21 +08:00
Power-One-2025
114ed5ad7b Update docs/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:51:21 +08:00
Power-One-2025
c85b23d9a9 Update docs/zh/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:51:21 +08:00
Power-One-2025
fbc61764ca Update docs/zh/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:51:21 +08:00
Power-One-2025
d866966531 Update docs/zh/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:51:21 +08:00
Power-One-2025
d140849d7c Update docs/zh/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:51:21 +08:00
Power-One-2025
679ddb0f8d Update docs/zh/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:51:21 +08:00
Power-One-2025
0ec0a5a4ac Update docs/zh/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:51:21 +08:00
Power-One-2025
74ecf9f73d Update docs/zh/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:51:21 +08:00
Power-One-2025
028c5c7bdb Update docs/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:51:21 +08:00
Power-One-2025
f3ab03becc docs/update/consistency 2026-01-07 16:51:21 +08:00
Power-One-2025
e408da75a4 docs/update/mobile-app-image-style 2026-01-07 16:51:21 +08:00
Power-One-2025
8ffbc82ebd docs/update/formatting-fix-zh 2026-01-07 16:51:21 +08:00
Power-One-2025
304dbf69c5 docs/updates/formatting-fix 2026-01-07 16:51:21 +08:00
Power-One-2025
66b0144b40 docs/update/add-restore-purchased-app 2026-01-07 16:51:21 +08:00
Power-One-2025
e91a76f92f docs/updates/dev-comments 2026-01-07 16:51:21 +08:00
Power-One-2025
45cd406cd4 docs/updates/add-images-paid-app 2026-01-07 16:51:21 +08:00
Power-One-2025
7ef7ae9335 docs/feat/purchase-paid-apps 2026-01-07 16:51:21 +08:00
Power-One-2025
f2f342a28a Update docs/zh/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:51:21 +08:00
Power-One-2025
fdca458e4f docs/update/clone-apps 2026-01-07 16:51:21 +08:00
Power-One-2025
b7141373b7 docs/updates/add-note 2026-01-07 16:51:21 +08:00
Power-One-2025
21118c8e95 docs/updates/single-source-for-sync 2026-01-07 16:51:19 +08:00
Power-One-2025
307a6bb502 docs/updates/address comments on share files 2026-01-07 16:50:00 +08:00
Power-One-2025
91ec932c95 Update docs/manual/olares/files/add-edit-download.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:50:00 +08:00
Power-One-2025
a1cb16cfe9 docs/feat/share-files 2026-01-07 16:49:57 +08:00
Power-One-2025
aec5e178b3 docs/update/add-title-level 2026-01-07 16:48:15 +08:00
Power-One-2025
2624ea5dc5 docs/updates/address comment on files sync 2026-01-07 16:48:15 +08:00
Power-One-2025
0d1bae720d Update docs/manual/olares/files/add-edit-download.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:48:15 +08:00
Power-One-2025
96520a8bc3 docs/feature/sync-files-to-local 2026-01-07 16:48:15 +08:00
Power-One-2025
27b9356037 Update docs/zh/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:48:15 +08:00
Power-One-2025
c289d5837c Update docs/zh/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:48:15 +08:00
Power-One-2025
e6f9922951 address comment 2026-01-07 16:48:15 +08:00
Power-One-2025
a3ad8ce78c Update market.md 2026-01-07 16:48:15 +08:00
Power-One-2025
c70587062a Update market.md 2026-01-07 16:48:14 +08:00
Power-One-2025
f7306b66dc Update market.md 2026-01-07 16:48:14 +08:00
Power-One-2025
325bfeb90d Update market.md 2026-01-07 16:48:14 +08:00
Power-One-2025
bfc3ca0720 Update docs/manual/olares/market.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 16:48:14 +08:00
Power-One-2025
ef071e43ca docs: new app clone feature to Market 2026-01-07 16:48:14 +08:00
Power-One-2025
7440e85c2e docs/update/address-comments 2026-01-07 14:23:29 +08:00
Power-One-2025
d71747928c Update docs/use-cases/stirling-pdf.md
Co-authored-by: Meow33 <supermonkey03@163.com>
2026-01-07 11:31:48 +08:00
eball
473898a715 daemon: bump zeroconf dependency to v0.2.4 (#2375)
daemon: bump zeroconf dependency to v0.2.4 and increase log verbosity for server events
2026-01-07 00:10:40 +08:00
lovehunter9
637b1839f7 fix: files sync reconnection at pipe client when sending has met broken pipe (#2373) 2026-01-05 23:46:42 +08:00
wiy
1f1c1a8d3b olares-app: update vault add websocket (#2372)
wizard: update qrcode size
2026-01-05 23:46:03 +08:00
dkeven
1ddcc3bd4c fix(gpu): handle scheduler inconsistency and device stuck in unhealthy (#2371) 2026-01-05 23:44:50 +08:00
dkeven
96a2eb524a fix(cli): remove olares name when uninstalling to prepare (#2370) 2026-01-05 23:44:08 +08:00
Power-One-2025
b20d5c0876 docs/feat/stirlingpdf-refine 2026-01-05 14:39:56 +08:00
Power-One-2025
c4fc3198bb docs/feat/stirlingpdf-add-index 2026-01-05 13:42:47 +08:00
Power-One-2025
260b6154f3 docs/feat/stirlingpdf-more 2026-01-05 13:38:33 +08:00
Power-One-2025
ecfcd0d1d8 docs/feat/content-add 2026-01-04 22:29:05 +08:00
eball
be7f3b3c3f daemon: update serial filtering logic to use suffix matching (#2367) 2026-01-04 20:44:41 +08:00
hysyeah
99c6d3860d app-service: app upgrade set tailscale acl (#2362)
* fix: failed release upgrade

* fix: helm upgrade do not use atomic param and allow upgrade failed release

* fix: app upgrade set tailscale acl (#2357)

* fix: increase wait timeout for namespace delete

* fix: update app-service image tag to 0.4.73
2025-12-31 23:58:57 +08:00
berg
9f56cf0f05 login, system frontend: update qrcode size (#2361)
feat: update login version and system frontend version
2025-12-31 23:58:11 +08:00
Yajing
76c8e93822 docs: fix misplaced braces in studio tutorial (#2358) 2025-12-31 21:41:30 +08:00
yajing wang
d38d0d0e1d docs: fix misplaced braces in studio tutorial 2025-12-31 20:59:24 +08:00
hysyeah
65b32c7c41 kubeblocks-addon: fix kubeblocks-addon rabbitmq image pull policy (#2356)
fix: kubeblocks-addon rabbitmq image pull policy
2025-12-31 15:10:26 +08:00
wiy
f6f14e8d9a olares app: update settings create sub-accounts to block domain (#2355) 2025-12-31 15:09:33 +08:00
eball
f8653692b1 daemon: update DID gate URL handling in JWS validation and resolution (#2354) 2025-12-31 13:07:22 +08:00
eball
5264df60cc cli: update ResolveOlaresName and CheckJWS to accept gateUrl parameter (#2352) 2025-12-31 00:11:35 +08:00
berg
1a200ed17c system frontend: update market topic ids (#2351)
feat: update system frontend version
2025-12-30 21:17:53 +08:00
eball
48fdaa5481 daemon: enhance USB monitoring with serial filtering support (#2349)
* daemon: enhance USB monitoring with serial filtering support

* daemon: add check for USB devices with serial before mounting

* daemon: implement FilterBySerial function for USB device filtering
2025-12-30 21:17:15 +08:00
eball
570fe070c9 k3s: update eviction thresholds and image GC settings (#2348)
k3s: update eviction thresholds and image GC settings for improved resource management
2025-12-30 21:16:54 +08:00
lovehunter9
6b18bbd94d fix: files change usb watcher to retry and change sync reconnection to callback (#2342)
* fix: files change usb watcher to retry and change sync reconnection to callback

* fix: create folder and rsync chown to 1000
2025-12-30 21:15:34 +08:00
Yajing
c6836f9859 docs: update nav to reflect the latest changes (#2343) 2025-12-30 17:41:39 +08:00
yajing wang
288869d91d docs: update nav to reflect the latest changes 2025-12-29 20:55:06 +08:00
hysyeah
8ea8a0857e app-service: add helm upgrade timeout (#2339)
* fix: failed release upgrade

* fix: update appservice image tag to 0.4.71

* fix: helm upgrade do not use atomic param and allow upgrade failed release
2025-12-27 14:05:22 +08:00
eball
87674cc5d9 opa: update image validation to exclude alpine and mariadb images (#2337) 2025-12-27 14:04:31 +08:00
berg
11f556e9af system frontend, market backend: verify the update time when the app status is changed. (#2336)
feat: update system frontend version
2025-12-27 14:04:14 +08:00
simon
d2d3195fea download-server: modify ytdlp support domain (#2335)
download
2025-12-27 14:03:45 +08:00
hysyeah
ad3b138284 app-service: fix exposeport upgrade (#2334)
* fix: exposeport upgrade (#2333)

* update appservice tag to 0.4.70
2025-12-26 19:41:14 +08:00
eball
ff609db1aa tapr: change kvrocks to run as root by default (#2332)
* tapr: upgrade pod template and image for PGCluster reconciliation (#2213)

* tapr: upgrade pod template and image for PGCluster reconciliation

* fix(ci): specify working directory in github action for tapr (#2215)

---------

Co-authored-by: dkeven <82354774+dkeven@users.noreply.github.com>

* tapr: upgrade pod template and image for PGCluster reconciliation

* fix(kvrocks): update init container image and pull policy configuration (#2331)

* tapr: change kvrocks running as root by default

---------

Co-authored-by: dkeven <82354774+dkeven@users.noreply.github.com>
2025-12-26 19:40:48 +08:00
dkeven
43c6bff906 feat(cli): collect more logs for K8s resources (#2330) 2025-12-26 15:36:02 +08:00
berg
b28dac652c system fronted, market backend, chart repo: add suspend app function (#2329)
feat: update market version
2025-12-26 14:46:38 +08:00
lovehunter9
fbb5c08227 fix: files sync reconnection (#2327) 2025-12-25 19:05:04 +08:00
dkeven
a04d363597 fix(daemon): update module appservice dependency to fix security issues (#2326) 2025-12-25 17:21:19 +08:00
dkeven
994d2b9b91 fix(cli): update module appservice dependency to fix security issues (#2325) 2025-12-25 17:20:47 +08:00
dependabot[bot]
909b7656fd chore(deps): bump github.com/open-policy-agent/opa from 0.18.0 to 1.4.0 in /infrastructure/kubesphere (#2324)
chore(deps): bump github.com/open-policy-agent/opa

Bumps [github.com/open-policy-agent/opa](https://github.com/open-policy-agent/opa) from 0.18.0 to 1.4.0.
- [Release notes](https://github.com/open-policy-agent/opa/releases)
- [Changelog](https://github.com/open-policy-agent/opa/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-policy-agent/opa/compare/v0.18.0...v1.4.0)

---
updated-dependencies:
- dependency-name: github.com/open-policy-agent/opa
  dependency-version: 1.4.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-25 14:11:30 +08:00
dependabot[bot]
c61260cb5a chore(deps): bump github.com/docker/docker from 20.10.7+incompatible to 25.0.13+incompatible in /infrastructure/kubesphere (#2323)
chore(deps): bump github.com/docker/docker in /infrastructure/kubesphere

Bumps [github.com/docker/docker](https://github.com/docker/docker) from 20.10.7+incompatible to 25.0.13+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v20.10.7...v25.0.13)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-version: 25.0.13+incompatible
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-25 14:04:15 +08:00
salt
fed1a60c63 chore: keep three days log (#2319)
Co-authored-by: ubuntu <you@example.com>
2025-12-25 13:59:13 +08:00
wiy
7062408f5d fix(olares-app): fix some secret warning (#2320) 2025-12-25 13:58:38 +08:00
dependabot[bot]
583ec7730c chore(deps): bump github.com/emicklei/go-restful from 2.14.3+incompatible to 2.16.0+incompatible in /infrastructure/kubesphere (#2322)
chore(deps): bump github.com/emicklei/go-restful

Bumps [github.com/emicklei/go-restful](https://github.com/emicklei/go-restful) from 2.14.3+incompatible to 2.16.0+incompatible.
- [Release notes](https://github.com/emicklei/go-restful/releases)
- [Changelog](https://github.com/emicklei/go-restful/blob/v3/CHANGES.md)
- [Commits](https://github.com/emicklei/go-restful/compare/v2.14.3...v2.16.0)

---
updated-dependencies:
- dependency-name: github.com/emicklei/go-restful
  dependency-version: 2.16.0+incompatible
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-25 13:58:00 +08:00
dependabot[bot]
e9f3b23ac9 chore(deps): bump golang.org/x/crypto from 0.0.0-20210817164053-32db794688a5 to 0.45.0 in /framework/kube-state-metrics (#2321)
chore(deps): bump golang.org/x/crypto in /framework/kube-state-metrics

Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.0.0-20210817164053-32db794688a5 to 0.45.0.
- [Commits](https://github.com/golang/crypto/commits/v0.45.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-version: 0.45.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-25 13:55:03 +08:00
dkeven
7f09420bdf fix(appservice): update depedencies to fix some vulnerabilities (#2314)
* refactor(appservice): rename go module to fit into the main repo (#2311)

* fix(appservice): update depedencies to fix some vulnerabilities (#2313)
2025-12-25 11:30:55 +08:00
salt
c93869db02 feat: use poppler-utils and catdoc (#2318)
Co-authored-by: ubuntu <you@example.com>
2025-12-25 11:09:09 +08:00
wiy
2f23def478 feat(olares-app): update olares-app version to v1.6.31 (#2317)
* feat(olares-app): update olares-app version to v1.6.31

* feat: update social keys
2025-12-25 00:21:50 +08:00
dkeven
4c5c43982a fix(cli): handle invalid modprobe sys conf when upgrading GPU driver (#2316) 2025-12-25 00:21:18 +08:00
aby913
a2a6c581c2 infisical: secret limit up to 1000 per minute (#2315) 2025-12-25 00:20:43 +08:00
eball
8b1a7e11f5 opa: enhance image trust validation by trimming docker.io prefix (#2308)
* opa: enhance image trust validation by trimming docker.io prefix

* fix: correct typo in image trimming function name in untrusted image checks
2025-12-25 00:20:08 +08:00
dependabot[bot]
2181adb67c chore(deps): bump github.com/gofiber/fiber/v2 from 2.49.2 to 2.52.9 in /platform/tapr (#2309)
chore(deps): bump github.com/gofiber/fiber/v2 in /platform/tapr

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-24 15:47:43 +08:00
wiy
e1b0bd7875 feat(wizard): remove the option to select an FRP node when activating a sub-account. (#2305)
feat(wizard): remove sub-account select frp node
2025-12-23 23:50:10 +08:00
dkeven
e465a2d8fc feat(bfl): reuse owner's proxy config when activating sub-accounts (#2302)
* feat(bfl): reuse owner's proxy config when activating sub-accounts (#2300)

* bfl: update image version to v0.4.37
2025-12-23 23:49:30 +08:00
eball
70d0ae1ff5 opa: add trusted image for kldtks image repo (#2301) 2025-12-23 23:49:01 +08:00
eball
e52db36045 daemon: improve umount handling for broken USB devices (#2299)
* daemon: improve umount handling for broken USB devices

* fix: update package name from @didvault/app to @olares/app in package-lock.json
2025-12-23 23:48:40 +08:00
hysyeah
1935b1fbb6 app-service: fix entrance policy update by upgrade (#2298)
* fifx: entrance policy update by upgrade

* fix: skip app update if deployment not changed

* fix: update app-service image tag to 0.4.69
2025-12-23 23:48:11 +08:00
salt
5dc69bf80e fix: search3 fix extract doc error, block task (#2296)
Co-authored-by: ubuntu <you@example.com>
2025-12-23 21:03:04 +08:00
wiy
e839d5ae41 feat(olares-app): update olares-app README.md (#2292) 2025-12-23 11:31:13 +08:00
wiy
e89c6f35cc feat(olares-app): update olares-app to fix some bugs (#2293) 2025-12-23 11:29:27 +08:00
hysyeah
c4a7c81777 app-service: feat add deviceName to helm values (#2291)
* feat: add deviceName to helm values (#2289)

* update appservice image to 0.4.68
2025-12-22 21:23:55 +08:00
eball
a69b5d40a9 ci: skip processing vendor files in Olares.yaml (#2290) 2025-12-22 21:23:18 +08:00
740 changed files with 12316 additions and 11663 deletions

View File

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

View File

@@ -41,7 +41,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.24.3
go-version: 1.24.11
- name: Install x86_64 cross-compiler
run: sudo apt-get update && sudo apt-get install -y build-essential

View File

@@ -42,7 +42,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.22.1
go-version: 1.24.11
- name: install udev-devel and pcap-devel
run: |

View File

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

View File

@@ -54,6 +54,7 @@ rules:
- "/system/configuration/encoding"
- "/api/search/get_directory/"
- "/api/search/sync_search/"
- "/api/share/smb_share_user/"
verbs: ["*"]
---

View File

@@ -317,7 +317,7 @@ spec:
chown -R 1000:1000 /uploadstemp && \
chown -R 1000:1000 /appdata
- name: olares-app-init
image: beclab/system-frontend:v1.6.28
image: beclab/system-frontend:v1.8.5
imagePullPolicy: IfNotPresent
command:
- /bin/sh
@@ -439,7 +439,7 @@ spec:
- name: NATS_SUBJECT_VAULT
value: os.vault.{{ .Values.bfl.username}}
- name: user-service
image: beclab/user-service:v0.0.81
image: beclab/user-service:v0.0.85
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3000
@@ -1356,6 +1356,17 @@ data:
proxy_set_header Connection '$connection_upgrade';
more_set_headers 'Upgrade: $http_upgrade';
}
location /api/refresh {
add_header Access-Control-Allow-Headers "access-control-allow-headers,access-control-allow-methods,access-control-allow-origin,content-type,x-auth,x-unauth-error,x-authorization";
add_header Access-Control-Allow-Methods "PUT, GET, DELETE, POST, OPTIONS";
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Credentials true;
proxy_pass http://authelia-backend-svc:9091;
proxy_set_header Host $host;
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
add_header X-Frame-Options SAMEORIGIN;
}
location / {
proxy_pass http://headscale-server-svc:8080;
proxy_http_version 1.1;

View File

@@ -12,4 +12,5 @@ rules:
- "/task/*"
- "/search/*"
- "/monitorsetting/*"
- "/file/*"
verbs: ["*"]

View File

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

View File

@@ -17,4 +17,203 @@ This directory contains the code for system applications, primarily for LarePass
| Settings | A system configuration application. |
| Dashboard | An app for monitoring system resource usage. |
| Control Hub | The console for Olares, providing precise and autonomous control over the system and its environment. |
| DevBox | A development tool for building and deploying Olares applications. |
| Studio | A development tool for building and deploying Olares applications. |
# Local Development Guide
This document describes how to start and develop various sub-projects locally.
## Available Projects
| Project | Command | Port |
|---------|---------|------|
| Desktop | `npm run dev:desktop` | 1090 |
| Files | `npm run dev:files` | 5090 |
| Settings | `npm run dev:settings` | 9000 |
| Market | `npm run dev:market` | 8080 |
| Vault | `npm run dev:vault` | 8090 |
| Wise | `npm run dev:wise` | 8100 |
| Dashboard | `npm run dev:dashboard` | 9003 |
| Control Hub | `npm run dev:hub` | 9002 |
| Share | `npm run dev:share` | 5070 |
| Editor | `npm run dev:editor` | 9100 |
| Preview | `npm run dev:preview` | 9001 |
| Studio | `npm run dev:studio` | 9001 |
## Step 1: Modify Local Hosts File
Projects require access through a specific domain name. You need to configure the local hosts file first.
### macOS / Linux
1. Open terminal and edit the hosts file with administrator privileges:
```bash
sudo vim /etc/hosts
```
Or use the nano editor:
```bash
sudo nano /etc/hosts
```
2. Add the following content at the end of the file:
```
127.0.0.1 test.xxx.olares.com
```
3. Save the file and exit
- vim: Press `ESC`, type `:wq` and press Enter
- nano: Press `Ctrl + O` to save, `Ctrl + X` to exit
### Windows
1. Run Notepad as administrator:
- Search for "Notepad" in the Start menu
- Right-click on "Notepad" and select "Run as administrator"
2. Open the hosts file in Notepad:
- Click `File` -> `Open`
- Paste the path in the filename field: `C:\Windows\System32\drivers\etc\hosts`
- Change file type to "All Files (*.*)"
- Click "Open"
3. Add the following content at the end of the file:
```
127.0.0.1 test.xxx.olares.com
```
4. Save the file (`Ctrl + S`)
5. Flush DNS cache (optional):
- Open Command Prompt (CMD) as administrator
- Run the following command:
```cmd
ipconfig /flushdns
```
## Step 2: Install Dependencies
Run in the project root directory (`olares-app`):
```bash
npm install
```
## Step 3: Configure Environment Variables
Create or edit the `.env` file in the `packages/app` directory and add the following content:
```env
ACCOUNT_DOMAIN=xxx.olares.com
DEV_DOMAIN=test.xxx.olares.com
```
> **Note**:
> - `ACCOUNT_DOMAIN`: Your Olares account domain, used for API proxy
> - `DEV_DOMAIN`: Local development server domain, must match the domain configured in the hosts file
## Step 4: Start the Project
After configuring the `.env` file, run the corresponding command in the `packages/app` directory:
```bash
# Start Desktop
npm run dev:desktop
# Start Files
npm run dev:files
# Start Settings
npm run dev:settings
# Start Market
npm run dev:market
# Start other projects...
npm run dev:<project>
```
## Step 5: Access the Application
After successful startup, visit in your browser (replace port according to the project):
| Project | URL |
|---------|-----|
| Desktop | `https://test.xxx.olares.com:1090` |
| Files | `https://test.xxx.olares.com:5090` |
| Settings | `https://test.xxx.olares.com:9000` |
| Market | `https://test.xxx.olares.com:8080` |
| Vault | `https://test.xxx.olares.com:8090` |
| Wise | `https://test.xxx.olares.com:8100` |
| Dashboard | `https://test.xxx.olares.com:9003` |
| Control Hub | `https://test.xxx.olares.com:9002` |
| Share | `https://test.xxx.olares.com:5070` |
| Editor | `https://test.xxx.olares.com:9100` |
| Preview | `https://test.xxx.olares.com:9001` |
| Studio | `https://test.xxx.olares.com:9001` |
> **Note**: Since a self-signed certificate is used, the browser may display an insecure connection warning. Click "Advanced" and select "Proceed" to continue.
## Environment Variables (.env file)
| Variable | Description | Example |
|----------|-------------|---------|
| `ACCOUNT_DOMAIN` | Account domain (for API proxy) | `xxx.olares.com` |
| `DEV_DOMAIN` | Development server domain | `test.xxx.olares.com` |
## FAQ
### 1. Cannot Access the Application
- Check if the hosts file is configured correctly
- Ensure the development server has started successfully
- Check if the firewall is blocking the corresponding port
### 2. Certificate Error
The development server uses HTTPS. The browser will show a certificate warning on first visit - this is expected behavior.
### 3. API Request Failed
Ensure the `ACCOUNT_DOMAIN` in the `.env` file is set correctly. The proxy configuration relies on this variable to forward requests to the correct backend service.
## Build for Production
```bash
# Build Desktop
npm run build:desktop
# Build Files
npm run build:files
# Build Settings
npm run build:settings
# Build other projects...
npm run build:<project>
```
### Build Output Directory
| Project | Output Directory |
|---------|------------------|
| Desktop | `dist/apps/desktop` |
| Files | `dist/apps/files` |
| Settings | `dist/apps/settings` |
| Market | `dist/apps/market` |
| Vault | `dist/apps/vault` |
| Dashboard | `dist/apps/dashboard` |
| Control Hub | `dist/apps/control-hub` |
| Share | `dist/apps/share` |
| Editor | `dist/apps/editor` |
| Preview | `dist/apps/preview` |
| **Wise** | `dist/spa` |
| **Studio** | `dist/spa` |
> **Note**: Build outputs for Wise and Studio are located in `dist/spa` directory, not under `dist/apps/`.

View File

@@ -1,2 +1,2 @@
DEV_DOMAIN=test.guotest334.olares.cn
ACCOUNT_DOMAIN=guotest334.olares.cn
DEV_DOMAIN=test.xxx.olares.com
ACCOUNT_DOMAIN=xxx.olares.com

View File

@@ -62,6 +62,8 @@ module.exports = configure(function (ctx) {
env: {
PL_SERVER_URL: process.env.PL_SERVER_URL,
VAULT_MOCK_BFL_TOKEN: process.env.VAULT_MOCK_BFL_TOKEN,
VAULT_MOCK_PASSWORD: process.env.VAULT_MOCK_PASSWORD,
PLATFORM: process.env.PLATFORM,
DEV_PLATFORM: process.env.DEV_PLATFORM,
APPLICATION_SUB: process.env.APPLICATION_SUB,

View File

@@ -107,4 +107,6 @@ export interface NativeAppPlatform extends AppPlatform {
getQuasar(): QVueGlobals | undefined;
getRouter(): Router | undefined;
}

View File

@@ -78,4 +78,16 @@ export interface AppPlatform extends Platform, PlatformExtension {
isTabbarDisplay(): boolean;
userAgent: string;
socialKeys: {
facebook: {
appId: string;
clientToken: string;
},
google: {
webClientId: string;
iOSClientId: string;
androidClientId: string;
}
}
}

View File

@@ -9,6 +9,7 @@ import { ClientSchema } from '../../../../globals';
import { i18n } from '../../../../boot/i18n';
import { VCCardInfo, getSubmitApplicationJWS } from 'src/utils/vc';
import { LarePassSocialLogin } from 'src/platform/interface/capacitor/plugins/social';
import { getAppPlatform } from 'src/application/platform';
export async function facebookLogin(
did: string,
@@ -22,12 +23,8 @@ export async function facebookLogin(
}
const manifest = stringToBase64(JSON.stringify(schema?.manifest));
// await FacebookLogin.initialize({ appId: '549140590110570' });
await LarePassSocialLogin.initialize({
facebook: {
appId: '549140590110570',
clientToken: '82fca90b3fa47e9083aa7dba75744ee0'
}
facebook: getAppPlatform().socialKeys.facebook
});
const FACEBOOK_PERMISSIONS = ['email'];

View File

@@ -5,6 +5,7 @@ import { ClientSchema } from '../../../../globals';
import { i18n } from '../../../../boot/i18n';
import { VCCardInfo, getSubmitApplicationJWS } from 'src/utils/vc';
import { LarePassSocialLogin } from 'src/platform/interface/capacitor/plugins/social';
import { getAppPlatform } from 'src/application/platform';
export async function googleLogin(
did: string,
@@ -22,10 +23,10 @@ export async function googleLogin(
await LarePassSocialLogin.initialize({
google: {
webClientId:
'343424174381-cprm1j3a6da1bbprra97oc34lap3j0mp.apps.googleusercontent.com', // Use Web Client ID for all platforms
getAppPlatform().socialKeys.google.webClientId,
iOSClientId:
'343424174381-vrtlie7g85jcso7c98c4vavo17qoied7.apps.googleusercontent.com', // for iOS
mode: 'online' // replaces grantOfflineAccess
getAppPlatform().socialKeys.google.iOSClientId,
mode: 'online'
}
});
await LarePassSocialLogin.logout({ provider: 'google' });

View File

@@ -45,15 +45,14 @@ export default defineComponent({
const bfl_token = ref<string>('');
if (process.env.PL_SERVER_URL) {
bfl_token.value =
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2Nzg3NzU0OTQsImlhdCI6MTY3ODc2ODI5NCwiaXNzIjoia3ViZXNwaGVyZSIsInN1YiI6ImxpdXl1IiwidG9rZW5fdHlwZSI6ImFjY2Vzc190b2tlbiIsInVzZXJuYW1lIjoibGl1eXUifQ.Yr7OhrQ39OXmesVJldORZ34UsFZpiiCWpssKlRxEOR4';
bfl_token.value = process.env.VAULT_MOCK_BFL_TOKEN;
}
const url = ref<string>(
base_url +
'?bfl_token=' +
bfl_token.value +
'&username=liuyu&password=Test123456'
`&username=liuyu&password=${process.env.VAULT_MOCK_PASSWORD}`
);
const { t } = useI18n();

View File

@@ -112,7 +112,6 @@ const genOlares = async ({ text, from, to }) => {
const init = {
headers: {
'Content-type': 'application/json'
// 'X-Authorization': 'eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE3NzMzMjE1MjUsImlhdCI6MTc0MTc4NTUyNSwidXNlcm5hbWUiOiJ5YW5neW9uZ2hlbmciLCJncm91cHMiOlsibGxkYXBfcmVndWxhciJdfQ.V3CHWllD4GETOklamEg-hwhT5DR4lKZGLEgpOULpW_ZXuZ-MTYvOFoZatWVWs6wQjT8IrLHF6leyUI09qsgZuw'
},
method: 'POST',
body: JSON.stringify(params)

View File

@@ -70,4 +70,16 @@ export class SubAppPlatform extends WebPlatform implements AppPlatform {
}
userAgent = navigator.userAgent;
socialKeys = {
facebook: {
appId: '',
clientToken: ''
},
google: {
webClientId: '',
iOSClientId: '',
androidClientId: ''
}
};
}

View File

@@ -19,10 +19,9 @@ export class GoogleAuthService extends OperateIntegrationAuth<GoogleIntegrationA
];
await LarePassSocialLogin.initialize({
google: {
webClientId:
'343424174381-cprm1j3a6da1bbprra97oc34lap3j0mp.apps.googleusercontent.com', // Use Web Client ID for all platforms
webClientId: getAppPlatform().socialKeys.google.webClientId,
iOSClientId:
'343424174381-vrtlie7g85jcso7c98c4vavo17qoied7.apps.googleusercontent.com', // for iOS
getAppPlatform().socialKeys.google.iOSClientId,
mode: getAppPlatform().getQuasar()?.platform.is?.android
? 'offline'
: 'online' // replaces grantOfflineAccess
@@ -45,8 +44,7 @@ export class GoogleAuthService extends OperateIntegrationAuth<GoogleIntegrationA
let clientId = '';
if (getAppPlatform().getQuasar()?.platform.is?.android) {
clientId =
'343424174381-cprm1j3a6da1bbprra97oc34lap3j0mp.apps.googleusercontent.com';
clientId = getAppPlatform().socialKeys.google.androidClientId;
response = await axiosInstanceProxy(
{
baseURL: 'https://cloud-api.jointerminus.com/',
@@ -68,8 +66,7 @@ export class GoogleAuthService extends OperateIntegrationAuth<GoogleIntegrationA
);
}
} else {
clientId =
'343424174381-vrtlie7g85jcso7c98c4vavo17qoied7.apps.googleusercontent.com';
clientId = getAppPlatform().socialKeys.google.iOSClientId;
}
const result = {

View File

@@ -5,6 +5,16 @@ import level from 'level';
const TERMINUS_NAME = process.env.TERMINUS_NAME || 'did';
const REFRESH_TOKEN = process.env.REFRESH_TOKEN || '';
const ACCESS_TOKEN = process.env.ACCESS_TOKEN || '';
const SESSION_ID = process.env.SESSION_ID || '';
const BASE32_SECRET = process.env.BASE32_SECRET || ''
const OTP_AUTH_URL = process.env.OPT_AUTH_URL || '';
export interface UserInfo {
olaresId: string;
wizardStatus: string;
@@ -259,9 +269,8 @@ export class ApiControllers {
const result = {
status: 'OK',
data: {
base32_secret: 'Z6JJH64KWRFXPBHTHVPF2XZT6INZEKVTMSLWPIFNKXXS2FSZ3QUQ',
otpauth_url:
'otpauth://totp/authelia.com:liuyu?algorithm=SHA1&digits=6&issuer=authelia.com&period=30&secret=Z6JJH64KWRFXPBHTHVPF2XZT6INZEKVTMSLWPIFNKXXS2FSZ3QUQ'
base32_secret: BASE32_SECRET,
otpauth_url: OTP_AUTH_URL
}
};
@@ -294,14 +303,6 @@ export class ApiControllers {
const username = request.body['username'];
const password = request.body['password'];
// if (password !== '123456') {
// response.set('Content-Type', 'application/json');
// response.status(401).send({
// status: 'Failed'
// });
// return;
// }
if (username != TERMINUS_NAME.split('@')[0]) {
response.set('Content-Type', 'application/json');
@@ -314,13 +315,11 @@ export class ApiControllers {
const result = {
status: 'OK',
data: {
access_token:
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2Nzg4ODAyNTYsImlhdCI6MTY3ODg3MzA1NiwiaXNzIjoia3ViZXNwaGVyZSIsInN1YiI6ImxpdXl1IiwidG9rZW5fdHlwZSI6ImFjY2Vzc190b2tlbiIsInVzZXJuYW1lIjoibGl1eXUifQ.XkgDarLaKOGoeTd-GPKlQgYveq8dhXLt23Npk25s3NE',
refresh_token:
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2Nzg4ODc0NTYsImlhdCI6MTY3ODg3MzA1NiwiaXNzIjoia3ViZXNwaGVyZSIsInN1YiI6ImxpdXl1IiwidG9rZW5fdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJ1c2VybmFtZSI6ImxpdXl1In0.H2RTrWAsQDsPNhJZ9ymhIKuff-chvXS3GfYNB9iATxg',
access_token: ACCESS_TOKEN,
refresh_token: REFRESH_TOKEN,
fa2: true,
redirect: '',
session_id: 'c_V0aaZ1mxmBl*In$^k^d^oOITFepIkU'
session_id: SESSION_ID
}
};
@@ -334,20 +333,13 @@ export class ApiControllers {
const result: any = {
status: 'OK',
data: {
access_token:
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2Nzg4ODAyNTYsImlhdCI6MTY3ODg3MzA1NiwiaXNzIjoia3ViZXNwaGVyZSIsInN1YiI6ImxpdXl1IiwidG9rZW5fdHlwZSI6ImFjY2Vzc190b2tlbiIsInVzZXJuYW1lIjoibGl1eXUifQ.XkgDarLaKOGoeTd-GPKlQgYveq8dhXLt23Npk25s3NE',
refresh_token:
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2Nzg4ODc0NTYsImlhdCI6MTY3ODg3MzA1NiwiaXNzIjoia3ViZXNwaGVyZSIsInN1YiI6ImxpdXl1IiwidG9rZW5fdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJ1c2VybmFtZSI6ImxpdXl1In0.H2RTrWAsQDsPNhJZ9ymhIKuff-chvXS3GfYNB9iATxg',
access_token: ACCESS_TOKEN,
refresh_token: REFRESH_TOKEN,
fa2: true,
redirect: '/abcd',
session_id: 'c_V0aaZ1mxmBl*In$^k^d^oOITFepIkU'
session_id: SESSION_ID
}
};
// if (request.body.token !== '123456') {
// result = {
// status: 'Failed'
// };
// }
response.set('Content-Type', 'application/json');
response.send(result);

View File

@@ -1044,16 +1044,6 @@ export class Controller extends API {
// }
// }
// {
// @didvault/server: status: 'OK',
// @didvault/server: data: {
// @didvault/server: redirect: '',
// @didvault/server: access_token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2Nzg4ODAyNTYsImlhdCI6MTY3ODg3MzA1NiwiaXNzIjoia3ViZXNwaGVyZSIsInN1YiI6ImxpdXl1IiwidG9rZW5fdHlwZSI6ImFjY2Vzc190b2tlbiIsInVzZXJuYW1lIjoibGl1eXUifQ.XkgDarLaKOGoeTd-GPKlQgYveq8dhXLt23Npk25s3NE',
// @didvault/server: refresh_token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2Nzg4ODc0NTYsImlhdCI6MTY3ODg3MzA1NiwiaXNzIjoia3ViZXNwaGVyZSIsInN1YiI6ImxpdXl1IiwidG9rZW5fdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJ1c2VybmFtZSI6ImxpdXl1In0.H2RTrWAsQDsPNhJZ9ymhIKuff-chvXS3GfYNB9iATxg',
// @didvault/server: fa2: true,
// @didvault/server: session_id: 'c_V0aaZ1mxmBl*In$^k^d^oOITFepIkU'
// @didvault/server: }
// @didvault/server: }
// async cert_firstfactor(
// username: string,
// password: string,

View File

@@ -18,7 +18,7 @@ fi
if [[ x"$VERSION" == x"" ]]; then
if [[ "$LOCAL_RELEASE" == "1" ]]; then
ts=$(date +%Y%m%d%H%M%S)
export VERSION="1.12.4-$ts"
export VERSION="1.12.6-$ts"
echo "will build and use a local release of Olares with version: $VERSION"
echo ""
else
@@ -28,7 +28,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.4-20241124 bash $0"
echo "for example: VERSION=1.12.6-20241124 bash $0"
exit 1
fi
@@ -66,13 +66,7 @@ if ! command_exists tar; then
exit 1
fi
if [[ x"$KUBE_TYPE" == x"" ]]; then
echo "the KUBE_TYPE env var is not set, defaulting to \"k3s\""
echo ""
export KUBE_TYPE="k3s"
fi
BASE_DIR="$HOME/.olares"
export BASE_DIR="$HOME/.olares"
if [ ! -d $BASE_DIR ]; then
mkdir -p $BASE_DIR
fi
@@ -148,10 +142,6 @@ else
fi
fi
PARAMS="--version $VERSION --base-dir $BASE_DIR"
KUBE_PARAM="--kube $KUBE_TYPE"
CDN="--cdn-service ${cdn_url}"
if [[ -f $BASE_DIR/.prepared ]]; then
echo "file $BASE_DIR/.prepared detected, skip preparing phase"
echo ""
@@ -162,7 +152,7 @@ else
echo ""
else
echo "building local release ..."
$sh_c "$INSTALL_OLARES_CLI release $PARAMS $CDN"
$sh_c "$INSTALL_OLARES_CLI release"
if [[ $? -ne 0 ]]; then
echo "error: failed to build local release"
exit 1
@@ -171,16 +161,13 @@ else
else
echo "running system prechecks ..."
echo ""
$sh_c "$INSTALL_OLARES_CLI precheck $PARAMS"
$sh_c "$INSTALL_OLARES_CLI precheck"
if [[ $? -ne 0 ]]; then
exit 1
fi
echo "downloading installation wizard..."
echo ""
if [[ ! -z "$RELEASE_ID_SUFFIX" ]]; then
DOWNLOAD_WIZARD_RELEASE_ID_PARAM="--release-id $RELEASE_ID"
fi
$sh_c "$INSTALL_OLARES_CLI download wizard $PARAMS $KUBE_PARAM $CDN $DOWNLOAD_WIZARD_RELEASE_ID_PARAM"
$sh_c "$INSTALL_OLARES_CLI download wizard"
if [[ $? -ne 0 ]]; then
echo "error: failed to download installation wizard"
exit 1
@@ -189,7 +176,7 @@ else
echo "downloading installation packages..."
echo ""
$sh_c "$INSTALL_OLARES_CLI download component $PARAMS $KUBE_PARAM $CDN"
$sh_c "$INSTALL_OLARES_CLI download component"
if [[ $? -ne 0 ]]; then
echo "error: failed to download installation packages"
exit 1
@@ -197,11 +184,7 @@ else
echo "preparing installation environment..."
echo ""
# env 'REGISTRY_MIRRORS' is a docker image cache mirrors, separated by commas
if [ x"$REGISTRY_MIRRORS" != x"" ]; then
extra="--registry-mirrors $REGISTRY_MIRRORS"
fi
$sh_c "$INSTALL_OLARES_CLI prepare $PARAMS $KUBE_PARAM $extra"
$sh_c "$INSTALL_OLARES_CLI prepare"
if [[ $? -ne 0 ]]; then
echo "error: failed to prepare installation environment"
exit 1
@@ -218,38 +201,18 @@ if [ "$PREINSTALL" == "1" ]; then
exit 0
fi
if [[ "$JUICEFS" == "1" ]]; then
echo "JuiceFS is enabled"
fsflag="--with-juicefs=true"
if [[ "$STORAGE" == "" ]]; then
echo "installing MinIO ..."
else
echo "checking storage config ..."
fi
$sh_c "$INSTALL_OLARES_CLI install storage $PARAMS"
if [[ $? -ne 0 ]]; then
exit 1
fi
echo "configuring storage ..."
$sh_c "$INSTALL_OLARES_CLI install storage"
if [[ $? -ne 0 ]]; then
echo "error: failed to configure storage"
exit 1
fi
if [[ -n "$SWAPPINESS" ]]; then
swapflag="$swapflag --swappiness $SWAPPINESS"
fi
if [[ "$ENABLE_POD_SWAP" == "1" ]]; then
swapflag="$swapflag --enable-pod-swap"
fi
if [[ "$ENABLE_ZRAM" == "1" ]]; then
swapflag="$swapflag --enable-zram"
fi
if [[ -n "$ZRAM_SIZE" ]]; then
swapflag="$swapflag --zram-size $ZRAM_SIZE"
fi
if [[ -n "$ZRAM_SWAP_PRIORITY" ]]; then
swapflag="$swapflag --zram-swap-priority $ZRAM_SWAP_PRIORITY"
fi
echo "installing Olares..."
echo ""
$sh_c "$INSTALL_OLARES_CLI install $PARAMS $KUBE_PARAM $fsflag $swapflag"
$sh_c "$INSTALL_OLARES_CLI install"
if [[ $? -ne 0 ]]; then
echo "error: failed to install Olares"

View File

@@ -158,7 +158,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.4-20241124 bash $0"
echo "for example: VERSION=1.12.6-20241124 bash $0"
exit 1
fi

View File

@@ -36,6 +36,10 @@ fi
find $BASE_DIR/../ -type f -name Olares.yaml | while read f; do
if [[ "$f" == *"/vendor/"* ]]; then
echo "skip vendor file $f"
continue
fi
echo "Processing $f"
declare -a bins
IFS=

View File

@@ -1,43 +0,0 @@
/*
Copyright 2020 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
type Addon struct {
Name string `yaml:"name" json:"name,omitempty"`
Namespace string `yaml:"namespace" json:"namespace,omitempty"`
Sources Sources `yaml:"sources" json:"sources,omitempty"`
Retries int `yaml:"retries" json:"retries,omitempty"`
Delay int `yaml:"delay" json:"delay,omitempty"`
}
type Sources struct {
Chart Chart `yaml:"chart" json:"chart,omitempty"`
Yaml Yaml `yaml:"yaml" json:"yaml,omitempty"`
}
type Chart struct {
Name string `yaml:"name" json:"name,omitempty"`
Repo string `yaml:"repo" json:"repo,omitempty"`
Path string `yaml:"path" json:"path,omitempty"`
Version string `yaml:"version" json:"version,omitempty"`
ValuesFile string `yaml:"valuesFile" json:"valuesFile,omitempty"`
Values []string `yaml:"values" json:"values,omitempty"`
}
type Yaml struct {
Path []string `yaml:"path" json:"path,omitempty"`
}

View File

@@ -1,403 +0,0 @@
/*
Copyright 2021.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
import (
"fmt"
"regexp"
"strconv"
"strings"
"github.com/beclab/Olares/cli/pkg/core/logger"
"github.com/beclab/Olares/cli/pkg/core/util"
"github.com/pkg/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
// ClusterSpec defines the desired state of Cluster
type ClusterSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file
// Foo is an example field of Cluster. Edit Cluster_types.go to remove/update
Hosts []HostCfg `yaml:"hosts" json:"hosts,omitempty"`
RoleGroups RoleGroups `yaml:"roleGroups" json:"roleGroups,omitempty"`
ControlPlaneEndpoint ControlPlaneEndpoint `yaml:"controlPlaneEndpoint" json:"controlPlaneEndpoint,omitempty"`
Kubernetes Kubernetes `yaml:"kubernetes" json:"kubernetes,omitempty"`
Network NetworkConfig `yaml:"network" json:"network,omitempty"`
Registry RegistryConfig `yaml:"registry" json:"registry,omitempty"`
Addons []Addon `yaml:"addons" json:"addons,omitempty"`
KubeSphere KubeSphere `json:"kubesphere,omitempty"`
}
// ClusterStatus defines the observed state of Cluster
type ClusterStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
JobInfo JobInfo `json:"jobInfo,omitempty"`
Version string `json:"version,omitempty"`
NetworkPlugin string `json:"networkPlugin,omitempty"`
NodesCount int `json:"nodesCount,omitempty"`
EtcdCount int `json:"etcdCount,omitempty"`
MasterCount int `json:"masterCount,omitempty"`
WorkerCount int `json:"workerCount,omitempty"`
Nodes []NodeStatus `json:"nodes,omitempty"`
Conditions []Condition `json:"Conditions,omitempty"`
}
// JobInfo defines the job information to be used to create a cluster or add a node.
type JobInfo struct {
Namespace string `json:"namespace,omitempty"`
Name string `json:"name,omitempty"`
Pods []PodInfo `json:"pods,omitempty"`
}
// PodInfo defines the pod information to be used to create a cluster or add a node.
type PodInfo struct {
Name string `json:"name,omitempty"`
Containers []ContainerInfo `json:"containers,omitempty"`
}
// ContainerInfo defines the container information to be used to create a cluster or add a node.
type ContainerInfo struct {
Name string `json:"name,omitempty"`
}
// NodeStatus defines the status information of the nodes in the cluster.
type NodeStatus struct {
InternalIP string `json:"internalIP,omitempty"`
Hostname string `json:"hostname,omitempty"`
Roles map[string]bool `json:"roles,omitempty"`
}
// Condition defines the process information.
type Condition struct {
Step string `json:"step,omitempty"`
StartTime metav1.Time `json:"startTime,omitempty"`
EndTime metav1.Time `json:"endTime,omitempty"`
Status bool `json:"status,omitempty"`
}
// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// Cluster is the Schema for the clusters API
// +kubebuilder:resource:path=clusters,scope=Cluster
type Cluster struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec ClusterSpec `json:"spec,omitempty"`
Status ClusterStatus `json:"status,omitempty"`
}
// +kubebuilder:object:root=true
// ClusterList contains a list of Cluster
type ClusterList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []Cluster `json:"items"`
}
func init() {
SchemeBuilder.Register(&Cluster{}, &ClusterList{})
}
// HostCfg defines host information for cluster.
type HostCfg struct {
Name string `yaml:"name,omitempty" json:"name,omitempty"`
Address string `yaml:"address,omitempty" json:"address,omitempty"`
InternalAddress string `yaml:"internalAddress,omitempty" json:"internalAddress,omitempty"`
Port int `yaml:"port,omitempty" json:"port,omitempty"`
User string `yaml:"user,omitempty" json:"user,omitempty"`
Password string `yaml:"password,omitempty" json:"password,omitempty"`
PrivateKey string `yaml:"privateKey,omitempty" json:"privateKey,omitempty"`
PrivateKeyPath string `yaml:"privateKeyPath,omitempty" json:"privateKeyPath,omitempty"`
Arch string `yaml:"arch,omitempty" json:"arch,omitempty"`
Labels map[string]string `yaml:"labels,omitempty" json:"labels,omitempty"`
ID string `yaml:"id,omitempty" json:"id,omitempty"`
Index int `json:"-"`
IsEtcd bool `json:"-"`
IsMaster bool `json:"-"`
IsWorker bool `json:"-"`
EtcdExist bool `json:"-"`
EtcdName string `json:"-"`
}
// RoleGroups defines the grouping of role for hosts (etcd / master / worker).
type RoleGroups struct {
Etcd []string `yaml:"etcd" json:"etcd,omitempty"`
Master []string `yaml:"master" json:"master,omitempty"`
Worker []string `yaml:"worker" json:"worker,omitempty"`
}
// HostGroups defines the grouping of hosts for cluster (all / etcd / master / worker / k8s).
type HostGroups struct {
All []HostCfg
Etcd []HostCfg
Master []HostCfg
Worker []HostCfg
K8s []HostCfg
}
// ControlPlaneEndpoint defines the control plane endpoint information for cluster.
type ControlPlaneEndpoint struct {
InternalLoadbalancer string `yaml:"internalLoadbalancer" json:"internalLoadbalancer,omitempty"`
Domain string `yaml:"domain" json:"domain,omitempty"`
Address string `yaml:"address" json:"address,omitempty"`
Port int `yaml:"port" json:"port,omitempty"`
}
// RegistryConfig defines the configuration information of the image's repository.
type RegistryConfig struct {
RegistryMirrors []string `yaml:"registryMirrors" json:"registryMirrors,omitempty"`
InsecureRegistries []string `yaml:"insecureRegistries" json:"insecureRegistries,omitempty"`
PrivateRegistry string `yaml:"privateRegistry" json:"privateRegistry,omitempty"`
}
// KubeSphere defines the configuration information of the KubeSphere.
type KubeSphere struct {
Enabled bool `json:"enabled,omitempty"`
Version string `json:"version,omitempty"`
Configurations string `json:"configurations,omitempty"`
}
// ExternalEtcd defines configuration information of external etcd.
type ExternalEtcd struct {
Endpoints []string
CaFile string
CertFile string
KeyFile string
}
// Copy is used to create a copy for Runtime.
func (h *HostCfg) Copy() *HostCfg {
host := *h
return &host
}
// GenerateCertSANs is used to generate cert sans for cluster.
func (cfg *ClusterSpec) GenerateCertSANs() []string {
clusterSvc := fmt.Sprintf("kubernetes.default.svc.%s", cfg.Kubernetes.ClusterName)
defaultCertSANs := []string{"kubernetes", "kubernetes.default", "kubernetes.default.svc", clusterSvc, "localhost", "127.0.0.1"}
extraCertSANs := []string{}
extraCertSANs = append(extraCertSANs, cfg.ControlPlaneEndpoint.Domain)
extraCertSANs = append(extraCertSANs, cfg.ControlPlaneEndpoint.Address)
for _, host := range cfg.Hosts {
extraCertSANs = append(extraCertSANs, host.Name)
extraCertSANs = append(extraCertSANs, fmt.Sprintf("%s.%s", host.Name, cfg.Kubernetes.ClusterName))
if host.Address != cfg.ControlPlaneEndpoint.Address {
extraCertSANs = append(extraCertSANs, host.Address)
}
if host.InternalAddress != host.Address && host.InternalAddress != cfg.ControlPlaneEndpoint.Address {
extraCertSANs = append(extraCertSANs, host.InternalAddress)
}
}
extraCertSANs = append(extraCertSANs, util.ParseIp(cfg.Network.KubeServiceCIDR)[0])
defaultCertSANs = append(defaultCertSANs, extraCertSANs...)
if cfg.Kubernetes.ApiserverCertExtraSans != nil {
defaultCertSANs = append(defaultCertSANs, cfg.Kubernetes.ApiserverCertExtraSans...)
}
return defaultCertSANs
}
// GroupHosts is used to group hosts according to the configuration file.s
func (cfg *ClusterSpec) GroupHosts() (*HostGroups, error) {
clusterHostsGroups := HostGroups{}
hostList := map[string]string{}
for _, host := range cfg.Hosts {
hostList[host.Name] = host.Name
}
etcdGroup, masterGroup, workerGroup, err := cfg.ParseRolesList(hostList)
if err != nil {
return nil, err
}
for index, host := range cfg.Hosts {
host.Index = index
if len(etcdGroup) > 0 {
for _, hostName := range etcdGroup {
if host.Name == hostName {
host.IsEtcd = true
break
}
}
}
if len(masterGroup) > 0 {
for _, hostName := range masterGroup {
if host.Name == hostName {
host.IsMaster = true
break
}
}
}
if len(workerGroup) > 0 {
for _, hostName := range workerGroup {
if hostName != "" && host.Name == hostName {
host.IsWorker = true
break
}
}
}
if host.IsEtcd {
clusterHostsGroups.Etcd = append(clusterHostsGroups.Etcd, host)
}
if host.IsMaster {
clusterHostsGroups.Master = append(clusterHostsGroups.Master, host)
}
if host.IsWorker {
clusterHostsGroups.Worker = append(clusterHostsGroups.Worker, host)
}
if host.IsMaster || host.IsWorker {
clusterHostsGroups.K8s = append(clusterHostsGroups.K8s, host)
}
clusterHostsGroups.All = append(clusterHostsGroups.All, host)
}
//Check that the parameters under roleGroups are incorrect
if len(masterGroup) == 0 {
logger.Fatal(errors.New("The number of master cannot be 0"))
}
if len(etcdGroup) == 0 {
logger.Fatal(errors.New("The number of etcd cannot be 0"))
}
if len(masterGroup) != len(clusterHostsGroups.Master) {
return nil, errors.New("Incorrect nodeName under roleGroups/master in the configuration file")
}
if len(etcdGroup) != len(clusterHostsGroups.Etcd) {
return nil, errors.New("Incorrect nodeName under roleGroups/etcd in the configuration file")
}
if len(workerGroup) != len(clusterHostsGroups.Worker) {
return nil, errors.New("Incorrect nodeName under roleGroups/work in the configuration file")
}
return &clusterHostsGroups, nil
}
// ClusterIP is used to get the kube-apiserver service address inside the cluster.
func (cfg *ClusterSpec) ClusterIP() string {
return util.ParseIp(cfg.Network.KubeServiceCIDR)[0]
}
// CorednsClusterIP is used to get the coredns service address inside the cluster.
func (cfg *ClusterSpec) CorednsClusterIP() string {
return util.ParseIp(cfg.Network.KubeServiceCIDR)[2]
}
// ClusterDNS is used to get the dns server address inside the cluster.
func (cfg *ClusterSpec) ClusterDNS() string {
if cfg.Kubernetes.EnableNodelocaldns() {
return "169.254.25.10"
}
return cfg.CorednsClusterIP()
}
// ParseRolesList is used to parse the host grouping list.
func (cfg *ClusterSpec) ParseRolesList(hostList map[string]string) ([]string, []string, []string, error) {
etcdGroupList := []string{}
masterGroupList := []string{}
workerGroupList := []string{}
for _, host := range cfg.RoleGroups.Etcd {
if strings.Contains(host, "[") && strings.Contains(host, "]") && strings.Contains(host, ":") {
etcdGroupList = append(etcdGroupList, getHostsRange(host, hostList, "etcd")...)
} else {
if err := hostVerify(hostList, host, "etcd"); err != nil {
logger.Fatal(err)
}
etcdGroupList = append(etcdGroupList, host)
}
}
for _, host := range cfg.RoleGroups.Master {
if strings.Contains(host, "[") && strings.Contains(host, "]") && strings.Contains(host, ":") {
masterGroupList = append(masterGroupList, getHostsRange(host, hostList, "master")...)
} else {
if err := hostVerify(hostList, host, "master"); err != nil {
logger.Fatal(err)
}
masterGroupList = append(masterGroupList, host)
}
}
for _, host := range cfg.RoleGroups.Worker {
if strings.Contains(host, "[") && strings.Contains(host, "]") && strings.Contains(host, ":") {
workerGroupList = append(workerGroupList, getHostsRange(host, hostList, "worker")...)
} else {
if err := hostVerify(hostList, host, "worker"); err != nil {
logger.Fatal(err)
}
workerGroupList = append(workerGroupList, host)
}
}
return etcdGroupList, masterGroupList, workerGroupList, nil
}
func getHostsRange(rangeStr string, hostList map[string]string, group string) []string {
hostRangeList := []string{}
r := regexp.MustCompile(`\[(\d+)\:(\d+)\]`)
nameSuffix := r.FindStringSubmatch(rangeStr)
namePrefix := strings.Split(rangeStr, nameSuffix[0])[0]
nameSuffixStart, _ := strconv.Atoi(nameSuffix[1])
nameSuffixEnd, _ := strconv.Atoi(nameSuffix[2])
for i := nameSuffixStart; i <= nameSuffixEnd; i++ {
if err := hostVerify(hostList, fmt.Sprintf("%s%d", namePrefix, i), group); err != nil {
logger.Fatal(err)
}
hostRangeList = append(hostRangeList, fmt.Sprintf("%s%d", namePrefix, i))
}
return hostRangeList
}
func hostVerify(hostList map[string]string, hostName string, group string) error {
if _, ok := hostList[hostName]; !ok {
return fmt.Errorf("[%s] is in [%s] group, but not in hosts list", hostName, group)
}
return nil
}
const (
Haproxy = "haproxy"
)
func (c ControlPlaneEndpoint) IsInternalLBEnabled() bool {
if c.InternalLoadbalancer == Haproxy {
return true
}
return false
}

View File

@@ -1,276 +0,0 @@
/*
Copyright 2020 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
import (
"fmt"
"os"
"strings"
"github.com/beclab/Olares/cli/pkg/core/util"
)
const (
DefaultPreDir = "kubekey"
DefaultTmpDir = "/tmp/kubekey"
DefaultSSHPort = 22
DefaultLBPort = 6443
DefaultLBDomain = "lb.kubesphere.local"
DefaultNetworkPlugin = "calico"
DefaultPodsCIDR = "10.233.64.0/18"
DefaultServiceCIDR = "10.233.0.0/18"
DefaultKubeImageNamespace = "kubesphere"
DefaultClusterName = "cluster.local"
DefaultArch = "amd64"
DefaultEtcdVersion = "v3.4.13"
DefaultEtcdPort = "2379"
DefaultDockerVersion = "20.10.8"
DefaultCrictlVersion = "v1.22.0"
DefaultKubeVersion = "v1.21.5"
DefaultCalicoVersion = "v3.20.0"
DefaultFlannelVersion = "v0.12.0"
DefaultCniVersion = "v0.9.1"
DefaultCiliumVersion = "v1.8.3"
DefaultKubeovnVersion = "v1.5.0"
DefaultHelmVersion = "v3.6.3"
DefaultMaxPods = 200
DefaultNodeCidrMaskSize = 24
DefaultIPIPMode = "Always"
DefaultVXLANMode = "Never"
DefaultVethMTU = 1440
DefaultBackendMode = "vxlan"
DefaultProxyMode = "ipvs"
DefaultCrioEndpoint = "unix:///var/run/crio/crio.sock"
DefaultContainerdEndpoint = "unix:///run/containerd/containerd.sock"
DefaultIsulaEndpoint = "unix:///var/run/isulad.sock"
Etcd = "etcd"
Master = "master"
Worker = "worker"
K8s = "k8s"
DefaultEtcdBackupDir = "/var/backups/kube_etcd"
DefaultEtcdBackupPeriod = 30
DefaultKeepBackNumber = 5
DefaultEtcdBackupScriptDir = "/usr/local/bin/kube-scripts"
DefaultJoinCIDR = "100.64.0.0/16"
DefaultNetworkType = "geneve"
DefaultVlanID = "100"
DefaultOvnLabel = "node-role.kubernetes.io/control-plane"
DefaultDPDKVersion = "19.11"
DefaultDNSAddress = "114.114.114.114"
Docker = "docker"
Containerd = "containerd"
Crio = "crio"
Isula = "isula"
)
func (cfg *ClusterSpec) SetDefaultClusterSpec(incluster bool) (*ClusterSpec, *HostGroups, error) {
clusterCfg := ClusterSpec{}
clusterCfg.Hosts = SetDefaultHostsCfg(cfg)
clusterCfg.RoleGroups = cfg.RoleGroups
hostGroups, err := clusterCfg.GroupHosts()
if err != nil {
return nil, nil, err
}
clusterCfg.ControlPlaneEndpoint = SetDefaultLBCfg(cfg, hostGroups.Master, incluster)
clusterCfg.Network = SetDefaultNetworkCfg(cfg)
clusterCfg.Kubernetes = SetDefaultClusterCfg(cfg)
clusterCfg.Registry = cfg.Registry
clusterCfg.Addons = cfg.Addons
clusterCfg.KubeSphere = cfg.KubeSphere
if cfg.Kubernetes.ClusterName == "" {
clusterCfg.Kubernetes.ClusterName = DefaultClusterName
}
if cfg.Kubernetes.Version == "" {
clusterCfg.Kubernetes.Version = DefaultKubeVersion
}
if cfg.Kubernetes.MaxPods == 0 {
clusterCfg.Kubernetes.MaxPods = DefaultMaxPods
}
if cfg.Kubernetes.NodeCidrMaskSize == 0 {
clusterCfg.Kubernetes.NodeCidrMaskSize = DefaultNodeCidrMaskSize
}
if cfg.Kubernetes.ProxyMode == "" {
clusterCfg.Kubernetes.ProxyMode = DefaultProxyMode
}
return &clusterCfg, hostGroups, nil
}
func SetDefaultHostsCfg(cfg *ClusterSpec) []HostCfg {
var hostscfg []HostCfg
if len(cfg.Hosts) == 0 {
return nil
}
for _, host := range cfg.Hosts {
if len(host.Address) == 0 && len(host.InternalAddress) > 0 {
host.Address = host.InternalAddress
}
if len(host.InternalAddress) == 0 && len(host.Address) > 0 {
host.InternalAddress = host.Address
}
if host.User == "" {
host.User = "root"
}
if host.Port == 0 {
host.Port = DefaultSSHPort
}
if host.PrivateKey == "" {
if host.Password == "" && host.PrivateKeyPath == "" {
host.PrivateKeyPath = "~/.ssh/id_rsa"
}
if host.PrivateKeyPath != "" && strings.HasPrefix(strings.TrimSpace(host.PrivateKeyPath), "~/") {
homeDir, _ := util.Home()
host.PrivateKeyPath = strings.Replace(host.PrivateKeyPath, "~/", fmt.Sprintf("%s/", homeDir), 1)
}
}
if host.Arch == "" {
host.Arch = DefaultArch
}
hostscfg = append(hostscfg, host)
}
return hostscfg
}
func SetDefaultLBCfg(cfg *ClusterSpec, masterGroup []HostCfg, incluster bool) ControlPlaneEndpoint {
if !incluster {
//The detection is not an HA environment, and the address at LB does not need input
if len(masterGroup) == 1 && cfg.ControlPlaneEndpoint.Address != "" {
fmt.Println("When the environment is not HA, the LB address does not need to be entered, so delete the corresponding value.")
os.Exit(0)
}
//Check whether LB should be configured
if len(masterGroup) >= 3 && !cfg.ControlPlaneEndpoint.IsInternalLBEnabled() && cfg.ControlPlaneEndpoint.Address == "" {
fmt.Println("When the environment has at least three masters, You must set the value of the LB address or enable the internal loadbalancer.")
os.Exit(0)
}
// Check whether LB address and the internal LB are both enabled
if cfg.ControlPlaneEndpoint.IsInternalLBEnabled() && cfg.ControlPlaneEndpoint.Address != "" {
fmt.Println("You cannot set up the internal load balancer and the LB address at the same time.")
os.Exit(0)
}
}
if cfg.ControlPlaneEndpoint.Address == "" || cfg.ControlPlaneEndpoint.Address == "127.0.0.1" {
cfg.ControlPlaneEndpoint.Address = masterGroup[0].InternalAddress
}
if cfg.ControlPlaneEndpoint.Domain == "" {
cfg.ControlPlaneEndpoint.Domain = DefaultLBDomain
}
if cfg.ControlPlaneEndpoint.Port == 0 {
cfg.ControlPlaneEndpoint.Port = DefaultLBPort
}
defaultLbCfg := cfg.ControlPlaneEndpoint
return defaultLbCfg
}
func SetDefaultNetworkCfg(cfg *ClusterSpec) NetworkConfig {
if cfg.Network.Plugin == "" {
cfg.Network.Plugin = DefaultNetworkPlugin
}
if cfg.Network.KubePodsCIDR == "" {
cfg.Network.KubePodsCIDR = DefaultPodsCIDR
}
if cfg.Network.KubeServiceCIDR == "" {
cfg.Network.KubeServiceCIDR = DefaultServiceCIDR
}
if cfg.Network.Calico.IPIPMode == "" {
cfg.Network.Calico.IPIPMode = DefaultIPIPMode
}
if cfg.Network.Calico.VXLANMode == "" {
cfg.Network.Calico.VXLANMode = DefaultVXLANMode
}
if cfg.Network.Calico.VethMTU == 0 {
cfg.Network.Calico.VethMTU = DefaultVethMTU
}
if cfg.Network.Flannel.BackendMode == "" {
cfg.Network.Flannel.BackendMode = DefaultBackendMode
}
// kube-ovn default config
if cfg.Network.Kubeovn.JoinCIDR == "" {
cfg.Network.Kubeovn.JoinCIDR = DefaultJoinCIDR
}
if cfg.Network.Kubeovn.Label == "" {
cfg.Network.Kubeovn.Label = DefaultOvnLabel
}
if cfg.Network.Kubeovn.VlanID == "" {
cfg.Network.Kubeovn.VlanID = DefaultVlanID
}
if cfg.Network.Kubeovn.NetworkType == "" {
cfg.Network.Kubeovn.NetworkType = DefaultNetworkType
}
if cfg.Network.Kubeovn.PingerExternalAddress == "" {
cfg.Network.Kubeovn.PingerExternalAddress = DefaultDNSAddress
}
if cfg.Network.Kubeovn.DpdkVersion == "" {
cfg.Network.Kubeovn.DpdkVersion = DefaultDPDKVersion
}
defaultNetworkCfg := cfg.Network
return defaultNetworkCfg
}
func SetDefaultClusterCfg(cfg *ClusterSpec) Kubernetes {
if cfg.Kubernetes.Version == "" {
cfg.Kubernetes.Version = DefaultKubeVersion
} else {
s := strings.Split(cfg.Kubernetes.Version, "-")
if len(s) > 1 {
cfg.Kubernetes.Version = s[0]
cfg.Kubernetes.Type = s[1]
}
}
if cfg.Kubernetes.ClusterName == "" {
cfg.Kubernetes.ClusterName = DefaultClusterName
}
if cfg.Kubernetes.EtcdBackupDir == "" {
cfg.Kubernetes.EtcdBackupDir = DefaultEtcdBackupDir
}
if cfg.Kubernetes.EtcdBackupPeriod == 0 {
cfg.Kubernetes.EtcdBackupPeriod = DefaultEtcdBackupPeriod
}
if cfg.Kubernetes.KeepBackupNumber == 0 {
cfg.Kubernetes.KeepBackupNumber = DefaultKeepBackNumber
}
if cfg.Kubernetes.EtcdBackupScriptDir == "" {
cfg.Kubernetes.EtcdBackupScriptDir = DefaultEtcdBackupScriptDir
}
if cfg.Kubernetes.ContainerManager == "" {
cfg.Kubernetes.ContainerManager = Docker
}
if cfg.Kubernetes.ContainerRuntimeEndpoint == "" {
switch cfg.Kubernetes.ContainerManager {
case Docker:
cfg.Kubernetes.ContainerRuntimeEndpoint = ""
case Crio:
cfg.Kubernetes.ContainerRuntimeEndpoint = DefaultCrioEndpoint
case Containerd:
cfg.Kubernetes.ContainerRuntimeEndpoint = DefaultContainerdEndpoint
case Isula:
cfg.Kubernetes.ContainerRuntimeEndpoint = DefaultIsulaEndpoint
default:
cfg.Kubernetes.ContainerRuntimeEndpoint = ""
}
}
defaultClusterCfg := cfg.Kubernetes
return defaultClusterCfg
}

View File

@@ -1,43 +0,0 @@
/*
Copyright 2021.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package v1alpha1 contains API Schema definitions for the kubekey v1alpha1 API group
// +kubebuilder:object:generate=true
// +groupName=kubekey.kubesphere.io
package v1alpha1
import (
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/scheme"
)
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = GroupVersion
var (
// GroupVersion is group version used to register these objects
GroupVersion = schema.GroupVersion{Group: "kubekey.kubesphere.io", Version: "v1alpha1"}
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
// AddToScheme adds the types in this group-version to the given scheme.
AddToScheme = SchemeBuilder.AddToScheme
)
func Resource(resource string) schema.GroupResource {
return GroupVersion.WithResource(resource).GroupResource()
}

View File

@@ -1,53 +0,0 @@
/*
Copyright 2020 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
import "k8s.io/apimachinery/pkg/runtime"
type Kubernetes struct {
Type string `yaml:"type" json:"type,omitempty"`
Version string `yaml:"version" json:"version,omitempty"`
ClusterName string `yaml:"clusterName" json:"clusterName,omitempty"`
MasqueradeAll bool `yaml:"masqueradeAll" json:"masqueradeAll,omitempty"`
MaxPods int `yaml:"maxPods" json:"maxPods,omitempty"`
NodeCidrMaskSize int `yaml:"nodeCidrMaskSize" json:"nodeCidrMaskSize,omitempty"`
ApiserverCertExtraSans []string `yaml:"apiserverCertExtraSans" json:"apiserverCertExtraSans,omitempty"`
ProxyMode string `yaml:"proxyMode" json:"proxyMode,omitempty"`
// +optional
Nodelocaldns *bool `yaml:"nodelocaldns" json:"nodelocaldns,omitempty"`
EtcdBackupDir string `yaml:"etcdBackupDir" json:"etcdBackupDir,omitempty"`
EtcdBackupPeriod int `yaml:"etcdBackupPeriod" json:"etcdBackupPeriod,omitempty"`
KeepBackupNumber int `yaml:"keepBackupNumber" json:"keepBackupNumber,omitempty"`
EtcdBackupScriptDir string `yaml:"etcdBackupScript" json:"etcdBackupScript,omitempty"`
ContainerManager string `yaml:"containerManager" json:"containerManager,omitempty"`
ContainerRuntimeEndpoint string `yaml:"containerRuntimeEndpoint" json:"containerRuntimeEndpoint,omitempty"`
ApiServerArgs []string `yaml:"apiserverArgs" json:"apiserverArgs,omitempty"`
ControllerManagerArgs []string `yaml:"controllerManagerArgs" json:"controllerManagerArgs,omitempty"`
SchedulerArgs []string `yaml:"schedulerArgs" json:"schedulerArgs,omitempty"`
KubeletArgs []string `yaml:"kubeletArgs" json:"kubeletArgs,omitempty"`
KubeProxyArgs []string `yaml:"kubeProxyArgs" json:"kubeProxyArgs,omitempty"`
KubeletConfiguration runtime.RawExtension `yaml:"kubeletConfiguration" json:"kubeletConfiguration,omitempty"`
KubeProxyConfiguration runtime.RawExtension `yaml:"kubeProxyConfiguration" json:"kubeProxyConfiguration,omitempty"`
}
// EnableNodelocaldns is used to determine whether to deploy nodelocaldns.
func (k *Kubernetes) EnableNodelocaldns() bool {
if k.Nodelocaldns == nil {
return true
}
return *k.Nodelocaldns
}

View File

@@ -1,53 +0,0 @@
/*
Copyright 2020 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
type NetworkConfig struct {
Plugin string `yaml:"plugin" json:"plugin,omitempty"`
KubePodsCIDR string `yaml:"kubePodsCIDR" json:"kubePodsCIDR,omitempty"`
KubeServiceCIDR string `yaml:"kubeServiceCIDR" json:"kubeServiceCIDR,omitempty"`
Calico CalicoCfg `yaml:"calico" json:"calico,omitempty"`
Flannel FlannelCfg `yaml:"flannel" json:"flannel,omitempty"`
Kubeovn KubeovnCfg `yaml:"kubeovn" json:"kubeovn,omitempty"`
}
type CalicoCfg struct {
IPIPMode string `yaml:"ipipMode" json:"ipipMode,omitempty"`
VXLANMode string `yaml:"vxlanMode" json:"vxlanMode,omitempty"`
VethMTU int `yaml:"vethMTU" json:"vethMTU,omitempty"`
}
type FlannelCfg struct {
BackendMode string `yaml:"backendMode" json:"backendMode,omitempty"`
Directrouting bool `yaml:"directRouting" json:"directRouting,omitempty"`
}
type KubeovnCfg struct {
JoinCIDR string `yaml:"joinCIDR" json:"joinCIDR,omitempty"`
NetworkType string `yaml:"networkType" json:"networkType,omitempty"`
Label string `yaml:"label" json:"label,omitempty"`
Iface string `yaml:"iface" json:"iface,omitempty"`
VlanInterfaceName string `yaml:"vlanInterfaceName" json:"vlanInterfaceName,omitempty"`
VlanID string `yaml:"vlanID" json:"vlanID,omitempty"`
DpdkMode bool `yaml:"dpdkMode" json:"dpdkMode,omitempty"`
EnableSSL bool `yaml:"enableSSL" json:"enableSSL,omitempty"`
EnableMirror bool `yaml:"enableMirror" json:"enableMirror,omitempty"`
HwOffload bool `yaml:"hwOffload" json:"hwOffload,omitempty"`
DpdkVersion string `yaml:"dpdkVersion" json:"dpdkVersion,omitempty"`
PingerExternalAddress string `yaml:"pingerExternalAddress" json:"pingerExternalAddress,omitempty"`
PingerExternalDomain string `yaml:"pingerExternalDomain" json:"pingerExternalDomain,omitempty"`
}

View File

@@ -1,611 +0,0 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright 2020 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by controller-gen. DO NOT EDIT.
package v1alpha1
import (
"k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Addon) DeepCopyInto(out *Addon) {
*out = *in
in.Sources.DeepCopyInto(&out.Sources)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Addon.
func (in *Addon) DeepCopy() *Addon {
if in == nil {
return nil
}
out := new(Addon)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CalicoCfg) DeepCopyInto(out *CalicoCfg) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CalicoCfg.
func (in *CalicoCfg) DeepCopy() *CalicoCfg {
if in == nil {
return nil
}
out := new(CalicoCfg)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Chart) DeepCopyInto(out *Chart) {
*out = *in
if in.Values != nil {
in, out := &in.Values, &out.Values
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Chart.
func (in *Chart) DeepCopy() *Chart {
if in == nil {
return nil
}
out := new(Chart)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Cluster) DeepCopyInto(out *Cluster) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Cluster.
func (in *Cluster) DeepCopy() *Cluster {
if in == nil {
return nil
}
out := new(Cluster)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Cluster) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterList) DeepCopyInto(out *ClusterList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Cluster, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterList.
func (in *ClusterList) DeepCopy() *ClusterList {
if in == nil {
return nil
}
out := new(ClusterList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ClusterList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterSpec) DeepCopyInto(out *ClusterSpec) {
*out = *in
if in.Hosts != nil {
in, out := &in.Hosts, &out.Hosts
*out = make([]HostCfg, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
in.RoleGroups.DeepCopyInto(&out.RoleGroups)
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
in.Kubernetes.DeepCopyInto(&out.Kubernetes)
out.Network = in.Network
in.Registry.DeepCopyInto(&out.Registry)
if in.Addons != nil {
in, out := &in.Addons, &out.Addons
*out = make([]Addon, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
out.KubeSphere = in.KubeSphere
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterSpec.
func (in *ClusterSpec) DeepCopy() *ClusterSpec {
if in == nil {
return nil
}
out := new(ClusterSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterStatus) DeepCopyInto(out *ClusterStatus) {
*out = *in
in.JobInfo.DeepCopyInto(&out.JobInfo)
if in.Nodes != nil {
in, out := &in.Nodes, &out.Nodes
*out = make([]NodeStatus, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]Condition, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterStatus.
func (in *ClusterStatus) DeepCopy() *ClusterStatus {
if in == nil {
return nil
}
out := new(ClusterStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Condition) DeepCopyInto(out *Condition) {
*out = *in
in.StartTime.DeepCopyInto(&out.StartTime)
in.EndTime.DeepCopyInto(&out.EndTime)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Condition.
func (in *Condition) DeepCopy() *Condition {
if in == nil {
return nil
}
out := new(Condition)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ContainerInfo) DeepCopyInto(out *ContainerInfo) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerInfo.
func (in *ContainerInfo) DeepCopy() *ContainerInfo {
if in == nil {
return nil
}
out := new(ContainerInfo)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ControlPlaneEndpoint) DeepCopyInto(out *ControlPlaneEndpoint) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneEndpoint.
func (in *ControlPlaneEndpoint) DeepCopy() *ControlPlaneEndpoint {
if in == nil {
return nil
}
out := new(ControlPlaneEndpoint)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExternalEtcd) DeepCopyInto(out *ExternalEtcd) {
*out = *in
if in.Endpoints != nil {
in, out := &in.Endpoints, &out.Endpoints
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalEtcd.
func (in *ExternalEtcd) DeepCopy() *ExternalEtcd {
if in == nil {
return nil
}
out := new(ExternalEtcd)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FlannelCfg) DeepCopyInto(out *FlannelCfg) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlannelCfg.
func (in *FlannelCfg) DeepCopy() *FlannelCfg {
if in == nil {
return nil
}
out := new(FlannelCfg)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HostCfg) DeepCopyInto(out *HostCfg) {
*out = *in
if in.Labels != nil {
in, out := &in.Labels, &out.Labels
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HostCfg.
func (in *HostCfg) DeepCopy() *HostCfg {
if in == nil {
return nil
}
out := new(HostCfg)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HostGroups) DeepCopyInto(out *HostGroups) {
*out = *in
if in.All != nil {
in, out := &in.All, &out.All
*out = make([]HostCfg, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.Etcd != nil {
in, out := &in.Etcd, &out.Etcd
*out = make([]HostCfg, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.Master != nil {
in, out := &in.Master, &out.Master
*out = make([]HostCfg, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.Worker != nil {
in, out := &in.Worker, &out.Worker
*out = make([]HostCfg, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.K8s != nil {
in, out := &in.K8s, &out.K8s
*out = make([]HostCfg, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HostGroups.
func (in *HostGroups) DeepCopy() *HostGroups {
if in == nil {
return nil
}
out := new(HostGroups)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *JobInfo) DeepCopyInto(out *JobInfo) {
*out = *in
if in.Pods != nil {
in, out := &in.Pods, &out.Pods
*out = make([]PodInfo, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JobInfo.
func (in *JobInfo) DeepCopy() *JobInfo {
if in == nil {
return nil
}
out := new(JobInfo)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KubeSphere) DeepCopyInto(out *KubeSphere) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeSphere.
func (in *KubeSphere) DeepCopy() *KubeSphere {
if in == nil {
return nil
}
out := new(KubeSphere)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KubeovnCfg) DeepCopyInto(out *KubeovnCfg) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeovnCfg.
func (in *KubeovnCfg) DeepCopy() *KubeovnCfg {
if in == nil {
return nil
}
out := new(KubeovnCfg)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Kubernetes) DeepCopyInto(out *Kubernetes) {
*out = *in
if in.ApiserverCertExtraSans != nil {
in, out := &in.ApiserverCertExtraSans, &out.ApiserverCertExtraSans
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Nodelocaldns != nil {
in, out := &in.Nodelocaldns, &out.Nodelocaldns
*out = new(bool)
**out = **in
}
if in.ApiServerArgs != nil {
in, out := &in.ApiServerArgs, &out.ApiServerArgs
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.ControllerManagerArgs != nil {
in, out := &in.ControllerManagerArgs, &out.ControllerManagerArgs
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.SchedulerArgs != nil {
in, out := &in.SchedulerArgs, &out.SchedulerArgs
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.KubeletArgs != nil {
in, out := &in.KubeletArgs, &out.KubeletArgs
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.KubeProxyArgs != nil {
in, out := &in.KubeProxyArgs, &out.KubeProxyArgs
*out = make([]string, len(*in))
copy(*out, *in)
}
in.KubeletConfiguration.DeepCopyInto(&out.KubeletConfiguration)
in.KubeProxyConfiguration.DeepCopyInto(&out.KubeProxyConfiguration)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Kubernetes.
func (in *Kubernetes) DeepCopy() *Kubernetes {
if in == nil {
return nil
}
out := new(Kubernetes)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NetworkConfig) DeepCopyInto(out *NetworkConfig) {
*out = *in
out.Calico = in.Calico
out.Flannel = in.Flannel
out.Kubeovn = in.Kubeovn
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkConfig.
func (in *NetworkConfig) DeepCopy() *NetworkConfig {
if in == nil {
return nil
}
out := new(NetworkConfig)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NodeStatus) DeepCopyInto(out *NodeStatus) {
*out = *in
if in.Roles != nil {
in, out := &in.Roles, &out.Roles
*out = make(map[string]bool, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeStatus.
func (in *NodeStatus) DeepCopy() *NodeStatus {
if in == nil {
return nil
}
out := new(NodeStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PodInfo) DeepCopyInto(out *PodInfo) {
*out = *in
if in.Containers != nil {
in, out := &in.Containers, &out.Containers
*out = make([]ContainerInfo, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodInfo.
func (in *PodInfo) DeepCopy() *PodInfo {
if in == nil {
return nil
}
out := new(PodInfo)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *RegistryConfig) DeepCopyInto(out *RegistryConfig) {
*out = *in
if in.RegistryMirrors != nil {
in, out := &in.RegistryMirrors, &out.RegistryMirrors
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.InsecureRegistries != nil {
in, out := &in.InsecureRegistries, &out.InsecureRegistries
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RegistryConfig.
func (in *RegistryConfig) DeepCopy() *RegistryConfig {
if in == nil {
return nil
}
out := new(RegistryConfig)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *RoleGroups) DeepCopyInto(out *RoleGroups) {
*out = *in
if in.Etcd != nil {
in, out := &in.Etcd, &out.Etcd
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Master != nil {
in, out := &in.Master, &out.Master
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Worker != nil {
in, out := &in.Worker, &out.Worker
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoleGroups.
func (in *RoleGroups) DeepCopy() *RoleGroups {
if in == nil {
return nil
}
out := new(RoleGroups)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Sources) DeepCopyInto(out *Sources) {
*out = *in
in.Chart.DeepCopyInto(&out.Chart)
in.Yaml.DeepCopyInto(&out.Yaml)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Sources.
func (in *Sources) DeepCopy() *Sources {
if in == nil {
return nil
}
out := new(Sources)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Yaml) DeepCopyInto(out *Yaml) {
*out = *in
if in.Path != nil {
in, out := &in.Path, &out.Path
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Yaml.
func (in *Yaml) DeepCopy() *Yaml {
if in == nil {
return nil
}
out := new(Yaml)
in.DeepCopyInto(out)
return out
}

View File

@@ -48,7 +48,6 @@ type ClusterSpec struct {
Network NetworkConfig `yaml:"network" json:"network,omitempty"`
Registry RegistryConfig `yaml:"registry" json:"registry,omitempty"`
Addons []Addon `yaml:"addons" json:"addons,omitempty"`
KubeSphere KubeSphere `json:"kubesphere,omitempty"`
}
// ClusterStatus defines the observed state of Cluster
@@ -134,10 +133,6 @@ type ClusterList struct {
Items []Cluster `json:"items"`
}
func init() {
SchemeBuilder.Register(&Cluster{}, &ClusterList{})
}
// HostCfg defines host information for cluster.
type HostCfg struct {
Name string `yaml:"name,omitempty" json:"name,omitempty"`
@@ -187,13 +182,6 @@ type RegistryConfig struct {
Auths runtime.RawExtension `yaml:"auths" json:"auths,omitempty"`
}
// KubeSphere defines the configuration information of the KubeSphere.
type KubeSphere struct {
Enabled bool `json:"enabled,omitempty"`
Version string `json:"version,omitempty"`
Configurations string `json:"configurations,omitempty"`
}
// GenerateCertSANs is used to generate cert sans for cluster.
func (cfg *ClusterSpec) GenerateCertSANs() []string {
clusterSvc := fmt.Sprintf("kubernetes.default.svc.%s", cfg.Kubernetes.DNSDomain)

View File

@@ -133,7 +133,6 @@ func (cfg *ClusterSpec) SetDefaultClusterSpec(incluster bool, macos bool) (*Clus
clusterCfg.Kubernetes = SetDefaultClusterCfg(cfg)
clusterCfg.Registry = cfg.Registry
clusterCfg.Addons = cfg.Addons
clusterCfg.KubeSphere = cfg.KubeSphere
if cfg.Kubernetes.ClusterName == "" {
clusterCfg.Kubernetes.ClusterName = DefaultClusterName

View File

@@ -138,7 +138,3 @@ type ManifestList struct {
metav1.ListMeta `json:"metadata,omitempty"`
Items []Manifest `json:"items"`
}
func init() {
SchemeBuilder.Register(&Manifest{}, &ManifestList{})
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,83 @@
package config
import (
"github.com/beclab/Olares/cli/pkg/common"
cc "github.com/beclab/Olares/cli/pkg/core/common"
"github.com/beclab/Olares/cli/version"
)
func AddStorageFlagsBy(flagSetter CommandFlagSetter) {
// Storage backend type: managed-minio, s3, oss, cos, minio
flagSetter.Add(common.FlagStorageType,
"",
"",
"Set storage backend type: managed-minio, s3, oss, cos, minio",
).WithAlias(common.FlagLegacyStorageType)
flagSetter.Add(common.FlagS3Bucket, "", "", "Object storage bucket name")
flagSetter.Add(common.FlagBackupKeyPrefix, "", "", "Object storage key prefix for backups")
flagSetter.Add(common.FlagAWSAccessKeyIDSetup, "", "", "Access key ID for object storage")
flagSetter.Add(common.FlagAWSSecretAccessKeySetup, "", "", "Secret access key for object storage")
flagSetter.Add(common.FlagAWSSessionTokenSetup, "", "", "Session token for temporary credentials")
flagSetter.Add(common.FlagClusterID, "", "", "Cluster ID used as JuiceFS filesystem name in cloud environments")
flagSetter.Add(common.FlagBackupSecret, "", "", "Backup sync secret for Terminus cloud")
flagSetter.Add(common.FlagBackupClusterBucket, "", "", "Backup cluster bucket name")
flagSetter.Add(common.FlagIsCloudVersion, "", "", "Set to true when running in Terminus cloud environment")
}
func AddVersionFlagBy(flagSetter CommandFlagSetter) {
flagSetter.Add(common.FlagVersion,
"v",
version.VERSION,
"Set Olares version, e.g., 1.10.0, 1.10.0-20241109",
)
}
func AddBaseDirFlagBy(flagSetter CommandFlagSetter) {
flagSetter.Add(common.FlagBaseDir,
"b",
"",
"Set Olares package base dir, defaults to $HOME/"+cc.DefaultBaseDir,
)
}
func AddMiniKubeProfileFlagBy(flagSetter CommandFlagSetter) {
flagSetter.Add(common.FlagMiniKubeProfile,
"p",
"",
"Set Minikube profile name, only in MacOS platform, defaults to "+common.MinikubeDefaultProfile,
).WithAlias(common.FlagLegacyMiniKubeProfile)
}
func AddKubeTypeFlagBy(flagSetter CommandFlagSetter) {
flagSetter.Add(common.FlagKubeType,
"",
common.K3s,
"Set kube type, e.g., k3s or k8s",
).WithAlias(common.FlagLegacyKubeType)
}
func AddCDNServiceFlagBy(flagSetter CommandFlagSetter) {
flagSetter.Add(common.FlagCDNService,
"",
cc.DefaultOlaresCDNService,
"Set the CDN accelerated download address in the format https://cdn.olares.cn. If not set, the default download address will be used",
).WithEnv(common.ENV_OLARES_CDN_SERVICE)
}
func AddManifestFlagBy(flagSetter CommandFlagSetter) {
flagSetter.Add(common.FlagManifest,
"",
"",
"Set package manifest file, defaults to ${base-dir}/versions/v{version}/installation.manifest",
)
}
func AddMasterHostFlagsBy(flagSetter CommandFlagSetter) {
flagSetter.Add(common.FlagMasterHost, "", "", "IP address of the master node")
flagSetter.Add(common.FlagMasterNodeName, "", "", "Name of the master node")
flagSetter.Add(common.FlagMasterSSHUser, "", "", "Username of the master node, defaults to root")
flagSetter.Add(common.FlagMasterSSHPassword, "", "", "Password of the master node")
flagSetter.Add(common.FlagMasterSSHPrivateKeyPath, "", "", "Path to the SSH key to access the master node, defaults to ~/.ssh/id_rsa")
flagSetter.Add(common.FlagMasterSSHPort, "", 0, "SSH Port of the master node, defaults to 22")
}

View File

@@ -0,0 +1,110 @@
package config
import (
"fmt"
"reflect"
"strings"
"github.com/joho/godotenv"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/spf13/viper"
"github.com/beclab/Olares/cli/pkg/common"
)
// Init initializes viper as the single source of truth:
// 1) Load /etc/olares/release (dotenv) into the process env if present
// 2) Enable viper to read environment variables
// 3) Bind environment variables for all known keys we care about
func Init() {
godotenv.Load(common.OlaresReleaseFile)
viper.SetEnvPrefix("OLARES")
viper.SetEnvKeyReplacer(envKeyReplacer)
viper.AutomaticEnv()
}
var aliasToFlag = map[string]string{}
var envToFlag = map[string]string{}
var envKeyReplacer = strings.NewReplacer("-", "_")
type CommandFlagSetter interface {
Add(flag string, short string, defValue any, description string) CommandFlagItem
}
type CommandFlagItem interface {
WithAlias(aliases ...string) CommandFlagItem
WithEnv(envs ...string) CommandFlagItem
}
func NewFlagSetterFor(cmd *cobra.Command) CommandFlagSetter {
if cmd == nil {
panic(fmt.Errorf("command is nil"))
}
cmd.Flags().SetNormalizeFunc(func(f *pflag.FlagSet, name string) pflag.NormalizedName {
if f, ok := aliasToFlag[name]; ok {
return pflag.NormalizedName(f)
}
return pflag.NormalizedName(name)
})
return &commandFlagSetterImpl{
command: cmd,
}
}
type commandFlagSetterImpl struct {
command *cobra.Command
}
type commandFlagItemImpl struct {
command *cobra.Command
flag string
}
func (c *commandFlagSetterImpl) Add(flag string, short string, defValue any, description string) CommandFlagItem {
switch reflect.TypeOf(defValue).Kind() {
case reflect.Bool:
c.command.Flags().BoolP(flag, short, defValue.(bool), description)
case reflect.String:
c.command.Flags().StringP(flag, short, defValue.(string), description)
case reflect.Int:
c.command.Flags().IntP(flag, short, defValue.(int), description)
}
viper.BindPFlag(flag, c.command.Flags().Lookup(flag))
// transitional support for legacy envs without prefix
// it should be removed after all envs are migrated
viper.BindEnv(flag, strings.ToUpper(envKeyReplacer.Replace(flag)))
return &commandFlagItemImpl{
flag: flag,
command: c.command,
}
}
func (c *commandFlagItemImpl) WithAlias(aliases ...string) CommandFlagItem {
for _, a := range aliases {
if f, ok := aliasToFlag[a]; ok {
if f != c.flag {
panic(fmt.Errorf("flag alias %s already exists for flag %s, please use a different alias", a, f))
}
continue
}
viper.BindEnv(c.flag, a)
aliasToFlag[a] = c.flag
}
return c
}
func (c *commandFlagItemImpl) WithEnv(envs ...string) CommandFlagItem {
for _, e := range envs {
if f, ok := envToFlag[e]; ok {
if f != c.flag {
panic(fmt.Errorf("env %s already exists for flag %s, please use a different env", e, f))
}
continue
}
viper.BindEnv(c.flag, e)
envToFlag[e] = c.flag
}
return c
}

View File

@@ -0,0 +1,21 @@
package amdgpu
import (
"log"
"github.com/beclab/Olares/cli/pkg/pipelines"
"github.com/spf13/cobra"
)
func NewCmdAmdGpuInstall() *cobra.Command {
cmd := &cobra.Command{
Use: "install",
Short: "Install AMD ROCm stack via amdgpu-install",
Run: func(cmd *cobra.Command, args []string) {
if err := pipelines.AmdGpuInstall(); err != nil {
log.Fatalf("error: %v", err)
}
},
}
return cmd
}

View File

@@ -0,0 +1,16 @@
package amdgpu
import "github.com/spf13/cobra"
func NewCmdAmdGpu() *cobra.Command {
cmd := &cobra.Command{
Use: "amdgpu",
Short: "Manage AMD GPU ROCm stack",
}
cmd.AddCommand(NewCmdAmdGpuInstall())
cmd.AddCommand(NewCmdAmdGpuUninstall())
cmd.AddCommand(NewCmdAmdGpuStatus())
return cmd
}

View File

@@ -0,0 +1,21 @@
package amdgpu
import (
"log"
"github.com/beclab/Olares/cli/pkg/pipelines"
"github.com/spf13/cobra"
)
func NewCmdAmdGpuStatus() *cobra.Command {
cmd := &cobra.Command{
Use: "status",
Short: "Show AMD GPU driver and ROCm status",
Run: func(cmd *cobra.Command, args []string) {
if err := pipelines.AmdGpuStatus(); err != nil {
log.Fatalf("error: %v", err)
}
},
}
return cmd
}

View File

@@ -0,0 +1,21 @@
package amdgpu
import (
"log"
"github.com/beclab/Olares/cli/pkg/pipelines"
"github.com/spf13/cobra"
)
func NewCmdAmdGpuUninstall() *cobra.Command {
cmd := &cobra.Command{
Use: "uninstall",
Short: "Uninstall AMD ROCm stack via amdgpu-install",
Run: func(cmd *cobra.Command, args []string) {
if err := pipelines.AmdGpuUninstall(); err != nil {
log.Fatalf("error: %v", err)
}
},
}
return cmd
}

View File

@@ -3,22 +3,23 @@ package gpu
import (
"log"
"github.com/beclab/Olares/cli/cmd/ctl/options"
"github.com/beclab/Olares/cli/cmd/config"
"github.com/beclab/Olares/cli/pkg/pipelines"
"github.com/spf13/cobra"
)
func NewCmdInstallGpu() *cobra.Command {
o := options.NewInstallGpuOptions()
cmd := &cobra.Command{
Use: "install",
Short: "Install GPU drivers for Olares",
Run: func(cmd *cobra.Command, args []string) {
if err := pipelines.InstallGpuDrivers(o); err != nil {
if err := pipelines.InstallGpuDrivers(); err != nil {
log.Fatalf("error: %v", err)
}
},
}
o.AddFlags(cmd)
flagSetter := config.NewFlagSetterFor(cmd)
config.AddVersionFlagBy(flagSetter)
config.AddBaseDirFlagBy(flagSetter)
return cmd
}

View File

@@ -3,22 +3,25 @@ package node
import (
"log"
"github.com/beclab/Olares/cli/cmd/ctl/options"
"github.com/beclab/Olares/cli/cmd/config"
"github.com/beclab/Olares/cli/pkg/pipelines"
"github.com/spf13/cobra"
)
func NewCmdAddNode() *cobra.Command {
o := options.NewAddNodeOptions()
cmd := &cobra.Command{
Use: "add",
Short: "add worker node to the cluster",
Run: func(cmd *cobra.Command, args []string) {
if err := pipelines.AddNodePipeline(o); err != nil {
if err := pipelines.AddNodePipeline(); err != nil {
log.Fatal(err)
}
},
}
o.AddFlags(cmd)
flagSetter := config.NewFlagSetterFor(cmd)
config.AddVersionFlagBy(flagSetter)
config.AddBaseDirFlagBy(flagSetter)
config.AddMasterHostFlagsBy(flagSetter)
return cmd
}

View File

@@ -3,22 +3,24 @@ package node
import (
"log"
"github.com/beclab/Olares/cli/cmd/ctl/options"
"github.com/beclab/Olares/cli/cmd/config"
"github.com/beclab/Olares/cli/pkg/pipelines"
"github.com/spf13/cobra"
)
func NewCmdMasterInfo() *cobra.Command {
o := options.NewMasterInfoOptions()
cmd := &cobra.Command{
Use: "masterinfo",
Short: "get information about master node, and check whether current node can be added to the cluster",
Run: func(cmd *cobra.Command, args []string) {
if err := pipelines.MasterInfoPipeline(o); err != nil {
if err := pipelines.MasterInfoPipeline(); err != nil {
log.Fatal(err)
}
},
}
o.AddFlags(cmd)
flagSetter := config.NewFlagSetterFor(cmd)
config.AddBaseDirFlagBy(flagSetter)
config.AddMasterHostFlagsBy(flagSetter)
return cmd
}

View File

@@ -1,167 +0,0 @@
package options
import (
"github.com/beclab/Olares/cli/pkg/common"
cc "github.com/beclab/Olares/cli/pkg/core/common"
"github.com/beclab/Olares/cli/pkg/phase/cluster"
"github.com/spf13/cobra"
"k8s.io/utils/pointer"
)
type CliTerminusUninstallOptions struct {
Version string
BaseDir string
All bool
Phase string
Quiet bool
}
func NewCliTerminusUninstallOptions() *CliTerminusUninstallOptions {
return &CliTerminusUninstallOptions{}
}
func (o *CliTerminusUninstallOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVarP(&o.Version, "version", "v", "", "Set Olares version, e.g., 1.10.0, 1.10.0-20241109")
cmd.Flags().StringVarP(&o.BaseDir, "base-dir", "b", "", "Set Olares package base dir, defaults to $HOME/"+cc.DefaultBaseDir)
cmd.Flags().BoolVar(&o.All, "all", false, "Uninstall Olares completely, including prepared dependencies")
cmd.Flags().StringVar(&o.Phase, "phase", cluster.PhaseInstall.String(), "Uninstall from a specified phase and revert to the previous one. For example, using --phase install will remove the tasks performed in the 'install' phase, effectively returning the system to the 'prepare' state.")
cmd.Flags().BoolVar(&o.Quiet, "quiet", false, "Quiet mode, default: false")
}
type CliTerminusInstallOptions struct {
Version string
KubeType string
WithJuiceFS bool
MiniKubeProfile string
BaseDir string
EnableReverseProxy *bool
common.SwapConfig
}
func NewCliTerminusInstallOptions() *CliTerminusInstallOptions {
return &CliTerminusInstallOptions{
EnableReverseProxy: pointer.Bool(false),
}
}
func (o *CliTerminusInstallOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().BoolVar(o.EnableReverseProxy, "enable-reverse-proxy", false, "Enable reverse proxy, if not set, will be dynamically enabled if public IP is not detected, and disabled otherwise")
cmd.Flags().StringVarP(&o.Version, "version", "v", "", "Set Olares version, e.g., 1.10.0, 1.10.0-20241109")
cmd.Flags().StringVar(&o.KubeType, "kube", "k3s", "Set kube type, e.g., k3s or k8s")
cmd.Flags().BoolVar(&o.WithJuiceFS, "with-juicefs", false, "Use JuiceFS as the rootfs for Olares workloads, rather than the local disk.")
cmd.Flags().StringVarP(&o.MiniKubeProfile, "profile", "p", "", "Set Minikube profile name, only in MacOS platform, defaults to "+common.MinikubeDefaultProfile)
cmd.Flags().StringVarP(&o.BaseDir, "base-dir", "b", "", "Set Olares package base dir, defaults to $HOME/"+cc.DefaultBaseDir)
(&o.SwapConfig).AddFlags(cmd.Flags())
}
type CliPrepareSystemOptions struct {
Version string
KubeType string
RegistryMirrors string
BaseDir string
MinikubeProfile string
}
func NewCliPrepareSystemOptions() *CliPrepareSystemOptions {
return &CliPrepareSystemOptions{}
}
func (o *CliPrepareSystemOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVarP(&o.Version, "version", "v", "", "Set Olares version, e.g., 1.10.0, 1.10.0-20241109")
cmd.Flags().StringVar(&o.KubeType, "kube", "k3s", "Set kube type, e.g., k3s or k8s")
cmd.Flags().StringVarP(&o.RegistryMirrors, "registry-mirrors", "r", "", "Docker Container registry mirrors, multiple mirrors are separated by commas")
cmd.Flags().StringVarP(&o.BaseDir, "base-dir", "b", "", "Set Olares package base dir, defaults to $HOME/"+cc.DefaultBaseDir)
cmd.Flags().StringVarP(&o.MinikubeProfile, "profile", "p", "", "Set Minikube profile name, only in MacOS platform, defaults to "+common.MinikubeDefaultProfile)
}
type ChangeIPOptions struct {
Version string
BaseDir string
NewMasterHost string
WSLDistribution string
MinikubeProfile string
}
func NewChangeIPOptions() *ChangeIPOptions {
return &ChangeIPOptions{}
}
func (o *ChangeIPOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVarP(&o.Version, "version", "v", "", "Set Olares version, e.g., 1.10.0, 1.10.0-20241109")
cmd.Flags().StringVarP(&o.BaseDir, "base-dir", "b", "", "Set Olares package base dir, defaults to $HOME/"+cc.DefaultBaseDir)
cmd.Flags().StringVar(&o.NewMasterHost, "new-master-host", "", "Update the master node's IP if it's changed, only in Linux worker node")
cmd.Flags().StringVarP(&o.WSLDistribution, "distribution", "d", "", "Set WSL distribution name, only in Windows platform, defaults to "+common.WSLDefaultDistribution)
cmd.Flags().StringVarP(&o.MinikubeProfile, "profile", "p", "", "Set Minikube profile name, only in MacOS platform, defaults to "+common.MinikubeDefaultProfile)
}
type PreCheckOptions struct {
Version string
BaseDir string
}
func NewPreCheckOptions() *PreCheckOptions {
return &PreCheckOptions{}
}
func (o *PreCheckOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVarP(&o.Version, "version", "v", "", "Set Olares version, e.g., 1.10.0, 1.10.0-20241109")
cmd.Flags().StringVarP(&o.BaseDir, "base-dir", "b", "", "Set Olares package base dir, defaults to $HOME/"+cc.DefaultBaseDir)
}
type InstallStorageOptions struct {
Version string
BaseDir string
}
func NewInstallStorageOptions() *InstallStorageOptions {
return &InstallStorageOptions{}
}
func (o *InstallStorageOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVarP(&o.Version, "version", "v", "", "Set Olares version, e.g., 1.10.0, 1.10.0-20241109")
cmd.Flags().StringVarP(&o.BaseDir, "base-dir", "b", "", "Set Olares package base dir, defaults to $HOME/"+cc.DefaultBaseDir)
}
type AddNodeOptions struct {
common.MasterHostConfig
Version string
BaseDir string
}
func NewAddNodeOptions() *AddNodeOptions {
return &AddNodeOptions{}
}
func (o *AddNodeOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVarP(&o.Version, "version", "v", "", "Set Olares version, e.g., 1.10.0, 1.10.0-20241109")
cmd.Flags().StringVarP(&o.BaseDir, "base-dir", "b", "", "Set Olares package base dir, defaults to $HOME/"+cc.DefaultBaseDir)
(&o.MasterHostConfig).AddFlags(cmd.Flags())
}
type MasterInfoOptions struct {
BaseDir string
common.MasterHostConfig
}
func NewMasterInfoOptions() *MasterInfoOptions {
return &MasterInfoOptions{}
}
func (o *MasterInfoOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVarP(&o.BaseDir, "base-dir", "b", "", "Set Olares package base dir, defaults to $HOME/"+cc.DefaultBaseDir)
(&o.MasterHostConfig).AddFlags(cmd.Flags())
}
type UpgradeOptions struct {
Version string
BaseDir string
}
func NewUpgradeOptions() *UpgradeOptions {
return &UpgradeOptions{}
}
func (o *UpgradeOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVarP(&o.Version, "version", "v", "", "Set target Olares version to upgrade to, e.g., 1.10.0, 1.10.0-20241109")
cmd.Flags().StringVarP(&o.BaseDir, "base-dir", "b", "", "Set Olares package base dir, defaults to $HOME/"+cc.DefaultBaseDir)
}

View File

@@ -1,48 +0,0 @@
package options
import (
cc "github.com/beclab/Olares/cli/pkg/core/common"
"github.com/spf13/cobra"
)
type CliDownloadWizardOptions struct {
Version string
KubeType string
BaseDir string
CDNService string
ReleaseID string
UrlOverride string
}
func NewCliDownloadWizardOptions() *CliDownloadWizardOptions {
return &CliDownloadWizardOptions{}
}
func (o *CliDownloadWizardOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVarP(&o.Version, "version", "v", "", "Set Olares version, e.g., 1.10.0, 1.10.0-20241109")
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.CDNService, "cdn-service", "", "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")
cmd.Flags().StringVar(&o.ReleaseID, "release-id", "", "Set the specific release id of the release version")
}
type CliDownloadOptions struct {
Version string
KubeType string
Manifest string
BaseDir string
CDNService string
}
func NewCliDownloadOptions() *CliDownloadOptions {
return &CliDownloadOptions{}
}
func (o *CliDownloadOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVarP(&o.Version, "version", "v", "", "Set Olares version, e.g., 1.10.0, 1.10.0-20241109")
cmd.Flags().StringVarP(&o.BaseDir, "base-dir", "b", "", "Set Olares package base dir , defaults to $HOME/"+cc.DefaultBaseDir)
cmd.Flags().StringVar(&o.Manifest, "manifest", "", "Set package manifest file , defaults to {base-dir}/versions/v{version}/installation.manifest")
cmd.Flags().StringVar(&o.KubeType, "kube", "k3s", "Set kube type, e.g., k3s or k8s")
cmd.Flags().StringVar(&o.CDNService, "cdn-service", "", "Set the CDN accelerated download address in the format https://example.cdn.com. If not set, the default download address will be used")
}

View File

@@ -1,33 +0,0 @@
package options
import (
"fmt"
"github.com/beclab/Olares/cli/pkg/common"
cc "github.com/beclab/Olares/cli/pkg/core/common"
"github.com/spf13/cobra"
)
type GpuOptions struct {
Version string
BaseDir string
}
func (o *GpuOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVarP(&o.Version, "version", "v", "", "Set Olares version, e.g., 1.10.0, 1.10.0-20241109")
cmd.Flags().StringVarP(&o.BaseDir, "base-dir", "b", "", "Set Olares package base dir, defaults to $HOME/"+cc.DefaultBaseDir)
}
type InstallGpuOptions struct {
GpuOptions
Cuda string
}
func NewInstallGpuOptions() *InstallGpuOptions {
return &InstallGpuOptions{}
}
func (o *InstallGpuOptions) AddFlags(cmd *cobra.Command) {
o.GpuOptions.AddFlags(cmd)
cmd.Flags().StringVar(&o.Cuda, "cuda", "", fmt.Sprintf("The version of the CUDA driver, current supported versions are %s", common.CurrentVerifiedCudaVersion))
}

View File

@@ -3,22 +3,36 @@ package os
import (
"log"
"github.com/beclab/Olares/cli/cmd/ctl/options"
"github.com/beclab/Olares/cli/cmd/config"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/pipelines"
"github.com/spf13/cobra"
)
func NewCmdChangeIP() *cobra.Command {
o := options.NewChangeIPOptions()
cmd := &cobra.Command{
Use: "change-ip",
Short: "change The IP address of Olares OS",
Run: func(cmd *cobra.Command, args []string) {
if err := pipelines.ChangeIPPipeline(o); err != nil {
if err := pipelines.ChangeIPPipeline(); err != nil {
log.Fatalf("error: %v", err)
}
},
}
o.AddFlags(cmd)
// todo: merge master host config with release info
// be backward compatible with old version and olaresd
flagSetter := config.NewFlagSetterFor(cmd)
config.AddVersionFlagBy(flagSetter)
config.AddBaseDirFlagBy(flagSetter)
config.AddMasterHostFlagsBy(flagSetter)
flagSetter.Add(common.FlagWSLDistribution,
"d",
"",
"Set WSL distribution name, only on Windows platform, defaults to "+common.WSLDefaultDistribution,
).WithAlias(common.FlagLegacyWSLDistribution)
config.AddMiniKubeProfileFlagBy(flagSetter)
return cmd
}

View File

@@ -3,7 +3,8 @@ package os
import (
"log"
"github.com/beclab/Olares/cli/cmd/ctl/options"
"github.com/beclab/Olares/cli/cmd/config"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/pipelines"
"github.com/spf13/cobra"
)
@@ -22,52 +23,61 @@ func NewCmdRootDownload() *cobra.Command {
}
func NewCmdDownload() *cobra.Command {
o := options.NewCliDownloadOptions()
cmd := &cobra.Command{
Use: "component",
Short: "Download the packages and components needed to install Olares",
Run: func(cmd *cobra.Command, args []string) {
if err := pipelines.DownloadInstallationPackage(o); err != nil {
if err := pipelines.DownloadInstallationPackage(); err != nil {
log.Fatalf("error: %v", err)
}
},
}
flagSetter := config.NewFlagSetterFor(cmd)
config.AddVersionFlagBy(flagSetter)
config.AddBaseDirFlagBy(flagSetter)
config.AddCDNServiceFlagBy(flagSetter)
config.AddManifestFlagBy(flagSetter)
o.AddFlags(cmd)
return cmd
}
func NewCmdDownloadWizard() *cobra.Command {
o := options.NewCliDownloadWizardOptions()
cmd := &cobra.Command{
Use: "wizard",
Short: "Download the Olares installation wizard",
Run: func(cmd *cobra.Command, args []string) {
if err := pipelines.DownloadInstallationWizard(o); err != nil {
if err := pipelines.DownloadInstallationWizard(); err != nil {
log.Fatalf("error: %v", err)
}
},
}
flagSetter := config.NewFlagSetterFor(cmd)
o.AddFlags(cmd)
flagSetter.Add(common.FlagReleaseID, "", "", "Set the specific release id of the release version")
flagSetter.Add(common.FlagURLOverride, "", "", "Set another URL for wizard download explicitly")
config.AddVersionFlagBy(flagSetter)
config.AddBaseDirFlagBy(flagSetter)
config.AddCDNServiceFlagBy(flagSetter)
return cmd
}
func NewCmdCheckDownload() *cobra.Command {
o := options.NewCliDownloadOptions()
cmd := &cobra.Command{
Use: "check",
Short: "Check Downloaded Olares Installation Package",
Run: func(cmd *cobra.Command, args []string) {
if err := pipelines.CheckDownloadInstallationPackage(o); err != nil {
if err := pipelines.CheckDownloadInstallationPackage(); err != nil {
log.Fatalf("error: %v", err)
}
},
}
o.AddFlags(cmd)
flagSetter := config.NewFlagSetterFor(cmd)
config.AddVersionFlagBy(flagSetter)
config.AddBaseDirFlagBy(flagSetter)
config.AddManifestFlagBy(flagSetter)
return cmd
}

View File

@@ -3,36 +3,81 @@ package os
import (
"log"
"github.com/beclab/Olares/cli/cmd/ctl/options"
"github.com/beclab/Olares/cli/cmd/config"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/pipelines"
"github.com/spf13/cobra"
)
type InstallOsOptions struct {
InstallOptions *options.CliTerminusInstallOptions
}
func NewInstallOsOptions() *InstallOsOptions {
return &InstallOsOptions{
InstallOptions: options.NewCliTerminusInstallOptions(),
}
}
func NewCmdInstallOs() *cobra.Command {
o := NewInstallOsOptions()
cmd := &cobra.Command{
Use: "install",
Short: "Install Olares",
Run: func(cmd *cobra.Command, args []string) {
if !cmd.Flags().Changed("enable-reverse-proxy") {
o.InstallOptions.EnableReverseProxy = nil
}
if err := pipelines.CliInstallTerminusPipeline(o.InstallOptions); err != nil {
if err := pipelines.CliInstallTerminusPipeline(); err != nil {
log.Fatalf("error: %v", err)
}
},
}
o.InstallOptions.AddFlags(cmd)
flagSetter := config.NewFlagSetterFor(cmd)
flagSetter.Add(common.FlagOSUserName,
"",
"",
"Set the username for the Olares instance, if not set, will be prompted for input",
).WithEnv(common.EnvLegacyOSUserName)
flagSetter.Add(common.FlagOSDomainName,
"",
"",
"Set the domain name for the Olares instance, if not set, will be prompted for input",
).WithEnv(common.EnvLegacyOSDomainName)
flagSetter.Add(common.FlagOSPassword,
"",
"",
"Set the inital password for the first user of the Olares instance, if not set, a randomly generated password will be used",
)
flagSetter.Add(common.FlagEnableReverseProxy,
"",
false,
"Enable reverse proxy, if not set, will be dynamically enabled if public IP is not detected, and disabled otherwise",
)
flagSetter.Add(common.FlagEnableJuiceFS,
"",
false,
"Use JuiceFS as the rootfs for Olares workloads, rather than the local disk.",
).WithAlias(common.FlagLegacyEnableJuiceFS).WithEnv(common.EnvLegacyEnableJuiceFS)
flagSetter.Add(common.FlagEnablePodSwap,
"",
false,
"Enable pods on Kubernetes cluster to use swap, setting --enable-zram, --zram-size or --zram-swap-priority implicitly enables this option, regardless of the command line args, note that only pods of the BestEffort QOS group can use swap due to K8s design",
)
flagSetter.Add(common.FlagSwappiness,
"",
false,
"Configure the Linux swappiness value, if not set, the current configuration is remained",
)
flagSetter.Add(common.FlagEnableZRAM,
"",
false,
"Set up a ZRAM device to be used for swap, setting --zram-size or --zram-swap-priority implicitly enables this option, regardless of the command line args",
)
flagSetter.Add(common.FlagZRAMSize,
"",
"",
"Set the size of the ZRAM device, takes a format of https://kubernetes.io/docs/reference/kubernetes-api/common-definitions/quantity, defaults to half of the total RAM",
)
flagSetter.Add(common.FlagZRAMSwapPriority,
"",
false,
"Set the swap priority of the ZRAM device, between -1 and 32767, defaults to 100",
)
config.AddCDNServiceFlagBy(flagSetter)
config.AddVersionFlagBy(flagSetter)
config.AddBaseDirFlagBy(flagSetter)
config.AddStorageFlagsBy(flagSetter)
config.AddKubeTypeFlagBy(flagSetter)
config.AddMiniKubeProfileFlagBy(flagSetter)
cmd.AddCommand(NewCmdInstallStorage())
return cmd
}

View File

@@ -3,22 +3,28 @@ package os
import (
"archive/tar"
"compress/gzip"
"context"
"fmt"
"io"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"log"
"net"
"os"
"os/exec"
"path/filepath"
ctrl "sigs.k8s.io/controller-runtime"
"strings"
"time"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
ctrl "sigs.k8s.io/controller-runtime"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/core/util"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
// LogCollectOptions holds options for collecting logs
@@ -242,7 +248,6 @@ func collectSystemdLogs(tw *tar.Writer, options *LogCollectOptions) error {
if err := cmd.Run(); err != nil {
logFile.Close()
return fmt.Errorf("failed to collect logs for %s: %v", service, err)
continue
}
logFile.Close()
@@ -276,7 +281,7 @@ func collectSystemdLogs(tw *tar.Writer, options *LogCollectOptions) error {
}
func collectDmesgLogs(tw *tar.Writer, options *LogCollectOptions) error {
cmd := exec.Command("dmesg")
cmd := exec.Command("dmesg -T")
output, err := cmd.Output()
if err != nil {
return err
@@ -375,49 +380,153 @@ func collectKubernetesLogs(tw *tar.Writer, options *LogCollectOptions) error {
}
}
cmd = exec.Command("kubectl", "describe", "pods", "--all-namespaces")
output, err = tryKubectlCommand(cmd, "describe pods", options)
if err != nil && !options.IgnoreKubeErrors {
return err
}
if err == nil {
header := &tar.Header{
Name: "pods-describe.txt",
Mode: 0644,
Size: int64(len(output)),
ModTime: time.Now(),
resourceTypes := []string{"node", "pod", "statefulset", "deployment", "replicaset", "service", "configmap"}
for _, res := range resourceTypes {
cmd = exec.Command("kubectl", "describe", res, "--all-namespaces")
output, err = tryKubectlCommand(cmd, fmt.Sprintf("describe %s", res), options)
if err != nil && !options.IgnoreKubeErrors {
return err
}
if err := tw.WriteHeader(header); err != nil {
return fmt.Errorf("failed to write pods description header: %v", err)
}
if _, err := tw.Write(output); err != nil {
return fmt.Errorf("failed to write pods description data: %v", err)
if err == nil {
header := &tar.Header{
Name: fmt.Sprintf("%s-describe.txt", res),
Mode: 0644,
Size: int64(len(output)),
ModTime: time.Now(),
}
if err := tw.WriteHeader(header); err != nil {
return fmt.Errorf("failed to write %s description header: %v", res, err)
}
if _, err := tw.Write(output); err != nil {
return fmt.Errorf("failed to write %s description data: %v", res, err)
}
}
}
cmd = exec.Command("kubectl", "describe", "node")
output, err = tryKubectlCommand(cmd, "describe node", options)
if err != nil && !options.IgnoreKubeErrors {
return err
}
if err == nil {
header := &tar.Header{
Name: "node-describe.txt",
Mode: 0644,
Size: int64(len(output)),
ModTime: time.Now(),
}
if err := tw.WriteHeader(header); err != nil {
return fmt.Errorf("failed to write node description header: %v", err)
}
if _, err := tw.Write(output); err != nil {
return fmt.Errorf("failed to write node description data: %v", err)
if err := collectNginxLogsFromLabeledPods(tw); err != nil {
if !options.IgnoreKubeErrors {
return fmt.Errorf("failed to collect nginx logs from labeled pods: %v", err)
}
}
return nil
}
func collectNginxLogsFromLabeledPods(tw *tar.Writer) error {
if _, err := util.GetCommand("kubectl"); err != nil {
fmt.Printf("warning: kubectl not found, skipping collecting nginx logs from labeled pods\n")
return nil
}
cfg, err := ctrl.GetConfig()
if err != nil {
return fmt.Errorf("failed to get kubeconfig: %v", err)
}
clientset, err := kubernetes.NewForConfig(cfg)
if err != nil {
return fmt.Errorf("failed to create kube client: %v", err)
}
type selectorSpec struct {
LabelSelector string
ContainerName string
}
selectors := []selectorSpec{
{LabelSelector: "app=l4-bfl-proxy", ContainerName: ""},
{LabelSelector: "tier=bfl", ContainerName: "ingress"},
}
type targetPod struct {
Namespace string
Name string
ContainerName string
}
var targets []targetPod
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
for _, sel := range selectors {
podList, err := clientset.CoreV1().Pods(corev1.NamespaceAll).List(ctx, metav1.ListOptions{LabelSelector: sel.LabelSelector})
if err != nil {
return fmt.Errorf("failed to list pods by label %q: %v", sel.LabelSelector, err)
}
for _, pod := range podList.Items {
targets = append(targets, targetPod{
Namespace: pod.Namespace,
Name: pod.Name,
ContainerName: sel.ContainerName,
})
}
}
if len(targets) == 0 {
return nil
}
// simplest approach: use kubectl cp (it already implements copy via tar over exec)
tempDir, err := os.MkdirTemp("", "olares-nginx-logs-*")
if err != nil {
return fmt.Errorf("failed to create temp directory for nginx logs: %v", err)
}
defer os.RemoveAll(tempDir)
files := []string{"/var/log/nginx/access.log", "/var/log/nginx/error.log"}
for _, target := range targets {
for _, remotePath := range files {
base := filepath.Base(remotePath)
archivePath := filepath.Join("nginx", target.Namespace, target.Name, base)
dest := filepath.Join(tempDir, fmt.Sprintf("%s__%s__%s", target.Namespace, target.Name, base))
err := kubectlCopyFile(target.Namespace, target.Name, target.ContainerName, remotePath, dest)
if err != nil {
return fmt.Errorf("failed to kubectl cp %s/%s:%s: %v", target.Namespace, target.Name, remotePath, err)
}
fi, err := os.Stat(dest)
if err != nil {
return fmt.Errorf("failed to stat copied nginx log %s: %v", dest, err)
}
f, err := os.Open(dest)
if err != nil {
return fmt.Errorf("failed to open copied nginx log %s: %v", dest, err)
}
defer f.Close()
header := &tar.Header{
Name: archivePath,
Mode: 0644,
Size: fi.Size(),
ModTime: time.Now(),
}
if err := tw.WriteHeader(header); err != nil {
return fmt.Errorf("failed to write header for %s: %v", archivePath, err)
}
if _, err := io.CopyN(tw, f, header.Size); err != nil {
return fmt.Errorf("failed to write data for %s: %v", archivePath, err)
}
}
}
return nil
}
func kubectlCopyFile(namespace, pod, container, remotePath, destPath string) error {
args := []string{"-n", namespace, "cp"}
if container != "" {
args = append(args, "-c", container)
}
args = append(args, fmt.Sprintf("%s:%s", pod, remotePath), destPath)
cmd := exec.Command("kubectl", args...)
if out, err := cmd.CombinedOutput(); err != nil {
return fmt.Errorf("kubectl %s failed: %v, output: %s", strings.Join(args, " "), err, strings.TrimSpace(string(out)))
}
return nil
}
func collectNetworkConfigs(tw *tar.Writer, options *LogCollectOptions) error {
if _, err := util.GetCommand("ip"); err == nil {
cmd := exec.Command("ip", "address")
@@ -501,13 +610,9 @@ func collectNetworkConfigs(tw *tar.Writer, options *LogCollectOptions) error {
}
func getBaseDir() (string, error) {
// quick path to get basedir from argument instance
arg := &common.Argument{}
if err := arg.LoadReleaseInfo(); err != nil {
return "", fmt.Errorf("failed to load olares release info: %v", err)
}
if arg.BaseDir != "" {
return arg.BaseDir, nil
basedir := viper.GetString(common.FlagBaseDir)
if basedir != "" {
return basedir, nil
}
homeDir, err := util.Home()
if err != nil {

View File

@@ -3,22 +3,23 @@ package os
import (
"log"
"github.com/beclab/Olares/cli/cmd/ctl/options"
"github.com/beclab/Olares/cli/cmd/config"
"github.com/beclab/Olares/cli/pkg/pipelines"
"github.com/spf13/cobra"
)
func NewCmdPrecheck() *cobra.Command {
o := options.NewPreCheckOptions()
cmd := &cobra.Command{
Use: "precheck",
Short: "precheck the installation compatibility of the system",
Run: func(cmd *cobra.Command, args []string) {
if err := pipelines.StartPreCheckPipeline(o); err != nil {
if err := pipelines.StartPreCheckPipeline(); err != nil {
log.Fatalf("error: %v", err)
}
},
}
o.AddFlags(cmd)
flagSetter := config.NewFlagSetterFor(cmd)
config.AddVersionFlagBy(flagSetter)
config.AddBaseDirFlagBy(flagSetter)
return cmd
}

View File

@@ -3,32 +3,34 @@ package os
import (
"log"
"github.com/beclab/Olares/cli/cmd/ctl/options"
"github.com/beclab/Olares/cli/cmd/config"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/pipelines"
"github.com/spf13/cobra"
)
type PrepareSystemOptions struct {
PrepareOptions *options.CliPrepareSystemOptions
}
func NewPrepareSystemOptions() *PrepareSystemOptions {
return &PrepareSystemOptions{
PrepareOptions: options.NewCliPrepareSystemOptions(),
}
}
func NewCmdPrepare() *cobra.Command {
o := NewPrepareSystemOptions()
cmd := &cobra.Command{
Use: "prepare [component1 component2 ...]",
Short: "Prepare install",
Run: func(cmd *cobra.Command, args []string) {
if err := pipelines.PrepareSystemPipeline(o.PrepareOptions, args); err != nil {
if err := pipelines.PrepareSystemPipeline(args); err != nil {
log.Fatalf("error: %v", err)
}
},
}
o.PrepareOptions.AddFlags(cmd)
flagSetter := config.NewFlagSetterFor(cmd)
flagSetter.Add(common.FlagRegistryMirrors,
"r",
"",
"Extra Docker Container registry mirrors, multiple mirrors are separated by commas",
)
config.AddVersionFlagBy(flagSetter)
config.AddBaseDirFlagBy(flagSetter)
config.AddStorageFlagsBy(flagSetter)
config.AddKubeTypeFlagBy(flagSetter)
config.AddMiniKubeProfileFlagBy(flagSetter)
return cmd
}

View File

@@ -8,26 +8,27 @@ import (
"strings"
"time"
"github.com/beclab/Olares/cli/pkg/core/common"
"github.com/beclab/Olares/cli/cmd/config"
"github.com/beclab/Olares/cli/pkg/common"
corecommon "github.com/beclab/Olares/cli/pkg/core/common"
"github.com/beclab/Olares/cli/pkg/core/util"
"github.com/beclab/Olares/cli/pkg/release/builder"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
func NewCmdRelease() *cobra.Command {
var (
baseDir string
version string
cdn string
ignoreMissingImages bool
extract bool
)
cmd := &cobra.Command{
Use: "release",
Short: "Build release based on a local Olares repository",
Run: func(cmd *cobra.Command, args []string) {
baseDir := viper.GetString(common.FlagBaseDir)
version := viper.GetString(common.FlagVersion)
cdn := viper.GetString(common.FlagCDNService)
ignoreMissingImages := viper.GetBool(common.FlagIgnoreMissingImages)
extract := viper.GetBool(common.FlagExtract)
cwd, err := os.Getwd()
if err != nil {
fmt.Printf("failed to get current working directory: %s\n", err)
@@ -43,13 +44,13 @@ func NewCmdRelease() *cobra.Command {
fmt.Printf("failed to get current user: %s\n", err)
os.Exit(1)
}
baseDir = filepath.Join(usr.HomeDir, common.DefaultBaseDir)
baseDir = filepath.Join(usr.HomeDir, corecommon.DefaultBaseDir)
fmt.Printf("--base-dir unspecified, using: %s\n", baseDir)
time.Sleep(1 * time.Second)
}
if version == "" {
version = fmt.Sprintf("1.12.4-%s", time.Now().Format("20060102150405"))
version = fmt.Sprintf("1.12.6-%s", time.Now().Format("20060102150405"))
fmt.Printf("--version unspecified, using: %s\n", version)
time.Sleep(1 * time.Second)
}
@@ -75,11 +76,20 @@ func NewCmdRelease() *cobra.Command {
},
}
cmd.Flags().StringVarP(&baseDir, "base-dir", "b", "", "base directory of Olares, where this release will be extracted to as a new version if --extract/-e is not disabled, defaults to $HOME/"+common.DefaultBaseDir)
cmd.Flags().StringVarP(&version, "version", "v", "", "version of this release, defaults to 0.0.0-local-dev-{yyyymmddhhmmss}")
cmd.Flags().StringVar(&cdn, "cdn-service", common.DefaultOlaresCDNService, "CDN used for downloading checksums of dependencies and images")
cmd.Flags().BoolVar(&ignoreMissingImages, "ignore-missing-images", true, "ignore missing images when downloading cheksums from CDN, only disable this if no new image is added, or the build may fail because the image is not uploaded to the CDN yet")
cmd.Flags().BoolVarP(&extract, "extract", "e", true, "extract this release to --base-dir after build, this can be disabled if only the release file itself is needed")
flagSetter := config.NewFlagSetterFor(cmd)
config.AddBaseDirFlagBy(flagSetter)
config.AddVersionFlagBy(flagSetter)
config.AddCDNServiceFlagBy(flagSetter)
flagSetter.Add(common.FlagIgnoreMissingImages,
"",
true,
"ignore missing images when downloading checksums from CDN, only disable this if no new image is added, or the build may fail because the image is not uploaded to the CDN yet",
)
flagSetter.Add(common.FlagExtract,
"e",
true,
"extract this release to --base-dir after build, this can be disabled if only the release file itself is needed",
)
return cmd
}

View File

@@ -3,23 +3,26 @@ package os
import (
"log"
"github.com/beclab/Olares/cli/cmd/ctl/options"
"github.com/beclab/Olares/cli/cmd/config"
"github.com/beclab/Olares/cli/pkg/pipelines"
"github.com/spf13/cobra"
)
func NewCmdInstallStorage() *cobra.Command {
o := options.NewInstallStorageOptions()
cmd := &cobra.Command{
Use: "storage",
Short: "install a storage backend for the Olares shared filesystem, or in the case of external storage, validate the config",
Run: func(cmd *cobra.Command, args []string) {
if err := pipelines.CliInstallStoragePipeline(o); err != nil {
if err := pipelines.CliInstallStoragePipeline(); err != nil {
log.Fatalf("error: %v", err)
}
},
}
o.AddFlags(cmd)
flagSetter := config.NewFlagSetterFor(cmd)
config.AddVersionFlagBy(flagSetter)
config.AddBaseDirFlagBy(flagSetter)
config.AddStorageFlagsBy(flagSetter)
return cmd
}

View File

@@ -3,33 +3,37 @@ package os
import (
"log"
"github.com/beclab/Olares/cli/cmd/ctl/options"
"github.com/beclab/Olares/cli/cmd/config"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/phase/cluster"
"github.com/beclab/Olares/cli/pkg/pipelines"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
type UninstallOsOptions struct {
UninstallOptions *options.CliTerminusUninstallOptions
}
func NewUninstallOsOptions() *UninstallOsOptions {
return &UninstallOsOptions{
UninstallOptions: options.NewCliTerminusUninstallOptions(),
}
}
func NewCmdUninstallOs() *cobra.Command {
o := NewUninstallOsOptions()
cmd := &cobra.Command{
Use: "uninstall",
Short: "Uninstall Olares",
Run: func(cmd *cobra.Command, args []string) {
err := pipelines.UninstallTerminusPipeline(o.UninstallOptions)
err := pipelines.UninstallTerminusPipeline()
if err != nil {
log.Fatalf("error: %v", err)
}
},
}
o.UninstallOptions.AddFlags(cmd)
flagSetter := config.NewFlagSetterFor(cmd)
config.AddVersionFlagBy(flagSetter)
config.AddBaseDirFlagBy(flagSetter)
config.AddStorageFlagsBy(flagSetter)
// these two flags' names are too general, and only used in cmd options, so we manually bind them to the viper
// inside the pipeline creator, it still uses the flag vars to get the values
cmd.Flags().Bool("all", false, "Uninstall Olares completely, including prepared dependencies")
viper.BindPFlag(common.FlagUninstallAll, cmd.Flags().Lookup("all"))
cmd.Flags().String("phase", cluster.PhaseInstall.String(), "Uninstall from a specified phase and revert to the previous one. For example, using --phase install will remove the tasks performed in the 'install' phase, effectively returning the system to the 'prepare' state.")
viper.BindPFlag(common.FlagUninstallPhase, cmd.Flags().Lookup("phase"))
return cmd
}

View File

@@ -3,39 +3,33 @@ package os
import (
"encoding/json"
"fmt"
"log"
"os"
"github.com/Masterminds/semver/v3"
"github.com/beclab/Olares/cli/cmd/ctl/options"
"github.com/beclab/Olares/cli/cmd/config"
"github.com/beclab/Olares/cli/pkg/phase"
"github.com/beclab/Olares/cli/pkg/pipelines"
"github.com/beclab/Olares/cli/pkg/upgrade"
"github.com/beclab/Olares/cli/version"
"github.com/spf13/cobra"
"log"
"os"
)
type UpgradeOsOptions struct {
UpgradeOptions *options.UpgradeOptions
}
func NewUpgradeOsOptions() *UpgradeOsOptions {
return &UpgradeOsOptions{
UpgradeOptions: options.NewUpgradeOptions(),
}
}
func NewCmdUpgradeOs() *cobra.Command {
o := NewUpgradeOsOptions()
cmd := &cobra.Command{
Use: "upgrade",
Short: "Upgrade Olares to a newer version",
Run: func(cmd *cobra.Command, args []string) {
if err := pipelines.UpgradeOlaresPipeline(o.UpgradeOptions); err != nil {
if err := pipelines.UpgradeOlaresPipeline(); err != nil {
log.Fatalf("error: %v", err)
}
},
}
o.UpgradeOptions.AddFlags(cmd)
flagSetter := config.NewFlagSetterFor(cmd)
config.AddVersionFlagBy(flagSetter)
config.AddBaseDirFlagBy(flagSetter)
cmd.AddCommand(NewCmdCurrentVersionUpgradeSpec())
cmd.AddCommand(NewCmdUpgradeViable())
cmd.AddCommand(NewCmdUpgradePrecheck())

View File

@@ -1,6 +1,10 @@
package ctl
import (
"fmt"
"github.com/beclab/Olares/cli/cmd/config"
"github.com/beclab/Olares/cli/cmd/ctl/amdgpu"
"github.com/beclab/Olares/cli/cmd/ctl/disk"
"github.com/beclab/Olares/cli/cmd/ctl/gpu"
"github.com/beclab/Olares/cli/cmd/ctl/node"
@@ -9,18 +13,27 @@ import (
"github.com/beclab/Olares/cli/cmd/ctl/user"
"github.com/beclab/Olares/cli/version"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
func NewDefaultCommand() *cobra.Command {
var showVendor bool
cobra.OnInitialize(func() {
config.Init()
})
cmds := &cobra.Command{
Use: "olares-cli",
Short: "Olares Installer",
CompletionOptions: cobra.CompletionOptions{DisableDefaultCmd: true},
Version: version.VERSION,
PersistentPreRun: func(cmd *cobra.Command, args []string) {
viper.BindPFlags(cmd.InheritedFlags())
viper.BindPFlags(cmd.PersistentFlags())
viper.BindPFlags(cmd.Flags())
},
Run: func(cmd *cobra.Command, args []string) {
if showVendor {
println(version.VENDOR)
fmt.Println(version.VENDOR)
} else {
cmd.Usage()
}
@@ -33,6 +46,7 @@ func NewDefaultCommand() *cobra.Command {
cmds.AddCommand(os.NewOSCommands()...)
cmds.AddCommand(node.NewNodeCommand())
cmds.AddCommand(gpu.NewCmdGpu())
cmds.AddCommand(amdgpu.NewCmdAmdGpu())
cmds.AddCommand(user.NewUserCommand())
cmds.AddCommand(disk.NewDiskCommand())

View File

@@ -1,15 +1,16 @@
package user
import (
"bytetrade.io/web3os/app-service/api/sys.bytetrade.io/v1alpha1"
"context"
"fmt"
"log"
"strings"
"github.com/beclab/Olares/cli/pkg/utils"
"github.com/beclab/Olares/framework/app-service/api/sys.bytetrade.io/v1alpha1"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/validation"
"log"
"strings"
iamv1alpha2 "github.com/beclab/api/iam/v1alpha2"
"github.com/spf13/cobra"

View File

@@ -1,16 +1,17 @@
package user
import (
"bytetrade.io/web3os/app-service/api/sys.bytetrade.io/v1alpha1"
"fmt"
"os"
"strconv"
"time"
"github.com/beclab/Olares/framework/app-service/api/sys.bytetrade.io/v1alpha1"
iamv1alpha2 "github.com/beclab/api/iam/v1alpha2"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/tools/clientcmd"
"os"
"sigs.k8s.io/controller-runtime/pkg/client"
"strconv"
"time"
)
func newUserClientFromKubeConfig(kubeconfig string) (client.Client, error) {

View File

@@ -1,27 +1,21 @@
module github.com/beclab/Olares/cli
go 1.24.2
toolchain go1.24.6
go 1.24.11
replace (
bytetrade.io/web3os/app-service => github.com/beclab/app-service v0.4.41
bytetrade.io/web3os/backups-sdk => github.com/Above-Os/backups-sdk v0.1.17
github.com/containers/image/v5 => github.com/containers/image/v5 v5.21.1
github.com/containers/storage => github.com/containers/storage v1.40.0
github.com/estesp/manifest-tool/v2 => github.com/estesp/manifest-tool/v2 v2.0.3
github.com/opencontainers/image-spec => github.com/opencontainers/image-spec v1.1.0
)
require (
bytetrade.io/web3os/app-service v0.0.0-00010101000000-000000000000
bytetrade.io/web3os/backups-sdk v0.0.0-00010101000000-000000000000
github.com/Masterminds/semver/v3 v3.4.0
github.com/PaesslerAG/jsonpath v0.1.1
github.com/alecthomas/assert/v2 v2.11.0
github.com/beclab/Olares/framework/app-service v0.0.0-20251225061130-909b7656fd70
github.com/beclab/api v0.0.2
github.com/cavaliergopher/grab/v3 v3.0.1
github.com/containerd/containerd v1.7.28
github.com/containerd/containerd v1.7.29
github.com/decentralized-identity/web5-go v0.25.0
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0
github.com/distribution/reference v0.6.0
@@ -30,8 +24,6 @@ require (
github.com/joho/godotenv v1.5.1
github.com/libp2p/go-netroute v0.2.2
github.com/lithammer/dedent v1.1.0
github.com/mitchellh/mapstructure v1.4.1
github.com/modood/table v0.0.0-20220527013332-8d47e76dad33
github.com/mr-tron/base58 v1.2.0
github.com/multiformats/go-varint v0.0.7
github.com/pelletier/go-toml v1.9.5
@@ -43,15 +35,16 @@ require (
github.com/shirou/gopsutil/v4 v4.25.7
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c
github.com/spf13/cobra v1.9.1
github.com/spf13/pflag v1.0.7
github.com/spf13/pflag v1.0.10
github.com/spf13/viper v1.21.0
github.com/stretchr/testify v1.11.1
github.com/syndtr/goleveldb v1.0.0
github.com/tyler-smith/go-bip39 v1.1.0
go.uber.org/zap v1.27.0
golang.org/x/crypto v0.41.0
golang.org/x/sys v0.35.0
golang.org/x/term v0.34.0
golang.org/x/text v0.28.0
golang.org/x/crypto v0.45.0
golang.org/x/sys v0.38.0
golang.org/x/term v0.37.0
golang.org/x/text v0.31.0
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
helm.sh/helm/v3 v3.18.6
@@ -94,9 +87,11 @@ require (
github.com/containerd/platforms v0.2.1 // indirect
github.com/containerd/ttrpc v1.2.7 // indirect
github.com/containerd/typeurl/v2 v2.2.3 // indirect
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
github.com/containers/image/v5 v5.36.1 // indirect
github.com/containers/storage v1.59.1 // indirect
github.com/cyphar/filepath-securejoin v0.5.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
github.com/dlclark/regexp2 v1.11.5 // 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.13.0 // indirect
@@ -118,6 +113,7 @@ require (
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/swag v0.23.1 // indirect
github.com/go-resty/resty/v2 v2.16.5 // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/gobwas/glob v0.2.4-0.20181002190808-e7a84e9525fe // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
@@ -174,7 +170,8 @@ require (
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/opencontainers/runtime-spec v1.2.1 // indirect
github.com/opencontainers/selinux v1.12.0 // indirect
github.com/opencontainers/selinux v1.13.1 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
@@ -185,11 +182,14 @@ require (
github.com/rivo/uniseg v0.4.7 // indirect
github.com/rubenv/sql-migrate v1.8.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sagikazarmark/locafero v0.11.0 // indirect
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect
github.com/shopspring/decimal v1.4.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartystreets/goconvey v1.8.1 // indirect
github.com/spf13/cast v1.9.2 // indirect
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
github.com/spf13/afero v1.15.0 // indirect
github.com/spf13/cast v1.10.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/thoas/go-funk v0.9.3 // indirect
github.com/tklauser/go-sysconf v0.3.15 // indirect
github.com/tklauser/numcpus v0.10.0 // indirect
@@ -205,10 +205,11 @@ require (
go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/net v0.43.0 // indirect
golang.org/x/net v0.47.0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/sync v0.16.0 // indirect
golang.org/x/sync v0.18.0 // indirect
golang.org/x/time v0.12.0 // indirect
golang.org/x/tools/godoc v0.1.0-deprecated // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect

View File

@@ -43,10 +43,10 @@ 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/framework/app-service v0.0.0-20251225061130-909b7656fd70 h1:U3z6m0hokD1gzl788BrUdxCbDyAjdOBBXA8ilYgn6VQ=
github.com/beclab/Olares/framework/app-service v0.0.0-20251225061130-909b7656fd70/go.mod h1:D9wl7y3obLqXMqfubMROMgdxWAwInnKNrFC//d0nyIA=
github.com/beclab/api v0.0.2 h1:aD5RcMie2uqa/FZI7aQBa1F4yVEib8/x3IIZSLiHkBM=
github.com/beclab/api v0.0.2/go.mod h1:ESZLe8cf4934QFkU6cqbskKfiTyNk67i1qbv/ctS6js=
github.com/beclab/app-service v0.4.41 h1:WSIXEqHSAepHweBooPkc+pedVaGGn335RugNwixkciY=
github.com/beclab/app-service v0.4.41/go.mod h1:0vEg3rv/DbR7dYznvTlXNXyYNn+TXNMaxz03GQYRWUQ=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
@@ -68,8 +68,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo=
github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
github.com/containerd/containerd v1.7.28 h1:Nsgm1AtcmEh4AHAJ4gGlNSaKgXiNccU270Dnf81FQ3c=
github.com/containerd/containerd v1.7.28/go.mod h1:azUkWcOvHrWvaiUjSQH0fjzuHIwSPg1WL5PshGP4Szs=
github.com/containerd/containerd v1.7.29 h1:90fWABQsaN9mJhGkoVnuzEY+o1XDPbg9BTC9QTAHnuE=
github.com/containerd/containerd v1.7.29/go.mod h1:azUkWcOvHrWvaiUjSQH0fjzuHIwSPg1WL5PshGP4Szs=
github.com/containerd/containerd/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVMyTRdsD2bS0=
github.com/containerd/containerd/api v1.8.0/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc=
github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII=
@@ -88,13 +88,17 @@ github.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRq
github.com/containerd/ttrpc v1.2.7/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=
github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40=
github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk=
github.com/containers/image/v5 v5.36.1 h1:6zpXBqR59UcAzoKpa/By5XekeqFV+htWYfr65+Cgjqo=
github.com/containers/image/v5 v5.36.1/go.mod h1:b4GMKH2z/5t6/09utbse2ZiLK/c72GuGLFdp7K69eA4=
github.com/containers/storage v1.59.1 h1:11Zu68MXsEQGBBd+GadPrHPpWeqjKS8hJDGiAHgIqDs=
github.com/containers/storage v1.59.1/go.mod h1:KoAYHnAjP3/cTsRS+mmWZGkufSY2GACiKQ4V3ZLQnR0=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
github.com/cyphar/filepath-securejoin v0.5.1 h1:eYgfMq5yryL4fbWfkLpFFy2ukSELzaJOTaUTuh+oF48=
github.com/cyphar/filepath-securejoin v0.5.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
@@ -105,16 +109,14 @@ github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U
github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/distribution/distribution/v3 v3.0.0 h1:q4R8wemdRQDClzoNNStftB2ZAfqOiN6UX90KJc4HjyM=
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/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8=
github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8=
@@ -179,6 +181,8 @@ github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpv
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/gobwas/glob v0.2.4-0.20181002190808-e7a84e9525fe h1:zn8tqiUbec4wR94o7Qj3LZCAT6uGobhEgnDRg6isG5U=
github.com/gobwas/glob v0.2.4-0.20181002190808-e7a84e9525fe/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
@@ -224,8 +228,6 @@ github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g=
github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k=
github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE=
github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
@@ -262,10 +264,10 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
@@ -312,8 +314,6 @@ github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa1
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
@@ -338,8 +338,6 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/modood/table v0.0.0-20220527013332-8d47e76dad33 h1:T5IbS9C1G2zeHb6eBy6OfIvj5tfQB23kGFpewCJuGDg=
github.com/modood/table v0.0.0-20220527013332-8d47e76dad33/go.mod h1:41qyXVI5QH9/ObyPj27CGCVau5v/njfc3Gjj7yzr0HQ=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
@@ -348,6 +346,8 @@ github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/n
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/nats-io/nats.go v1.45.0 h1:/wGPbnYXDM0pLKFjZTX+2JOw9TQPoIgTFrUaH97giwA=
@@ -368,14 +368,16 @@ github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A=
github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
github.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU8lpJfSlR0xww=
github.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/selinux v1.12.0 h1:6n5JV4Cf+4y0KNXW48TLj5DwfXpvWlxXplUkdTrmPb8=
github.com/opencontainers/selinux v1.12.0/go.mod h1:BTPX+bjVbWGXw7ZZWUbdENt8w0htPSrlgOOysQaU62U=
github.com/opencontainers/selinux v1.13.1 h1:A8nNeceYngH9Ow++M+VVEwJVpdFmrlxsN22F+ISDCJE=
github.com/opencontainers/selinux v1.13.1/go.mod h1:S10WXZ/osk2kWOYKy1x2f/eXF5ZHJoUs8UU/2caNRbg=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
@@ -416,6 +418,8 @@ github.com/rubenv/sql-migrate v1.8.0 h1:dXnYiJk9k3wetp7GfQbKJcPHjVJL6YK19tKj8t2N
github.com/rubenv/sql-migrate v1.8.0/go.mod h1:F2bGFBwCU+pnmbtNYDeKvSuvL6lBVtXDXUUv5t+u1qw=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7AwssoOcM/tq5JjjG2yYOc8odClEiXA=
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4=
@@ -434,17 +438,19 @@ github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c h1:aqg5Vm5dwtvL+Yg
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c/go.mod h1:owqhoLW1qZoYLZzLnBw+QkPP9WZnjlSWihhxAJC1+/M=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGByCY=
github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec=
github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY=
github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60=
github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE=
github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U=
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M=
github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
@@ -460,6 +466,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/thoas/go-funk v0.9.3 h1:7+nAEx3kn5ZJcnDm2Bh23N2yOtweO14bi//dvRtgLpw=
@@ -502,8 +510,8 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glB
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0 h1:cMyu9O88joYEaI47CnQkxO1XZdpoTF9fEnW2duIddhw=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0/go.mod h1:6Am3rn7P9TVVeXYG+wtcGE7IE1tsQ+bP3AuWcKt/gOI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk=
go.opentelemetry.io/otel/exporters/prometheus v0.54.0 h1:rFwzp68QMgtzu9PgP3jm9XaMICI6TsofWWPcBDKwlsU=
go.opentelemetry.io/otel/exporters/prometheus v0.54.0/go.mod h1:QyjcV9qDP6VeK5qPyKETvNjmaaEc7+gqjh4SS0ZYzDU=
go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.8.0 h1:CHXNXwfKWfzS65yrlB2PVds1IBZcdsX8Vepy9of0iRU=
@@ -542,8 +550,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
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=
@@ -552,8 +560,8 @@ golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPI
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
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 +572,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
@@ -574,8 +582,8 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
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=
@@ -587,14 +595,14 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
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.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -606,8 +614,10 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
golang.org/x/tools/godoc v0.1.0-deprecated h1:o+aZ1BOj6Hsx/GBdJO/s815sqftjSnrZZwyYTHODvtk=
golang.org/x/tools/godoc v0.1.0-deprecated/go.mod h1:qM63CriJ961IHWmnWa9CjZnBndniPt4a3CK0PVB9bIg=
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=

133
cli/pkg/amdgpu/tasks.go Normal file
View File

@@ -0,0 +1,133 @@
package amdgpu
import (
"fmt"
"os/exec"
"path"
"path/filepath"
"github.com/beclab/Olares/cli/pkg/common"
cc "github.com/beclab/Olares/cli/pkg/core/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"
"github.com/beclab/Olares/cli/pkg/utils"
"github.com/Masterminds/semver/v3"
"github.com/pkg/errors"
)
// InstallAmdRocmModule installs AMD ROCm stack on supported Ubuntu if AMD GPU is present.
type InstallAmdRocmModule struct {
common.KubeModule
}
func (m *InstallAmdRocmModule) Init() {
m.Name = "InstallAMDGPU"
installAmd := &task.RemoteTask{
Name: "InstallAmdRocm",
Hosts: m.Runtime.GetHostsByRole(common.Master),
Action: &InstallAmdRocm{
// no manifest needed
},
Parallel: false,
Retry: 1,
}
m.Tasks = []task.Interface{
installAmd,
}
}
// InstallAmdRocm installs ROCm using amdgpu-install on Ubuntu 22.04/24.04 for AMD GPUs.
type InstallAmdRocm struct {
common.KubeAction
}
func (t *InstallAmdRocm) Execute(runtime connector.Runtime) error {
si := runtime.GetSystemInfo()
if !si.IsLinux() || !si.IsUbuntu() || !(si.IsUbuntuVersionEqual(connector.Ubuntu2204) || si.IsUbuntuVersionEqual(connector.Ubuntu2404)) {
return nil
}
amdGPUExists, err := utils.HasAmdIGPU(runtime)
if err != nil {
return err
}
// skip rocm install
if !amdGPUExists {
return nil
}
rocmV, _ := utils.RocmVersion()
min := semver.MustParse("7.1.1")
if rocmV != nil && rocmV.LessThan(min) {
return fmt.Errorf("detected ROCm version %s, which is lower than required %s; please uninstall existing ROCm/AMDGPU components before installation with command: olares-cli amdgpu uninstall", rocmV.Original(), min.Original())
}
if rocmV != nil && rocmV.GreaterThan(min) {
logger.Warnf("Warning: detected ROCm version %s great than maximum tested version %s")
return nil
}
if rocmV != nil && rocmV.Equal(min) {
logger.Infof("detected ROCm version %s, skip rocm install...", min.Original())
return nil
}
// ensure python3-setuptools and python3-wheel
_, _ = runtime.GetRunner().SudoCmd("apt-get update", false, true)
checkPkgs := "dpkg -s python3-setuptools python3-wheel >/dev/null 2>&1 || DEBIAN_FRONTEND=noninteractive apt-get install -y python3-setuptools python3-wheel"
if _, err := runtime.GetRunner().SudoCmd(checkPkgs, false, true); err != nil {
return errors.Wrap(errors.WithStack(err), "failed to install python3-setuptools and python3-wheel")
}
// ensure amdgpu-install exists
if _, err := exec.LookPath("amdgpu-install"); err != nil {
var debURL string
if si.IsUbuntuVersionEqual(connector.Ubuntu2404) {
debURL = "https://repo.radeon.com/amdgpu-install/7.1.1/ubuntu/noble/amdgpu-install_7.1.1.70101-1_all.deb"
} else {
debURL = "https://repo.radeon.com/amdgpu-install/7.1.1/ubuntu/jammy/amdgpu-install_7.1.1.70101-1_all.deb"
}
tmpDeb := path.Join(runtime.GetBaseDir(), cc.PackageCacheDir, "gpu", "amdgpu-install_7.1.1.70101-1_all.deb")
if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("install -d -m 0755 %s", filepath.Dir(tmpDeb)), false, true); err != nil {
return err
}
cmd := fmt.Sprintf("sh -c 'wget -O %s %s'", tmpDeb, debURL)
if _, err := runtime.GetRunner().SudoCmd(cmd, false, true); err != nil {
return errors.Wrap(errors.WithStack(err), "failed to download amdgpu-install deb")
}
if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("DEBIAN_FRONTEND=noninteractive apt-get install -y %s", tmpDeb), false, true); err != nil {
return errors.Wrap(errors.WithStack(err), "failed to install amdgpu-install deb")
}
}
// run installer for rocm usecase
if _, err := runtime.GetRunner().SudoCmd("amdgpu-install -y --usecase=rocm", false, true); err != nil {
return errors.Wrap(errors.WithStack(err), "failed to install AMD ROCm via amdgpu-install")
}
fmt.Println()
logger.Warn("Warning: To enable ROCm, please reboot your machine after installation.")
return nil
}
type AmdgpuInstallAction struct {
common.KubeAction
}
func (t *AmdgpuInstallAction) Execute(runtime connector.Runtime) error {
if _, err := runtime.GetRunner().SudoCmd("amdgpu-install -y --usecase=rocm", false, true); err != nil {
return errors.Wrap(errors.WithStack(err), "failed to install AMD ROCm via amdgpu-install")
}
return nil
}
type AmdgpuUninstallAction struct {
common.KubeAction
}
func (t *AmdgpuUninstallAction) Execute(runtime connector.Runtime) error {
if _, err := runtime.GetRunner().SudoCmd("amdgpu-install --uninstall -y", false, true); err != nil {
return errors.Wrap(errors.WithStack(err), "failed to uninstall AMD ROCm via amdgpu-install")
}
fmt.Println()
logger.Warn("Warning: Please reboot your machine after uninstall to fully remove ROCm components.")
return nil
}

View File

@@ -1,46 +0,0 @@
/*
Copyright 2021 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package confirm
import (
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/core/task"
)
type InstallConfirmModule struct {
common.KubeModule
Skip bool
}
func (i *InstallConfirmModule) IsSkip() bool {
return i.Skip
}
func (i *InstallConfirmModule) Init() {
i.Name = "ConfirmModule"
i.Desc = "Display confirmation form"
display := &task.LocalTask{
Name: "ConfirmForm",
Desc: "Display confirmation form",
Action: new(InstallationConfirm),
}
i.Tasks = []task.Interface{
display,
}
}

View File

@@ -1,144 +0,0 @@
/*
Copyright 2021 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package confirm
import (
"bufio"
"fmt"
"os"
"strings"
"github.com/mitchellh/mapstructure"
"github.com/modood/table"
"github.com/pkg/errors"
versionutil "k8s.io/apimachinery/pkg/util/version"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/core/connector"
"github.com/beclab/Olares/cli/pkg/core/logger"
)
// PreCheckResults defines the items to be checked.
type PreCheckResults struct {
Name string `table:"name"`
Sudo string `table:"sudo"`
Curl string `table:"curl"`
Openssl string `table:"openssl"`
Ebtables string `table:"ebtables"`
Socat string `table:"socat"`
Ipset string `table:"ipset"`
Ipvsadm string `table:"ipvsadm"`
Conntrack string `table:"conntrack"`
Chronyd string `table:"chrony"`
Docker string `table:"docker"`
Containerd string `table:"containerd"`
Nfs string `table:"nfs client"`
Ceph string `table:"ceph client"`
Glusterfs string `table:"glusterfs client"`
Time string `table:"time"`
}
type InstallationConfirm struct {
common.KubeAction
}
func (i *InstallationConfirm) Execute(runtime connector.Runtime) error {
var (
results []PreCheckResults
stopFlag bool
)
pre := make([]map[string]string, 0, len(runtime.GetAllHosts()))
for _, host := range runtime.GetAllHosts() {
if v, ok := host.GetCache().Get(common.NodePreCheck); ok {
pre = append(pre, v.(map[string]string))
} else {
return errors.New("get node check result failed by host cache")
}
}
for node := range pre {
var result PreCheckResults
_ = mapstructure.Decode(pre[node], &result)
results = append(results, result)
}
table.OutputA(results)
reader := bufio.NewReader(os.Stdin)
if i.KubeConf.Arg.Artifact == "" {
for _, host := range results {
if host.Sudo == "" {
logger.Errorf("%s: sudo is required.", host.Name)
stopFlag = true
}
if host.Conntrack == "" {
logger.Errorf("%s: conntrack is required.", host.Name)
stopFlag = true
}
if host.Socat == "" {
logger.Errorf("%s: socat is required.", host.Name)
stopFlag = true
}
}
}
fmt.Println("")
fmt.Println("This is a simple check of your environment.")
fmt.Println("Before installation, ensure that your machines meet all requirements specified at")
fmt.Println("https://github.com/kubesphere/kubekey#requirements-and-recommendations")
fmt.Println("")
if k8sVersion, err := versionutil.ParseGeneric(i.KubeConf.Cluster.Kubernetes.Version); err == nil {
if k8sVersion.AtLeast(versionutil.MustParseSemantic("v1.24.0")) && i.KubeConf.Cluster.Kubernetes.ContainerManager == common.Docker {
fmt.Println("[Notice]")
fmt.Println("Incorrect runtime. Please specify a container runtime other than Docker to install Kubernetes v1.24 or later.")
fmt.Println("You can set \"spec.kubernetes.containerManager\" in the configuration file to \"containerd\" or add \"--container-manager containerd\" to the \"./kk create cluster\" command.")
fmt.Println("For more information, see:")
fmt.Println("https://github.com/kubesphere/kubekey/blob/master/docs/commands/kk-create-cluster.md")
fmt.Println("https://kubernetes.io/docs/setup/production-environment/container-runtimes/#container-runtimes")
fmt.Println("https://kubernetes.io/blog/2022/02/17/dockershim-faq/")
fmt.Println("")
stopFlag = true
}
}
if stopFlag {
os.Exit(1)
}
confirmOK := true // TODO: force skip
for !confirmOK {
fmt.Printf("Continue this installation? [yes/no]: ")
input, err := reader.ReadString('\n')
if err != nil {
logger.Fatal(err)
}
input = strings.TrimSpace(strings.ToLower(input))
switch strings.ToLower(input) {
case "yes", "y":
confirmOK = true
case "no", "n":
os.Exit(0)
default:
continue
}
}
return nil
}

View File

@@ -81,6 +81,7 @@ func (m *RunPrechecksModule) Init() {
new(NvidiaCardArchChecker),
new(NouveauChecker),
new(CudaChecker),
new(RocmChecker),
}
runPreChecks := &task.LocalTask{
Name: "RunPrechecks",

View File

@@ -372,6 +372,48 @@ func (c *CudaChecker) Check(runtime connector.Runtime) error {
return nil
}
// RocmChecker checks AMD ROCm version for AMD GPU on Ubuntu 22.04/24.04 only.
type RocmChecker struct{}
func (r *RocmChecker) Name() string {
return "ROCm"
}
func (r *RocmChecker) Check(runtime connector.Runtime) error {
if !runtime.GetSystemInfo().IsLinux() {
return nil
}
si := runtime.GetSystemInfo()
if !si.IsUbuntu() || !(si.IsUbuntuVersionEqual(connector.Ubuntu2204) || si.IsUbuntuVersionEqual(connector.Ubuntu2404)) {
return nil
}
// detect AMD GPU presence
amdGPUExists, err := utils.HasAmdIGPU(runtime)
if err != nil {
return err
}
// no AMD GPU found, no need to check rocm
if !amdGPUExists {
return nil
}
curV, err := utils.RocmVersion()
if err != nil && !os.IsNotExist(err) {
return err
}
if os.IsNotExist(err) {
return nil
}
min := semver.MustParse("7.1.1")
if curV.LessThan(min) {
return fmt.Errorf("detected ROCm version %s, which is lower than required %s; please uninstall existing ROCm/AMDGPU components before installation with command: olares-cli amdgpu uninstall", curV.Original(), min.Original())
}
return nil
}
//////////////////////////////////////////////
// precheck - task
@@ -489,7 +531,7 @@ func (t *GetStorageKeyTask) Execute(runtime connector.Runtime) error {
defer cancel()
if stdout, err := runtime.GetRunner().CmdContext(ctx, fmt.Sprintf("%s get terminus terminus -o jsonpath='{.metadata.annotations.bytetrade\\.io/s3-ak}'", kubectl), false, false); err != nil {
storageAccessKey = os.Getenv(common.ENV_AWS_ACCESS_KEY_ID_SETUP)
storageAccessKey = t.KubeConf.Arg.Storage.StorageAccessKey
if storageAccessKey == "" {
logger.Errorf("storage access key not found")
}
@@ -498,7 +540,7 @@ func (t *GetStorageKeyTask) Execute(runtime connector.Runtime) error {
}
if stdout, err := runtime.GetRunner().CmdContext(ctx, fmt.Sprintf("%s get terminus terminus -o jsonpath='{.metadata.annotations.bytetrade\\.io/s3-sk}'", kubectl), false, false); err != nil {
storageSecretKey = os.Getenv(common.ENV_AWS_SECRET_ACCESS_KEY_SETUP)
storageSecretKey = t.KubeConf.Arg.Storage.StorageSecretKey
if storageSecretKey == "" {
logger.Errorf("storage secret key not found")
}
@@ -507,7 +549,7 @@ func (t *GetStorageKeyTask) Execute(runtime connector.Runtime) error {
}
if stdout, err := runtime.GetRunner().CmdContext(ctx, fmt.Sprintf("%s get terminus terminus -o jsonpath='{.metadata.annotations.bytetrade\\.io/s3-sts}'", kubectl), false, false); err != nil {
storageToken = os.Getenv(common.ENV_AWS_SESSION_TOKEN_SETUP)
storageToken = t.KubeConf.Arg.Storage.StorageToken
if storageToken == "" {
logger.Errorf("storage token not found")
}
@@ -516,7 +558,7 @@ func (t *GetStorageKeyTask) Execute(runtime connector.Runtime) error {
}
if stdout, err := runtime.GetRunner().CmdContext(ctx, fmt.Sprintf("%s get terminus terminus -o jsonpath='{.metadata.labels.bytetrade\\.io/cluster-id}'", kubectl), false, false); err != nil {
storageClusterId = os.Getenv(common.ENV_CLUSTER_ID)
storageClusterId = t.KubeConf.Arg.Storage.StorageClusterId
if storageClusterId == "" {
logger.Errorf("storage cluster id not found")
}

View File

@@ -23,31 +23,19 @@ import (
const (
DefaultK8sVersion = "v1.33.3"
DefaultK3sVersion = "v1.33.3-k3s"
DefaultKubernetesVersion = ""
DefaultKubeSphereVersion = "v3.3.0"
CurrentVerifiedCudaVersion = "13.1"
)
const (
K3s = "k3s"
K8e = "k8e"
Kubernetes = "kubernetes"
K3s = "k3s"
LocalHost = "localhost"
AllInOne = "allInOne"
File = "file"
Operator = "operator"
CommandLine = "commandLine"
Master = "master"
Worker = "worker"
ETCD = "etcd"
K8s = "k8s"
Registry = "registry"
KubeKey = "kubekey"
Harbor = "harbor"
DockerCompose = "compose"
Master = "master"
Worker = "worker"
ETCD = "etcd"
K8s = "k8s"
Registry = "registry"
KubeBinaries = "KubeBinaries"
WslBinaries = "WslBinaries"
@@ -58,23 +46,14 @@ const (
BinDir = "/usr/local/bin"
KubeConfigDir = "/etc/kubernetes"
KubeAddonsDir = "/etc/kubernetes/addons"
KubeEtcdCertDir = "/etc/kubernetes/etcd"
KubeCertDir = "/etc/kubernetes/pki"
KubeManifestDir = "/etc/kubernetes/manifests"
KubeScriptDir = "/usr/local/bin/kube-scripts"
KubeletFlexvolumesPluginsDir = "/usr/libexec/kubernetes/kubelet-plugins/volume/exec"
K3sImageDir = "/var/lib/images"
MinikubeDefaultProfile = "olares-0"
MinikubeEtcdCertDir = "/var/lib/minikube/certs/etcd"
WSLDefaultDistribution = "Ubuntu"
RunLockDir = "/var/run/lock"
InstallerScriptsDir = "scripts"
ETCDCertDir = "/etc/ssl/etcd/ssl"
RegistryCertDir = "/etc/ssl/registry/ssl"
HaproxyDir = "/etc/kubekey/haproxy"
ETCDCertDir = "/etc/ssl/etcd/ssl"
IPv4Regexp = "[\\d]+\\.[\\d]+\\.[\\d]+\\.[\\d]+"
IPv6Regexp = "[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){0,7}::[a-f0-9]{0,4}(:[a-f0-9]{1,4}){0,7}"
@@ -85,7 +64,6 @@ const (
Kubeovn = "kubeovn"
Docker = "docker"
Crictl = "crictl"
Containerd = "containerd"
Crio = "crio"
Isula = "isula"
@@ -94,14 +72,8 @@ const (
// global cache key
// PreCheckModule
NodePreCheck = "nodePreCheck"
K8sVersion = "k8sVersion" // current k8s version
MaxK8sVersion = "maxK8sVersion" // max k8s version of nodes
KubeSphereVersion = "kubeSphereVersion" // current KubeSphere version
ClusterNodeStatus = "clusterNodeStatus"
ClusterNodeCRIRuntimes = "ClusterNodeCRIRuntimes"
DesiredK8sVersion = "desiredK8sVersion"
PlanK8sVersion = "planK8sVersion"
NodeK8sVersion = "NodeK8sVersion"
// ETCDModule
ETCDCluster = "etcdCluster"
@@ -113,15 +85,6 @@ const (
ClusterExist = "clusterExist"
MasterInfo = "masterInfo"
// CertsModule
Certificate = "certificate"
CaCertificate = "caCertificate"
// Artifact pipeline
Artifact = "artifact"
SkipMasterNodePullImages = "skipMasterNodePullImages"
)
const (
@@ -147,16 +110,6 @@ const (
Fedora = "fedora"
RHEl = "rhel"
Raspbian = "raspbian"
PVE = "pve"
WSL = "wsl"
)
const (
TRUE = "true"
FALSE = "false"
YES = "yes"
NO = "no"
)
const (
@@ -271,32 +224,84 @@ const (
ENV_OLARES_VERSION = "OLARES_VERSION"
ENV_TERMINUS_IS_CLOUD_VERSION = "TERMINUS_IS_CLOUD_VERSION"
ENV_KUBE_TYPE = "KUBE_TYPE"
ENV_REGISTRY_MIRRORS = "REGISTRY_MIRRORS"
ENV_OLARES_CDN_SERVICE = "OLARES_SYSTEM_CDN_SERVICE"
ENV_STORAGE = "STORAGE"
ENV_S3_BUCKET = "S3_BUCKET"
ENV_LOCAL_GPU_ENABLE = "LOCAL_GPU_ENABLE"
ENV_AWS_ACCESS_KEY_ID_SETUP = "AWS_ACCESS_KEY_ID_SETUP"
ENV_AWS_SECRET_ACCESS_KEY_SETUP = "AWS_SECRET_ACCESS_KEY_SETUP"
ENV_AWS_SESSION_TOKEN_SETUP = "AWS_SESSION_TOKEN_SETUP"
ENV_BACKUP_KEY_PREFIX = "BACKUP_KEY_PREFIX"
ENV_BACKUP_SECRET = "BACKUP_SECRET"
ENV_CLUSTER_ID = "CLUSTER_ID"
ENV_BACKUP_CLUSTER_BUCKET = "BACKUP_CLUSTER_BUCKET"
ENV_HOST_IP = "HOST_IP"
ENV_PREINSTALL = "PREINSTALL"
ENV_DISABLE_HOST_IP_PROMPT = "DISABLE_HOST_IP_PROMPT"
ENV_AUTO_ADD_FIREWALL_RULES = "AUTO_ADD_FIREWALL_RULES"
ENV_TERMINUS_OS_DOMAINNAME = "TERMINUS_OS_DOMAINNAME"
ENV_DEFAULT_WSL_DISTRO_LOCATION = "DEFAULT_WSL_DISTRO_LOCATION" // If set to 1, the default WSL distro storage will be used.
ENV_CONTAINER = "container"
ENV_CONTAINER_MODE = "CONTAINER_MODE" // running in docker container
OLARES_SYSTEM_ENV_FILENAME = "system-env.yaml"
OLARES_USER_ENV_FILENAME = "user-env.yaml"
)
const (
FlagVersion = "version"
FlagBaseDir = "base-dir"
FlagWSLDistribution = "wsl-distribution"
FlagLegacyWSLDistribution = "distribution"
FlagMasterHost = "master-host"
FlagMasterNodeName = "master-node-name"
FlagMasterSSHUser = "master-ssh-user"
FlagMasterSSHPassword = "master-ssh-password"
FlagMasterSSHPrivateKeyPath = "master-ssh-private-key-path"
FlagMasterSSHPort = "master-ssh-port"
FlagOSUserName = "os-username"
EnvLegacyOSUserName = "TERMINUS_OS_USERNAME"
FlagOSDomainName = "os-domainname"
EnvLegacyOSDomainName = "TERMINUS_OS_DOMAINNAME"
FlagOSPassword = "os-password"
EnvLegacyEncryptedOSPassword = "TERMINUS_OS_PASSWORD"
FlagCDNService = "cdn-service"
FlagExtract = "extract"
FlagIgnoreMissingImages = "ignore-missing-images"
FlagManifest = "manifest"
FlagURLOverride = "url-override"
FlagReleaseID = "release-id"
FlagKubeType = "kube-type"
FlagLegacyKubeType = "kube"
FlagEnableJuiceFS = "enable-juicefs"
FlagLegacyEnableJuiceFS = "with-juicefs"
EnvLegacyEnableJuiceFS = "JUICEFS"
FlagMiniKubeProfile = "minikube-profile"
FlagLegacyMiniKubeProfile = "profile"
FlagEnableReverseProxy = "enable-reverse-proxy"
FlagEnablePodSwap = "enable-pod-swap"
FlagSwappiness = "swappiness"
FlagEnableZRAM = "enable-zram"
FlagZRAMSize = "zram-size"
FlagZRAMSwapPriority = "zram-swap-priority"
FlagRegistryMirrors = "registry-mirrors"
FlagStorageType = "storage-type"
FlagLegacyStorageType = "storage"
FlagS3Bucket = "s3-bucket"
FlagBackupKeyPrefix = "backup-key-prefix"
FlagAWSAccessKeyIDSetup = "aws-access-key-id-setup"
FlagAWSSecretAccessKeySetup = "aws-secret-access-key-setup"
FlagAWSSessionTokenSetup = "aws-session-token-setup"
FlagClusterID = "cluster-id"
FlagBackupSecret = "backup-secret"
FlagBackupClusterBucket = "backup-cluster-bucket"
FlagIsCloudVersion = "is-cloud-version"
FlagUninstallPhase = "uninstall-phase"
FlagUninstallAll = "uninstall-all"
)
func SetSystemEnv(key, value string) {
os.Setenv(key, value)
}

View File

@@ -29,10 +29,8 @@ type KubeAction struct {
func (k *KubeAction) AutoAssert(runtime connector.Runtime) {
kubeRuntime := runtime.(*KubeRuntime)
conf := &KubeConf{
Cluster: kubeRuntime.Cluster,
ClusterName: kubeRuntime.ClusterName,
Kubeconfig: kubeRuntime.Kubeconfig,
Arg: kubeRuntime.Arg,
Cluster: kubeRuntime.Cluster,
Arg: kubeRuntime.Arg,
}
k.KubeConf = conf

View File

@@ -22,11 +22,8 @@ import (
)
type KubeConf struct {
ClusterHosts []string
ClusterName string
Cluster *kubekeyapiv1alpha2.ClusterSpec
Kubeconfig string
Arg *Argument
Cluster *kubekeyapiv1alpha2.ClusterSpec
Arg *Argument
}
type KubeModule struct {
@@ -41,27 +38,8 @@ func (k *KubeModule) IsSkip() bool {
func (k *KubeModule) AutoAssert() {
kubeRuntime := k.Runtime.(*KubeRuntime)
conf := &KubeConf{
ClusterName: kubeRuntime.ClusterName,
Cluster: kubeRuntime.Cluster,
Kubeconfig: kubeRuntime.Kubeconfig,
Arg: kubeRuntime.Arg,
}
k.KubeConf = conf
}
type KubeCustomModule struct {
module.CustomModule
KubeConf *KubeConf
}
func (k *KubeCustomModule) AutoAssert() {
kubeRuntime := k.Runtime.(*KubeRuntime)
conf := &KubeConf{
ClusterName: kubeRuntime.ClusterName,
Cluster: kubeRuntime.Cluster,
Kubeconfig: kubeRuntime.Kubeconfig,
Arg: kubeRuntime.Arg,
Cluster: kubeRuntime.Cluster,
Arg: kubeRuntime.Arg,
}
k.KubeConf = conf

View File

@@ -29,9 +29,8 @@ type KubePrepare struct {
func (k *KubePrepare) AutoAssert(runtime connector.Runtime) {
kubeRuntime := runtime.(*KubeRuntime)
conf := &KubeConf{
Cluster: kubeRuntime.Cluster,
Kubeconfig: kubeRuntime.Kubeconfig,
Arg: kubeRuntime.Arg,
Cluster: kubeRuntime.Cluster,
Arg: kubeRuntime.Arg,
}
k.KubeConf = conf

View File

@@ -29,10 +29,8 @@ type KubeRollback struct {
func (k *KubeRollback) AutoAssert(runtime connector.Runtime) {
kubeRuntime := runtime.(*KubeRuntime)
conf := &KubeConf{
Cluster: kubeRuntime.Cluster,
ClusterName: kubeRuntime.ClusterName,
Kubeconfig: kubeRuntime.Kubeconfig,
Arg: kubeRuntime.Arg,
Cluster: kubeRuntime.Cluster,
Arg: kubeRuntime.Arg,
}
k.KubeConf = conf

View File

@@ -28,7 +28,7 @@ import (
"github.com/joho/godotenv"
"github.com/pkg/errors"
"github.com/spf13/pflag"
"github.com/spf13/viper"
kubekeyapiv1alpha2 "github.com/beclab/Olares/cli/apis/kubekey/v1alpha2"
"github.com/beclab/Olares/cli/pkg/core/common"
@@ -40,43 +40,19 @@ import (
type KubeRuntime struct {
connector.BaseRuntime
ClusterName string
Cluster *kubekeyapiv1alpha2.ClusterSpec
Kubeconfig string
Arg *Argument
Cluster *kubekeyapiv1alpha2.ClusterSpec
Arg *Argument
}
type Argument struct {
NodeName string `json:"node_name"`
FilePath string `json:"file_path"`
KubernetesVersion string `json:"kubernetes_version"`
KsEnable bool `json:"ks_enable"`
KsVersion string `json:"ks_version"`
OlaresVersion string `json:"olares_version"`
Debug bool `json:"debug"`
IgnoreErr bool `json:"ignore_err"`
SkipPullImages bool `json:"skip_pull_images"`
SKipPushImages bool `json:"skip_push_images"`
SecurityEnhancement bool `json:"security_enhancement"`
DeployLocalStorage *bool `json:"deploy_local_storage"`
// DownloadCommand func(path, url string) string
SkipConfirmCheck bool `json:"skip_confirm_check"`
InCluster bool `json:"in_cluster"`
ContainerManager string `json:"container_manager"`
FromCluster bool `json:"from_cluster"`
KubeConfig string `json:"kube_config"`
Artifact string `json:"artifact"`
InstallPackages bool `json:"install_packages"`
ImagesDir string `json:"images_dir"`
Namespace string `json:"namespace"`
DeleteCRI bool `json:"delete_cri"`
Role string `json:"role"`
Type string `json:"type"`
Kubetype string `json:"kube_type"`
SystemInfo connector.Systems
InCluster bool `json:"in_cluster"`
ContainerManager string `json:"container_manager"`
Kubetype string `json:"kube_type"`
SystemInfo connector.Systems
// Extra args
ExtraAddon string `json:"extra_addon"` // addon yaml config
RegistryMirrors string `json:"registry_mirrors"`
OlaresCDNService string `json:"olares_cdn_service"`
@@ -86,10 +62,6 @@ type Argument struct {
// master node ssh config
*MasterHostConfig
LocalSSHPort int `json:"-"`
SkipMasterPullImages bool `json:"skip_master_pull_images"`
// User
User *User `json:"user"`
// if juicefs is opted off, the local storage is used directly
@@ -102,8 +74,6 @@ type Argument struct {
NetworkSettings *NetworkSettings `json:"network_settings"`
GPU *GPU `json:"gpu"`
Request any `json:"-"`
IsCloudInstance bool `json:"is_cloud_instance"`
MinikubeProfile string `json:"minikube_profile"`
WSLDistribution string `json:"wsl_distribution"`
@@ -114,8 +84,6 @@ type Argument struct {
ConsoleLogTruncate bool `json:"console_log_truncate"`
HostIP string `json:"host_ip"`
CudaVersion string `json:"cuda_version"`
IsOlaresInContainer bool `json:"is_olares_in_container"`
}
@@ -127,14 +95,6 @@ type SwapConfig struct {
ZRAMSwapPriority int `json:"zram_swap_priority"`
}
func (cfg *SwapConfig) AddFlags(fs *pflag.FlagSet) {
fs.BoolVar(&cfg.EnablePodSwap, "enable-pod-swap", false, "Enable pods on Kubernetes cluster to use swap, setting --enable-zram, --zram-size or --zram-swap-priority implicitly enables this option, regardless of the command line args, note that only pods of the BestEffort QOS group can use swap due to K8s design")
fs.IntVar(&cfg.Swappiness, "swappiness", 0, "Configure the Linux swappiness value, if not set, the current configuration is remained")
fs.BoolVar(&cfg.EnableZRAM, "enable-zram", false, "Set up a ZRAM device to be used for swap, setting --zram-size or --zram-swap-priority implicitly enables this option, regardless of the command line args")
fs.StringVar(&cfg.ZRAMSize, "zram-size", "", "Set the size of the ZRAM device, takes a format of https://kubernetes.io/docs/reference/kubernetes-api/common-definitions/quantity, defaults to half of the total RAM")
fs.IntVar(&cfg.ZRAMSwapPriority, "zram-swap-priority", 0, "Set the swap priority of the ZRAM device, between -1 and 32767, defaults to 100")
}
func (cfg *SwapConfig) Validate() error {
if cfg.ZRAMSize == "" {
return nil
@@ -164,21 +124,12 @@ type MasterHostConfig struct {
MasterSSHPort int `json:"master_ssh_port"`
}
func (cfg *MasterHostConfig) AddFlags(fs *pflag.FlagSet) {
fs.StringVar(&cfg.MasterHost, "master-host", "", "IP address of the master node")
fs.StringVar(&cfg.MasterNodeName, "master-node-name", "", "Name of the master node")
fs.StringVar(&cfg.MasterSSHUser, "master-ssh-user", "", "Username of the master node, defaults to root")
fs.StringVar(&cfg.MasterSSHPassword, "master-ssh-password", "", "Password of the master node")
fs.StringVar(&cfg.MasterSSHPrivateKeyPath, "master-ssh-private-key-path", "", "Path to the SSH key to access the master node, defaults to ~/.ssh/id_rsa")
fs.IntVar(&cfg.MasterSSHPort, "master-ssh-port", 0, "SSH Port of the master node, defaults to 22")
}
func (cfg *MasterHostConfig) Validate() error {
if cfg.MasterHost == "" {
return errors.New("--master-host is not provided")
return errors.New("master host is not provided")
}
if cfg.MasterSSHUser != "" && cfg.MasterSSHUser != "root" && cfg.MasterSSHPassword == "" {
return errors.New("--master-ssh-password must be provided for non-root user in order to execute sudo command")
return errors.New("master ssh password must be provided for non-root user in order to execute sudo command")
}
return nil
}
@@ -222,9 +173,9 @@ type Storage struct {
StorageAccessKey string `json:"storage_access_key"`
StorageSecretKey string `json:"storage_secret_key"`
StorageToken string `json:"storage_token"` // juicefs --> from env
StorageClusterId string `json:"storage_cluster_id"` // use only on the Terminus cloud, juicefs --> from env
StorageSyncSecret string `json:"storage_sync_secret"` // use only on the Terminus cloud --> from env
StorageToken string `json:"storage_token"` // juicefs
StorageClusterId string `json:"storage_cluster_id"` // use only on the Terminus cloud, juicefs
StorageSyncSecret string `json:"storage_sync_secret"` // use only on the Terminus cloud
BackupClusterBucket string `json:"backup_cluster_bucket"`
}
@@ -235,59 +186,39 @@ type GPU struct {
func NewArgument() *Argument {
si := connector.GetSystemInfo()
arg := &Argument{
KsEnable: true,
KsVersion: DefaultKubeSphereVersion,
InstallPackages: false,
SKipPushImages: false,
ContainerManager: Containerd,
SystemInfo: si,
Storage: &Storage{
StorageType: ManagedMinIO,
},
GPU: &GPU{
Enable: !strings.EqualFold(os.Getenv(ENV_LOCAL_GPU_ENABLE), "0"), // default enable GPU, not set or 1 means enable
GPU: &GPU{},
User: &User{
UserName: strings.TrimSpace(viper.GetString(FlagOSUserName)),
DomainName: strings.TrimSpace(viper.GetString(FlagOSDomainName)),
Password: strings.TrimSpace(viper.GetString(FlagOSPassword)),
},
User: &User{},
NetworkSettings: &NetworkSettings{},
RegistryMirrors: os.Getenv(ENV_REGISTRY_MIRRORS),
OlaresCDNService: os.Getenv(ENV_OLARES_CDN_SERVICE),
HostIP: os.Getenv(ENV_HOST_IP),
RegistryMirrors: viper.GetString(FlagRegistryMirrors),
OlaresCDNService: viper.GetString(FlagCDNService),
HostIP: viper.GetString(ENV_HOST_IP),
Environment: os.Environ(),
MasterHostConfig: &MasterHostConfig{},
SwapConfig: &SwapConfig{},
}
// default enable GPU unless explicitly set to "0"
arg.GPU.Enable = !strings.EqualFold(os.Getenv(ENV_LOCAL_GPU_ENABLE), "0")
arg.IsCloudInstance, _ = strconv.ParseBool(os.Getenv(ENV_TERMINUS_IS_CLOUD_VERSION))
arg.IsOlaresInContainer = os.Getenv("CONTAINER_MODE") == "oic"
arg.IsOlaresInContainer = os.Getenv(ENV_CONTAINER_MODE) == "oic"
si.IsOIC = arg.IsOlaresInContainer
if err := arg.LoadReleaseInfo(); err != nil {
fmt.Printf("error loading release info: %v", err)
os.Exit(1)
}
// Ensure BaseDir is initialized before loading master.conf
// so master host config can be loaded from ${base-dir}/master.conf reliably.
arg.SetBaseDir(viper.GetString(FlagBaseDir))
arg.loadMasterHostConfig()
return arg
}
// LoadReleaseInfo loads base directory and version settings
// from /etc/olares/release and environment variables,
// with the latter takes precedence.
// Note that the command line options --base-dir and --version
// still have the highest priority and will override any values loaded here
func (a *Argument) LoadReleaseInfo() error {
// load envs from the release file
// already existing envs are not overridden so
err := godotenv.Load(OlaresReleaseFile)
// silently ignore the non-existence of a release file
// otherwise, return the error
if err != nil && !os.IsNotExist(err) {
return err
}
a.BaseDir = os.Getenv(ENV_OLARES_BASE_DIR)
a.OlaresVersion = os.Getenv(ENV_OLARES_VERSION)
return nil
}
func (a *Argument) SaveReleaseInfo() error {
func (a *Argument) SaveReleaseInfo(withoutName bool) error {
if a.BaseDir == "" {
return errors.New("invalid: empty base directory")
}
@@ -300,15 +231,17 @@ func (a *Argument) SaveReleaseInfo() error {
ENV_OLARES_VERSION: a.OlaresVersion,
}
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) {
// if the user is not set, try to load the user name from the release file
envs, err := godotenv.Read(OlaresReleaseFile)
if err == nil {
if userName, ok := envs["OLARES_NAME"]; ok {
releaseInfoMap["OLARES_NAME"] = userName
if !withoutName {
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) {
// if the user is not set, try to load the user name from the release file
envs, err := godotenv.Read(OlaresReleaseFile)
if err == nil {
if userName, ok := envs["OLARES_NAME"]; ok {
releaseInfoMap["OLARES_NAME"] = userName
}
}
}
}
@@ -370,14 +303,6 @@ func (a *Argument) SetOlaresVersion(version string) {
a.OlaresVersion = version
}
func (a *Argument) SetRegistryMirrors(registryMirrors string) {
a.RegistryMirrors = registryMirrors
}
func (a *Argument) SetDeleteCRI(deleteCRI bool) {
a.DeleteCRI = deleteCRI
}
func (a *Argument) SetStorage(storage *Storage) {
a.Storage = storage
}
@@ -409,11 +334,6 @@ func (a *Argument) SetKubeVersion(kubeType string) {
a.Kubetype = kubeType
}
func (a *Argument) SetKubernetesVersion(kubeType string, kubeVersion string) {
a.KubernetesVersion = kubeVersion
a.Kubetype = kubeType
}
func (a *Argument) SetBaseDir(dir string) {
if dir != "" {
a.BaseDir = dir
@@ -432,10 +352,36 @@ func (a *Argument) SetBaseDir(dir string) {
}
}
func (a *Argument) SetCudaVersion(cudaVersion string) {
a.CudaVersion = CurrentVerifiedCudaVersion
if cudaVersion != "" {
a.CudaVersion = cudaVersion
// loadMasterHostConfig loads master host configuration from master.conf file (if exists)
// and then overrides with any values set via command line flags or environment variables.
func (a *Argument) loadMasterHostConfig() {
// First, try to load from master.conf file
configPath := filepath.Join(a.BaseDir, MasterHostConfigFile)
if content, err := os.ReadFile(configPath); err == nil {
json.Unmarshal(content, a.MasterHostConfig)
}
// Then override with viper values (from flags or env)
if v := viper.GetString(FlagMasterHost); v != "" {
a.MasterHost = v
}
if v := viper.GetString(FlagMasterNodeName); v != "" {
a.MasterNodeName = v
}
if v := viper.GetString(FlagMasterSSHUser); v != "" {
a.MasterSSHUser = v
}
if v := viper.GetString(FlagMasterSSHPassword); v != "" {
a.MasterSSHPassword = v
}
if v := viper.GetString(FlagMasterSSHPrivateKeyPath); v != "" {
a.MasterSSHPrivateKeyPath = v
}
if v := viper.GetInt(FlagMasterSSHPort); v != 0 {
a.MasterSSHPort = v
}
// Set a dummy name to bypass validity checks if master host is set but node name is not
if a.MasterHost != "" && a.MasterNodeName == "" {
a.MasterNodeName = "master"
}
}
@@ -465,60 +411,15 @@ func (a *Argument) SetSwapConfig(config SwapConfig) {
a.Swappiness = config.Swappiness
}
func (a *Argument) SetMasterHostOverride(config MasterHostConfig) {
if config.MasterHost != "" {
a.MasterHost = config.MasterHost
}
if config.MasterNodeName != "" {
a.MasterNodeName = config.MasterNodeName
}
// set a dummy name to bypass validity checks
// as it will be overridden later when the node name is fetched
if a.MasterNodeName == "" {
a.MasterNodeName = "master"
}
if config.MasterSSHPassword != "" {
a.MasterSSHPassword = config.MasterSSHPassword
}
if config.MasterSSHUser != "" {
a.MasterSSHUser = config.MasterSSHUser
}
if config.MasterSSHPort != 0 {
a.MasterSSHPort = config.MasterSSHPort
}
if config.MasterSSHPrivateKeyPath != "" {
a.MasterSSHPrivateKeyPath = config.MasterSSHPrivateKeyPath
}
}
func (a *Argument) LoadMasterHostConfigIfAny() error {
if a.BaseDir == "" {
return errors.New("basedir unset")
}
content, err := os.ReadFile(filepath.Join(a.BaseDir, MasterHostConfigFile))
if os.IsNotExist(err) {
return nil
}
if err != nil {
return err
}
return json.Unmarshal(content, a.MasterHostConfig)
}
func NewKubeRuntime(flag string, arg Argument) (*KubeRuntime, error) {
loader := NewLoader(flag, arg)
func NewKubeRuntime(arg Argument) (*KubeRuntime, error) {
loader := NewLoader(arg)
cluster, err := loader.Load()
if err != nil {
return nil, err
}
if err = loadExtraAddons(cluster, arg.ExtraAddon); err != nil {
return nil, err
}
base := connector.NewBaseRuntime(cluster.Name, connector.NewDialer(),
arg.Debug, arg.IgnoreErr, arg.BaseDir, arg.OlaresVersion, arg.ConsoleLogFileName, arg.ConsoleLogTruncate, arg.SystemInfo)
arg.BaseDir, arg.OlaresVersion, arg.ConsoleLogFileName, arg.ConsoleLogTruncate, arg.SystemInfo)
clusterSpec := &cluster.Spec
defaultCluster, roleGroups := clusterSpec.SetDefaultClusterSpec(arg.InCluster, arg.SystemInfo.IsDarwin())
@@ -528,9 +429,6 @@ func NewKubeRuntime(flag string, arg Argument) (*KubeRuntime, error) {
if host.IsRole(Master) || host.IsRole(Worker) {
host.SetRole(K8s)
}
if host.IsRole(Master) && arg.SkipMasterPullImages {
host.GetCache().Set(SkipMasterNodePullImages, true)
}
if _, ok := hostSet[host.GetName()]; !ok {
hostSet[host.GetName()] = struct{}{}
base.AppendHost(host)
@@ -544,12 +442,9 @@ func NewKubeRuntime(flag string, arg Argument) (*KubeRuntime, error) {
args, _ := json.Marshal(arg)
logger.Debugf("[runtime] arg: %s", string(args))
arg.KsEnable = defaultCluster.KubeSphere.Enabled
arg.KsVersion = defaultCluster.KubeSphere.Version
r := &KubeRuntime{
Cluster: defaultCluster,
ClusterName: cluster.Name,
Arg: &arg,
Cluster: defaultCluster,
Arg: &arg,
}
r.BaseRuntime = base

View File

@@ -17,15 +17,9 @@
package common
import (
"bufio"
"encoding/json"
"fmt"
"io/ioutil"
"net/url"
"os"
"os/exec"
"os/user"
"path/filepath"
"regexp"
"strings"
"time"
@@ -33,10 +27,7 @@ import (
"github.com/beclab/Olares/cli/pkg/core/util"
kubekeyapiv1alpha2 "github.com/beclab/Olares/cli/apis/kubekey/v1alpha2"
"github.com/beclab/Olares/cli/pkg/version/kubesphere"
"github.com/pkg/errors"
"gopkg.in/yaml.v2"
k8syaml "k8s.io/apimachinery/pkg/util/yaml"
)
var (
@@ -47,137 +38,19 @@ type Loader interface {
Load() (*kubekeyapiv1alpha2.Cluster, error)
}
type Options map[string]interface{}
func NewLoader(flag string, arg Argument) Loader {
switch flag {
case File:
return NewFileLoader(arg)
case Operator:
return &ConfigMapLoader{}
case AllInOne:
return NewDefaultLoader(arg)
case CommandLine:
return NewCommandLineLoader(arg)
default:
return NewDefaultLoader(arg)
}
}
type CommandLineLoader struct {
arg Argument
hostname string
kubernetesVersion string
}
func NewCommandLineLoader(arg Argument) *CommandLineLoader {
return &CommandLineLoader{
arg: arg,
kubernetesVersion: arg.KubernetesVersion,
}
}
func (c *CommandLineLoader) validate() error {
hostname, err := os.Hostname()
if err != nil {
return errors.New(fmt.Sprintf("Failed to get hostname: %v\n", err))
}
c.hostname = hostname
// flags
if c.arg.MasterNodeName == "" {
return errors.New("No master nodeName provided, with flag '--master-node-name'")
}
if c.arg.MasterHost == "" {
return errors.New("No master host provided, with flag '--master-host'")
}
if c.arg.MasterSSHUser == "" {
return errors.New("No master ssh user provided, with flag '--master-ssh-user'")
}
if c.arg.KubernetesVersion == "" {
return errors.New("No kubernetes version provided, with flag '--with-kubernetes'")
}
if c.arg.MasterSSHPassword == "" && c.arg.MasterSSHPrivateKeyPath == "" {
return errors.New("No master ssh password and private key file, with flag '--master-ssh-password' or '--master-ssh-private-keyfile'")
}
if err := localSSH(c.arg.SystemInfo.GetOsType()); err != nil {
return err
}
return nil
}
func (c *CommandLineLoader) Load() (*kubekeyapiv1alpha2.Cluster, error) {
u, err := currentUser(c.arg.SystemInfo.GetOsType())
if err != nil {
return nil, err
}
if err := c.validate(); err != nil {
return nil, err
}
cluster := &kubekeyapiv1alpha2.Cluster{}
// current node
cluster.Spec.Hosts = append(cluster.Spec.Hosts, kubekeyapiv1alpha2.HostCfg{
Name: c.hostname,
Address: "",
InternalAddress: "",
Port: c.arg.LocalSSHPort,
User: u.Name,
PrivateKeyPath: fmt.Sprintf("%s/.ssh/id_rsa", u.HomeDir),
Arch: "",
})
cluster.Spec.RoleGroups = map[string][]string{
Worker: {c.hostname},
}
// master node
masterHostCfg := kubekeyapiv1alpha2.HostCfg{
Name: c.arg.MasterNodeName,
Address: c.arg.MasterHost,
InternalAddress: c.arg.MasterHost,
Port: c.arg.MasterSSHPort,
User: c.arg.MasterSSHUser,
Arch: "",
}
if c.arg.MasterSSHPassword != "" {
masterHostCfg.Password = c.arg.MasterSSHPassword
}
if c.arg.MasterSSHPrivateKeyPath != "" {
masterHostCfg.Password = ""
masterHostCfg.PrivateKeyPath = c.arg.MasterSSHPrivateKeyPath
}
cluster.Spec.Hosts = append(cluster.Spec.Hosts, masterHostCfg)
cluster.Spec.RoleGroups[Master] = []string{c.arg.MasterNodeName}
cluster.Spec.RoleGroups[ETCD] = []string{c.arg.MasterNodeName}
if err := defaultCommonClusterConfig(cluster, c.arg); err != nil {
return nil, err
}
return cluster, nil
func NewLoader(arg Argument) Loader {
return NewDefaultLoader(arg)
}
type DefaultLoader struct {
arg Argument
KubernetesVersion string
KubeSphereVersion string
KubeSphereEnable bool
}
func NewDefaultLoader(arg Argument) *DefaultLoader {
return &DefaultLoader{
arg: arg,
KubernetesVersion: arg.KubernetesVersion,
KubeSphereVersion: arg.KsVersion,
KubeSphereEnable: arg.KsEnable,
}
}
@@ -268,16 +141,6 @@ func (d *DefaultLoader) Load() (*kubekeyapiv1alpha2.Cluster, error) {
}
}
if d.KubeSphereEnable {
ver := normalizedBuildVersion(d.KubeSphereVersion)
if ver == "" {
return nil, errors.New(fmt.Sprintf("Unsupported Kubesphere Version: %v\n", d.KubeSphereVersion))
}
if err := defaultKSConfig(&allInOne.Spec.KubeSphere, ver); err != nil {
return nil, err
}
}
if err := defaultCommonClusterConfig(allInOne, d.arg); err != nil {
return nil, err
}
@@ -289,147 +152,6 @@ func (d *DefaultLoader) Load() (*kubekeyapiv1alpha2.Cluster, error) {
return allInOne, nil
}
type FileLoader struct {
arg Argument
FilePath string
KubernetesVersion string
KubeSphereVersion string
KubeSphereEnable bool
}
func NewFileLoader(arg Argument) *FileLoader {
return &FileLoader{
arg: arg,
FilePath: arg.FilePath,
KubernetesVersion: arg.KubernetesVersion,
KubeSphereVersion: arg.KsVersion,
KubeSphereEnable: arg.KsEnable,
}
}
func (f FileLoader) Load() (*kubekeyapiv1alpha2.Cluster, error) {
var objName string
clusterCfg := kubekeyapiv1alpha2.Cluster{}
fp, err := filepath.Abs(f.FilePath)
if err != nil {
return nil, errors.Wrap(err, "Failed to look up current directory")
}
// fixme: It will lead to nil pointer err
//if len(f.KubernetesVersion) != 0 {
// _ = exec.Command("/bin/sh", "-c", fmt.Sprintf("sed -i \"/version/s/\\:.*/\\: %s/g\" %s", f.KubernetesVersion, fp)).Run()
//}
file, err := os.Open(fp)
if err != nil {
return nil, errors.Wrap(err, "Unable to open the given cluster configuration file")
}
defer file.Close()
b1 := bufio.NewReader(file)
for {
result := make(map[string]interface{})
content, err := k8syaml.NewYAMLReader(b1).Read()
if len(content) == 0 {
break
}
if err != nil {
return nil, errors.Wrap(err, "Unable to read the given cluster configuration file")
}
err = yaml.Unmarshal(content, &result)
if err != nil {
return nil, errors.Wrap(err, "Unable to unmarshal the given cluster configuration file")
}
if result["kind"] == "Cluster" {
contentToJson, err := k8syaml.ToJSON(content)
if err != nil {
return nil, errors.Wrap(err, "Unable to convert configuration to json")
}
if err := json.Unmarshal(contentToJson, &clusterCfg); err != nil {
return nil, errors.Wrap(err, "Failed to unmarshal configuration")
}
metadata := result["metadata"].(map[interface{}]interface{})
objName = metadata["name"].(string)
}
if result["kind"] == "ConfigMap" || result["kind"] == "ClusterConfiguration" {
metadata := result["metadata"].(map[interface{}]interface{})
labels := metadata["labels"].(map[interface{}]interface{})
clusterCfg.Spec.KubeSphere.Enabled = true
v, ok := labels["version"]
if !ok {
return nil, errors.New("Unknown version")
}
version := v.(string)
_, stable := kubesphere.StabledVersionSupport(version)
_, latest := kubesphere.LatestRelease(version)
_, dev := kubesphere.DevRelease(version)
if stable || latest || dev {
clusterCfg.Spec.KubeSphere.Configurations = "---\n" + string(content)
clusterCfg.Spec.KubeSphere.Version = version
} else {
return nil, errors.New(fmt.Sprintf("Unsupported KubeSphere version: %s", version))
}
}
}
if f.KubeSphereEnable {
ver := normalizedBuildVersion(f.KubeSphereVersion)
if ver == "" {
return nil, errors.New(fmt.Sprintf("Unsupported Kubesphere Version: %v\n", f.KubeSphereVersion))
}
if err := defaultKSConfig(&clusterCfg.Spec.KubeSphere, ver); err != nil {
return nil, err
}
}
if ver := normalizedBuildVersion(f.KubernetesVersion); ver != "" {
s := strings.Split(ver, "-")
if len(s) > 1 {
clusterCfg.Spec.Kubernetes.Version = s[0]
clusterCfg.Spec.Kubernetes.Type = s[1]
} else {
clusterCfg.Spec.Kubernetes.Version = ver
}
}
if f.arg.ContainerManager != "" && f.arg.ContainerManager != Docker {
clusterCfg.Spec.Kubernetes.ContainerManager = f.arg.ContainerManager
}
clusterCfg.Spec.Kubernetes.Version = normalizedBuildVersion(clusterCfg.Spec.Kubernetes.Version)
clusterCfg.Spec.KubeSphere.Version = normalizedBuildVersion(clusterCfg.Spec.KubeSphere.Version)
clusterCfg.Name = objName
return &clusterCfg, nil
}
type ConfigMapLoader struct {
}
func (c ConfigMapLoader) Load() (*kubekeyapiv1alpha2.Cluster, error) {
return nil, nil
}
func defaultKSConfig(ks *kubekeyapiv1alpha2.KubeSphere, version string) error {
ks.Enabled = true
version = strings.TrimSpace(version)
ksInstaller, ok := kubesphere.StabledVersionSupport(version)
if ok {
ks.Version = ksInstaller.Version
ks.Configurations = ksInstaller.CCToString()
} else if latest, ok := kubesphere.LatestRelease(version); ok {
ks.Version = version
ks.Configurations = latest.CCToString()
} else if dev, ok := kubesphere.DevRelease(version); ok {
ks.Version = version
ks.Configurations = dev.CCToString()
} else {
return errors.New(fmt.Sprintf("Unsupported KubeSphere version: %s", version))
}
return nil
}
// normalizedBuildVersion used to returns normalized build version (with "v" prefix if needed)
// If input doesn't match known version pattern, returns empty string.
func normalizedBuildVersion(version string) string {
@@ -442,57 +164,6 @@ func normalizedBuildVersion(version string) string {
return ""
}
type ExtraAddon struct {
Addons []kubekeyapiv1alpha2.Addon `yaml:"Addons"`
}
// load addon from argument
func loadExtraAddons(cluster *kubekeyapiv1alpha2.Cluster, addonFile string) error {
if addonFile == "" {
return nil
}
fp, err := filepath.Abs(addonFile)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("Failed to load addon in file: %s", addonFile))
}
content, err := ioutil.ReadFile(fp)
if err != nil {
return errors.Wrap(err, "Unable to open the given addon config file")
}
if len(content) == 0 {
return nil
}
var result ExtraAddon
err = yaml.Unmarshal(content, &result)
if err != nil {
return errors.Wrap(err, "Unable to read the given addon configuration file")
}
if len(result.Addons) > 0 {
cluster.Spec.Addons = append(cluster.Spec.Addons, result.Addons...)
}
return nil
}
func currentUser(osType string) (*user.User, error) {
u, err := user.Current()
if err != nil {
return nil, err
}
if osType != Darwin && osType != Windows {
if u.Username != "root" {
return nil, errors.New(fmt.Sprintf("Current user is %s. Please use root!", u.Username))
}
}
return u, nil
}
func installSUDOIfMissing() error {
p, _ := util.GetCommand("sudo")
if p != "" {

View File

@@ -1,72 +0,0 @@
/*
Copyright 2021 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package common
import (
"fmt"
"os"
"os/exec"
"os/user"
"github.com/beclab/Olares/cli/pkg/core/connector"
"github.com/pkg/errors"
)
type LocalRuntime struct {
connector.BaseRuntime
}
func NewLocalRuntime(debug, ingoreErr bool) (LocalRuntime, error) {
var localRuntime LocalRuntime
u, err := user.Current()
if err != nil {
return localRuntime, err
}
if u.Username != "root" {
return localRuntime, fmt.Errorf("current user is %s. Please use root", u.Username)
}
if output, err := exec.Command("/bin/sh", "-c", "if [ ! -f \"$HOME/.ssh/id_rsa\" ]; then mkdir -p \"$HOME/.ssh\" && ssh-keygen -t rsa-sha2-512 -P \"\" -f $HOME/.ssh/id_rsa && ls $HOME/.ssh;fi;").CombinedOutput(); err != nil {
return localRuntime, errors.New(fmt.Sprintf("Failed to generate public key: %v\n%s", err, string(output)))
}
if output, err := exec.Command("/bin/sh", "-c", "echo \"\n$(cat $HOME/.ssh/id_rsa.pub)\" >> $HOME/.ssh/authorized_keys && awk ' !x[$0]++{print > \"'$HOME'/.ssh/authorized_keys.tmp\"}' $HOME/.ssh/authorized_keys && mv $HOME/.ssh/authorized_keys.tmp $HOME/.ssh/authorized_keys").CombinedOutput(); err != nil {
return localRuntime, errors.New(fmt.Sprintf("Failed to copy public key to authorized_keys: %v\n%s", err, string(output)))
}
name, err := os.Hostname()
if err != nil {
return localRuntime, err
}
base := connector.NewBaseRuntime(name, connector.NewDialer(), debug, ingoreErr, "", "", "", false, nil)
host := connector.NewHost()
host.Name = name
host.Address = ""
host.InternalAddress = ""
host.Port = 22
host.User = u.Username
host.Password = ""
host.PrivateKeyPath = fmt.Sprintf("%s/.ssh/id_rsa", u.HomeDir)
host.Arch = ""
host.SetRole(KubeKey)
base.AppendHost(host)
base.AppendRoleMap(host)
local := LocalRuntime{base}
return local, nil
}

View File

@@ -51,7 +51,6 @@ type ModuleRuntime interface {
GetBaseDir() string
GetInstallerDir() string
GetWorkDir() string
GetIgnoreErr() bool
GetAllHosts() []Host
SetAllHosts([]Host)
GetHostsByRole(role string) []Host

View File

@@ -39,8 +39,6 @@ type BaseRuntime struct {
baseDir string
installerDir string
workDir string
verbose bool
ignoreErr bool
allHosts []Host
roleHosts map[string][]Host
deprecatedHosts map[string]string
@@ -50,12 +48,10 @@ type BaseRuntime struct {
k8sClient *kubernetes.Clientset
}
func NewBaseRuntime(name string, connector Connector, verbose bool, ignoreErr bool, baseDir string, olaresVersion string, consoleLogFileName string, consoleLogTruncate bool, systemInfo Systems) BaseRuntime {
func NewBaseRuntime(name string, connector Connector, baseDir string, olaresVersion string, consoleLogFileName string, consoleLogTruncate bool, systemInfo Systems) BaseRuntime {
base := BaseRuntime{
ObjName: name,
connector: connector,
verbose: verbose,
ignoreErr: ignoreErr,
allHosts: make([]Host, 0, 0),
roleHosts: make(map[string][]Host),
deprecatedHosts: make(map[string]string),
@@ -169,10 +165,6 @@ func (b *BaseRuntime) GetWorkDir() string {
return b.workDir
}
func (b *BaseRuntime) GetIgnoreErr() bool {
return b.ignoreErr
}
func (b *BaseRuntime) GetAllHosts() []Host {
hosts := make([]Host, 0, 0)
for i := range b.allHosts {

View File

@@ -51,10 +51,12 @@ func (d DebianVersion) String() string {
}
const (
Ubuntu20 UbuntuVersion = "20."
Ubuntu22 UbuntuVersion = "22."
Ubuntu24 UbuntuVersion = "24."
Ubuntu25 UbuntuVersion = "25."
Ubuntu20 UbuntuVersion = "20."
Ubuntu22 UbuntuVersion = "22."
Ubuntu24 UbuntuVersion = "24."
Ubuntu25 UbuntuVersion = "25."
Ubuntu2204 UbuntuVersion = "22.04"
Ubuntu2404 UbuntuVersion = "24.04"
Debian9 DebianVersion = "9"
Debian10 DebianVersion = "10"

View File

@@ -59,20 +59,6 @@ func (b *BaseTaskModule) Run(result *ending.ModuleResult) {
logger.Infof("[A] %s: %s %s (%s)", ac.Host.GetName(), t.GetName(), ac.Status.String(), util.ShortDur(elapsed))
result.AppendHostResult(ac)
if _, ok := t.(*task.RemoteTask); ok {
if b.Runtime.GetIgnoreErr() {
if len(b.Runtime.GetAllHosts()) > 0 {
if ac.GetStatus() == ending.FAILED {
res.Status = ending.SUCCESS
b.Runtime.DeleteHost(ac.Host)
}
} else {
result.ErrResult(errors.Wrapf(res.CombineErr(), "Module[%s] exec failed", b.Name))
return
}
}
}
}
if res.IsFailed() {

View File

@@ -86,6 +86,14 @@ func IsDir(path string) bool {
return s.IsDir()
}
func IsExecutable(path string) bool {
info, err := os.Stat(path)
if err != nil {
return false
}
return info.Mode().Perm()&0111 != 0
}
func CountDirFiles(dirName string) int {
if !IsDir(dirName) {
return 0

View File

@@ -10,8 +10,8 @@ import (
"strings"
"time"
v1alpha1 "bytetrade.io/web3os/app-service/api/sys.bytetrade.io/v1alpha1"
apputils "bytetrade.io/web3os/app-service/pkg/utils"
v1alpha1 "github.com/beclab/Olares/framework/app-service/api/sys.bytetrade.io/v1alpha1"
apputils "github.com/beclab/Olares/framework/app-service/pkg/utils"
ctrl "sigs.k8s.io/controller-runtime"
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
@@ -165,7 +165,7 @@ func (t *UpdateNvidiaContainerToolkitSource) Execute(runtime connector.Runtime)
// decide mirror based on OLARES_SYSTEM_CDN_SERVICE
var mirrorHost string
cdnService := os.Getenv(common.ENV_OLARES_CDN_SERVICE)
cdnService := t.KubeConf.Arg.OlaresCDNService
if cdnService != "" {
cdnRaw := cdnService
if !strings.HasPrefix(cdnRaw, "http") {
@@ -263,6 +263,10 @@ func (t *PatchK3sDriver) Execute(runtime connector.Runtime) error {
return err
}
if _, err := runtime.GetRunner().SudoCmd("apt install -y strace", false, false); err != nil {
return err
}
if _, err := runtime.GetRunner().SudoCmd(dstName, false, false); err != nil {
return errors.Wrap(err, "failed to apply CUDA patch for WSL")
}

View File

@@ -10,17 +10,39 @@ var (
K3sCudaFixValues = template.Must(template.New("cuda_lib_fix.sh").Parse(
dedent.Dedent(`#!/bin/bash
sh_c="sh -c"
real_driver=$($sh_c "find /usr/lib/wsl/drivers/ -name libcuda.so.1.1|head -1")
real_driver=""
real_nvml=""
# Try to find the real driver path via strace
real_driver_path=$($sh_c "strace -qq -e trace=openat /usr/lib/wsl/lib/nvidia-smi 2>&1|grep '/usr/lib/wsl/drivers'|grep libnvidia-ml.so.1|awk '{print \$2}'|sed 's/[\",]//g'|sed 's/libnvidia-ml.so.1//g'")
if [[ x"$real_driver_path" != x"" ]]; then
real_driver="${real_driver_path}libcuda.so.1.1"
real_nvml="${real_driver_path}libnvidia-ml.so.1"
else
driver_path=$($sh_c "strace -qq -e trace=openat /usr/lib/wsl/lib/nvidia-smi 2>&1|grep '/usr/lib/wsl/'|grep libnvidia-ml.so.1")
if [[ x"$driver_path" != x"" ]]; then
echo "already fixed cuda libs, exit now."
exit 0
fi
fi
if [[ x"$real_driver" == x"" ]]; then
real_driver=$($sh_c "find /usr/lib/wsl/drivers/ -name libcuda.so.1.1|head -1")
real_nvml=$($sh_c "find /usr/lib/wsl/drivers/ -name libnvidia-ml.so.1|head -1")
fi
if [[ x"$real_driver" != x"" ]]; then
$sh_c "ln -s /usr/lib/wsl/lib/libcuda* /usr/lib/x86_64-linux-gnu/"
$sh_c "rm -f /usr/lib/x86_64-linux-gnu/libcuda.so"
$sh_c "rm -f /usr/lib/x86_64-linux-gnu/libcuda.so.1"
$sh_c "rm -f /usr/lib/x86_64-linux-gnu/libcuda.so.1.1"
$sh_c "rm -f /usr/lib/x86_64-linux-gnu/libnvidia-ml.so.1"
$sh_c "cp -f $real_driver /usr/lib/wsl/lib/libcuda.so"
$sh_c "cp -f $real_driver /usr/lib/wsl/lib/libcuda.so.1"
$sh_c "cp -f $real_driver /usr/lib/wsl/lib/libcuda.so.1.1"
$sh_c "ln -s $real_driver /usr/lib/x86_64-linux-gnu/libcuda.so.1"
$sh_c "ln -s $real_driver /usr/lib/x86_64-linux-gnu/libcuda.so.1.1"
$sh_c "cp -f $real_nvml /usr/lib/wsl/lib/libnvidia-ml.so.1"
$sh_c "cp -f $real_driver /usr/lib/x86_64-linux-gnu/"
$sh_c "cp -f $real_nvml /usr/lib/x86_64-linux-gnu/"
$sh_c "ln -s /usr/lib/x86_64-linux-gnu/libcuda.so.1.1 /usr/lib/x86_64-linux-gnu/libcuda.so.1"
$sh_c "ln -s /usr/lib/x86_64-linux-gnu/libcuda.so.1 /usr/lib/x86_64-linux-gnu/libcuda.so"
fi`),
))

View File

@@ -36,6 +36,7 @@ import (
"github.com/beclab/Olares/cli/pkg/k3s/templates"
"github.com/beclab/Olares/cli/pkg/manifest"
"github.com/beclab/Olares/cli/pkg/registry"
"github.com/beclab/Olares/cli/pkg/storage"
)
type InstallContainerModule struct {
@@ -470,6 +471,18 @@ func (j *JoinNodesModule) Init() {
Parallel: true,
}
createSharedLibDirForWorker := &task.RemoteTask{
Name: "CreateSharedLibDir(k3s)",
Desc: "Create shared lib directory on worker",
Hosts: j.Runtime.GetHostsByRole(common.Worker),
Prepare: &prepare.PrepareCollection{
&kubernetes.NodeInCluster{Not: true},
new(common.OnlyWorker),
},
Action: new(storage.CreateSharedLibDir),
Parallel: true,
}
enableK3s := &task.RemoteTask{
Name: "EnableK3sService",
Desc: "Enable k3s service",
@@ -536,6 +549,7 @@ func (j *JoinNodesModule) Init() {
k3sService,
k3sEnv,
k3sRegistryConfig,
createSharedLibDirForWorker,
enableK3s,
copyKubeConfigForMaster,
syncKubeConfigToWorker,
@@ -579,22 +593,3 @@ func (d *DeleteClusterModule) Init() {
execScript,
}
}
type SaveKubeConfigModule struct {
common.KubeModule
}
func (s *SaveKubeConfigModule) Init() {
s.Name = "SaveKubeConfigModule"
s.Desc = "Save kube config file as a configmap"
save := &task.LocalTask{
Name: "SaveKubeConfig(k3s)",
Desc: "Save kube config as a configmap",
Action: new(SaveKubeConfig),
}
s.Tasks = []task.Interface{
save,
}
}

View File

@@ -17,8 +17,6 @@
package k3s
import (
"context"
"encoding/base64"
"fmt"
"path/filepath"
"strings"
@@ -41,11 +39,7 @@ import (
"github.com/beclab/Olares/cli/pkg/k3s/templates"
"github.com/beclab/Olares/cli/pkg/utils"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
versionutil "k8s.io/apimachinery/pkg/util/version"
kube "k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
)
type GetClusterStatus struct {
@@ -195,13 +189,13 @@ func (g *GenerateK3sService) Execute(runtime connector.Runtime) error {
defaultKubeletArs := map[string]string{
"kube-reserved": "cpu=200m,memory=250Mi,ephemeral-storage=1Gi",
"system-reserved": "cpu=200m,memory=250Mi,ephemeral-storage=1Gi",
"eviction-hard": "memory.available<5%,nodefs.available<10%,imagefs.available<10%",
"eviction-hard": "memory.available<5%,nodefs.available<5%,imagefs.available<5%",
"config": "/etc/rancher/k3s/kubelet.config",
"containerd": container.DefaultContainerdCRISocket,
"cgroup-driver": "systemd",
"runtime-request-timeout": "5m",
"image-gc-high-threshold": "91",
"image-gc-low-threshold": "90",
"image-gc-high-threshold": "96",
"image-gc-low-threshold": "95",
"housekeeping_interval": "5s",
}
defaultKubeProxyArgs := map[string]string{
@@ -397,53 +391,23 @@ type CopyK3sKubeConfig struct {
}
func (c *CopyK3sKubeConfig) Execute(runtime connector.Runtime) error {
createConfigDirCmd := "mkdir -p /root/.kube && mkdir -p $HOME/.kube"
getKubeConfigCmd := "cp -f /etc/rancher/k3s/k3s.yaml /root/.kube/config"
chmodKubeConfigCmd := "chmod 0600 /root/.kube/config"
targetHome, targetUID, targetGID, err := utils.ResolveSudoUserHomeAndIDs(runtime)
if err != nil {
return err
}
cmd := strings.Join([]string{createConfigDirCmd, getKubeConfigCmd, chmodKubeConfigCmd}, " && ")
if _, err := runtime.GetRunner().SudoCmd(cmd, false, false); err != nil {
cmds := []string{
"mkdir -p /root/.kube",
"cp -f /etc/rancher/k3s/k3s.yaml /root/.kube/config",
"chmod 0600 /root/.kube/config",
fmt.Sprintf("mkdir -p %s", filepath.Join(targetHome, ".kube")),
fmt.Sprintf("cp -f /etc/rancher/k3s/k3s.yaml %s", filepath.Join(targetHome, ".kube", "config")),
fmt.Sprintf("chmod 0600 %s", filepath.Join(targetHome, ".kube", "config")),
fmt.Sprintf("chown -R %s:%s %s", targetUID, targetGID, filepath.Join(targetHome, ".kube")),
}
if _, err := runtime.GetRunner().SudoCmd(strings.Join(cmds, " && "), false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "copy k3s kube config failed")
}
userMkdir := "mkdir -p $HOME/.kube"
if _, err := runtime.GetRunner().Cmd(userMkdir, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "user mkdir $HOME/.kube failed")
}
userCopyKubeConfig := "cp -f /etc/rancher/k3s/k3s.yaml $HOME/.kube/config"
if _, err := runtime.GetRunner().SudoCmd(userCopyKubeConfig, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "user copy /etc/rancher/k3s/k3s.yaml to $HOME/.kube/config failed")
}
if _, err := runtime.GetRunner().SudoCmd("chmod 0600 $HOME/.kube/config", false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "chmod k3s $HOME/.kube/config 0600 failed")
}
// userId, err := runtime.GetRunner().Cmd("echo $(id -u)", false, false)
// if err != nil {
// return errors.Wrap(errors.WithStack(err), "get user id failed")
// }
// userGroupId, err := runtime.GetRunner().Cmd("echo $(id -g)", false, false)
// if err != nil {
// return errors.Wrap(errors.WithStack(err), "get user group id failed")
// }
userId, err := runtime.GetRunner().Cmd("echo $SUDO_UID", false, false)
if err != nil {
return errors.Wrap(errors.WithStack(err), "get user id failed")
}
userGroupId, err := runtime.GetRunner().Cmd("echo $SUDO_GID", false, false)
if err != nil {
return errors.Wrap(errors.WithStack(err), "get user group id failed")
}
chownKubeConfig := fmt.Sprintf("chown -R %s:%s $HOME/.kube", userId, userGroupId)
if _, err := runtime.GetRunner().SudoCmd(chownKubeConfig, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "chown user kube config failed")
}
return nil
}
@@ -493,59 +457,29 @@ func (s *SyncKubeConfigToWorker) Execute(runtime connector.Runtime) error {
if v, ok := s.PipelineCache.Get(common.ClusterStatus); ok {
cluster := v.(*K3sStatus)
createConfigDirCmd := "mkdir -p /root/.kube"
if _, err := runtime.GetRunner().SudoCmd(createConfigDirCmd, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "create .kube dir failed")
}
oldServer := "server: https://127.0.0.1:6443"
newServer := fmt.Sprintf("server: https://%s:%d",
s.KubeConf.Cluster.ControlPlaneEndpoint.Domain,
s.KubeConf.Cluster.ControlPlaneEndpoint.Port)
newKubeConfig := strings.Replace(cluster.KubeConfig, oldServer, newServer, -1)
syncKubeConfigForRootCmd := fmt.Sprintf("echo '%s' > %s", newKubeConfig, "/root/.kube/config")
if _, err := runtime.GetRunner().SudoCmd(syncKubeConfigForRootCmd, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "sync kube config for root failed")
}
if _, err := runtime.GetRunner().SudoCmd("chmod 0600 /root/.kube/config", false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "chmod k3s $HOME/.kube/config failed")
}
userConfigDirCmd := "mkdir -p $HOME/.kube"
if _, err := runtime.GetRunner().Cmd(userConfigDirCmd, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "user mkdir $HOME/.kube failed")
}
syncKubeConfigForUserCmd := fmt.Sprintf("echo '%s' > %s", newKubeConfig, "$HOME/.kube/config")
if _, err := runtime.GetRunner().Cmd(syncKubeConfigForUserCmd, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "sync kube config for normal user failed")
}
// userId, err := runtime.GetRunner().Cmd("echo $(id -u)", false, false)
// if err != nil {
// return errors.Wrap(errors.WithStack(err), "get user id failed")
// }
// userGroupId, err := runtime.GetRunner().Cmd("echo $(id -g)", false, false)
// if err != nil {
// return errors.Wrap(errors.WithStack(err), "get user group id failed")
// }
userId, err := runtime.GetRunner().Cmd("echo $SUDO_UID", false, false)
targetHome, targetUID, targetGID, err := utils.ResolveSudoUserHomeAndIDs(runtime)
if err != nil {
return errors.Wrap(errors.WithStack(err), "get user id failed")
return err
}
targetKubeConfigPath := filepath.Join(targetHome, ".kube", "config")
userGroupId, err := runtime.GetRunner().Cmd("echo $SUDO_GID", false, false)
if err != nil {
return errors.Wrap(errors.WithStack(err), "get user group id failed")
cmds := []string{
"mkdir -p /root/.kube",
fmt.Sprintf("echo '%s' > %s", newKubeConfig, "/root/.kube/config"),
"chmod 0600 /root/.kube/config",
fmt.Sprintf("mkdir -p %s", filepath.Join(targetHome, ".kube")),
fmt.Sprintf("echo '%s' > %s", newKubeConfig, targetKubeConfigPath),
fmt.Sprintf("chmod 0600 %s", targetKubeConfigPath),
fmt.Sprintf("chown -R %s:%s %s", targetUID, targetGID, filepath.Join(targetHome, ".kube")),
}
chownKubeConfig := fmt.Sprintf("chown -R %s:%s -R $HOME/.kube", userId, userGroupId)
if _, err := runtime.GetRunner().SudoCmd(chownKubeConfig, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "chown user kube config failed")
if _, err := runtime.GetRunner().SudoCmd(strings.Join(cmds, " && "), false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "sync kube config failed")
}
}
return nil
@@ -575,65 +509,6 @@ func (e *ExecUninstallScript) Execute(runtime connector.Runtime) error {
return nil
}
type SaveKubeConfig struct {
common.KubeAction
}
func (s *SaveKubeConfig) Execute(_ connector.Runtime) error {
status, ok := s.PipelineCache.Get(common.ClusterStatus)
if !ok {
return errors.New("get kubernetes status failed by pipeline cache")
}
cluster := status.(*K3sStatus)
oldServer := fmt.Sprintf("https://%s:%d", s.KubeConf.Cluster.ControlPlaneEndpoint.Domain, s.KubeConf.Cluster.ControlPlaneEndpoint.Port)
newServer := fmt.Sprintf("https://%s:%d", s.KubeConf.Cluster.ControlPlaneEndpoint.Address, s.KubeConf.Cluster.ControlPlaneEndpoint.Port)
newKubeConfigStr := strings.Replace(cluster.KubeConfig, oldServer, newServer, -1)
kubeConfigBase64 := base64.StdEncoding.EncodeToString([]byte(newKubeConfigStr))
config, err := clientcmd.NewClientConfigFromBytes([]byte(newKubeConfigStr))
if err != nil {
return err
}
restConfig, err := config.ClientConfig()
if err != nil {
return err
}
clientsetForCluster, err := kube.NewForConfig(restConfig)
if err != nil {
return err
}
namespace := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "kubekey-system",
},
}
if _, err := clientsetForCluster.
CoreV1().
Namespaces().
Create(context.TODO(), namespace, metav1.CreateOptions{}); err != nil {
// return err
}
cm := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s-kubeconfig", s.KubeConf.ClusterName),
},
Data: map[string]string{
"kubeconfig": kubeConfigBase64,
},
}
if _, err := clientsetForCluster.
CoreV1().
ConfigMaps("kubekey-system").
Create(context.TODO(), cm, metav1.CreateOptions{}); err != nil {
// return err
}
return nil
}
type GenerateK3sRegistryConfig struct {
common.KubeAction
}

View File

@@ -23,6 +23,7 @@ import (
"github.com/beclab/Olares/cli/pkg/core/prepare"
"github.com/beclab/Olares/cli/pkg/core/task"
"github.com/beclab/Olares/cli/pkg/manifest"
"github.com/beclab/Olares/cli/pkg/storage"
)
type StatusModule struct {
@@ -243,6 +244,18 @@ func (j *JoinNodesModule) Init() {
Retry: 5,
}
createSharedLibDirForWorker := &task.RemoteTask{
Name: "CreateSharedLibDir(k8s)",
Desc: "Create shared lib directory on worker",
Hosts: j.Runtime.GetHostsByRole(common.Worker),
Prepare: &prepare.PrepareCollection{
&NodeInCluster{Not: true},
new(common.OnlyWorker),
},
Action: new(storage.CreateSharedLibDir),
Parallel: true,
}
joinWorkerNode := &task.RemoteTask{
Name: "JoinWorkerNode(k8s)",
Desc: "Join worker node",
@@ -323,6 +336,7 @@ func (j *JoinNodesModule) Init() {
j.Tasks = []task.Interface{
generateKubeadmConfig,
joinMasterNode,
createSharedLibDirForWorker,
joinWorkerNode,
copyKubeConfig,
removeMasterTaint,
@@ -380,26 +394,6 @@ func (c *UmountKubeModule) Init() {
}
}
type SaveKubeConfigModule struct {
common.KubeModule
}
func (s *SaveKubeConfigModule) Init() {
s.Name = "SaveKubeConfigModule"
s.Desc = "Save kube config file as a configmap"
save := &task.LocalTask{
Name: "SaveKubeConfig(k8s)",
Desc: "Save kube config as a configmap",
Action: new(SaveKubeConfig),
Retry: 5,
}
s.Tasks = []task.Interface{
save,
}
}
type ConfigureKubernetesModule struct {
common.KubeModule
}

View File

@@ -19,7 +19,6 @@ package kubernetes
import (
"bufio"
"context"
"encoding/base64"
"fmt"
"os"
"os/exec"
@@ -34,11 +33,6 @@ import (
"github.com/beclab/Olares/cli/pkg/manifest"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
kubeerrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
kube "k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
kubekeyv1alpha2 "github.com/beclab/Olares/cli/apis/kubekey/v1alpha2"
"github.com/beclab/Olares/cli/pkg/common"
@@ -417,51 +411,23 @@ type CopyKubeConfigForControlPlane struct {
}
func (c *CopyKubeConfigForControlPlane) Execute(runtime connector.Runtime) error {
createConfigDirCmd := "mkdir -p /root/.kube"
getKubeConfigCmd := "cp -f /etc/kubernetes/admin.conf /root/.kube/config"
cmd := strings.Join([]string{createConfigDirCmd, getKubeConfigCmd}, " && ")
if _, err := runtime.GetRunner().SudoCmd(cmd, false, false); err != nil {
targetHome, targetUID, targetGID, err := utils.ResolveSudoUserHomeAndIDs(runtime)
if err != nil {
return err
}
cmds := []string{
"mkdir -p /root/.kube",
"cp -f /etc/kubernetes/admin.conf /root/.kube/config",
"chmod 0600 /root/.kube/config",
fmt.Sprintf("mkdir -p %s", filepath.Join(targetHome, ".kube")),
fmt.Sprintf("cp -f /etc/kubernetes/admin.conf %s", filepath.Join(targetHome, ".kube", "config")),
fmt.Sprintf("chmod 0600 %s", filepath.Join(targetHome, ".kube", "config")),
fmt.Sprintf("chown -R %s:%s %s", targetUID, targetGID, filepath.Join(targetHome, ".kube")),
}
if _, err := runtime.GetRunner().SudoCmd(strings.Join(cmds, " && "), false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "copy kube config failed")
}
userMkdir := "mkdir -p $HOME/.kube"
if _, err := runtime.GetRunner().Cmd(userMkdir, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "user mkdir $HOME/.kube failed")
}
userCopyKubeConfig := "cp -f /etc/kubernetes/admin.conf $HOME/.kube/config"
if _, err := runtime.GetRunner().SudoCmd(userCopyKubeConfig, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "user copy /etc/kubernetes/admin.conf to $HOME/.kube/config failed")
}
if _, err := runtime.GetRunner().SudoCmd("chmod 0600 $HOME/.kube/config", false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "chmod $HOME/.kube/config failed")
}
// userId, err := runtime.GetRunner().Cmd("echo $(id -u)", false, false)
// if err != nil {
// return errors.Wrap(errors.WithStack(err), "get user id failed")
// }
// userGroupId, err := runtime.GetRunner().Cmd("echo $(id -g)", false, false)
// if err != nil {
// return errors.Wrap(errors.WithStack(err), "get user group id failed")
// }
userId, err := runtime.GetRunner().Cmd("echo $SUDO_UID", false, false)
if err != nil {
return errors.Wrap(errors.WithStack(err), "get user id failed")
}
userGroupId, err := runtime.GetRunner().Cmd("echo $SUDO_GID", false, false)
if err != nil {
return errors.Wrap(errors.WithStack(err), "get user group id failed")
}
chownKubeConfig := fmt.Sprintf("chown -R %s:%s $HOME/.kube", userId, userGroupId)
if _, err := runtime.GetRunner().SudoCmd(chownKubeConfig, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "chown user kube config failed")
}
return nil
}
@@ -521,53 +487,23 @@ func (s *SyncKubeConfigToWorker) Execute(runtime connector.Runtime) error {
if v, ok := s.PipelineCache.Get(common.ClusterStatus); ok {
cluster := v.(*KubernetesStatus)
createConfigDirCmd := "mkdir -p /root/.kube"
if _, err := runtime.GetRunner().SudoCmd(createConfigDirCmd, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "create .kube dir failed")
}
syncKubeConfigForRootCmd := fmt.Sprintf("echo '%s' > %s", cluster.KubeConfig, "/root/.kube/config")
if _, err := runtime.GetRunner().SudoCmd(syncKubeConfigForRootCmd, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "sync kube config for root failed")
}
if _, err := runtime.GetRunner().SudoCmd("chmod 0600 /root/.kube/config", false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "chmod $HOME/.kube/config failed")
}
userConfigDirCmd := "mkdir -p $HOME/.kube"
if _, err := runtime.GetRunner().Cmd(userConfigDirCmd, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "user mkdir $HOME/.kube failed")
}
syncKubeConfigForUserCmd := fmt.Sprintf("echo '%s' > %s", cluster.KubeConfig, "$HOME/.kube/config")
if _, err := runtime.GetRunner().Cmd(syncKubeConfigForUserCmd, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "sync kube config for normal user failed")
}
// userId, err := runtime.GetRunner().Cmd("echo $(id -u)", false, false)
// if err != nil {
// return errors.Wrap(errors.WithStack(err), "get user id failed")
// }
// userGroupId, err := runtime.GetRunner().Cmd("echo $(id -g)", false, false)
// if err != nil {
// return errors.Wrap(errors.WithStack(err), "get user group id failed")
// }
userId, err := runtime.GetRunner().Cmd("echo $SUDO_UID", false, false)
targetHome, targetUID, targetGID, err := utils.ResolveSudoUserHomeAndIDs(runtime)
if err != nil {
return errors.Wrap(errors.WithStack(err), "get user id failed")
return err
}
targetKubeConfigPath := filepath.Join(targetHome, ".kube", "config")
userGroupId, err := runtime.GetRunner().Cmd("echo $SUDO_GID", false, false)
if err != nil {
return errors.Wrap(errors.WithStack(err), "get user group id failed")
cmds := []string{
"mkdir -p /root/.kube",
fmt.Sprintf("echo '%s' > %s", cluster.KubeConfig, "/root/.kube/config"),
"chmod 0600 /root/.kube/config",
fmt.Sprintf("mkdir -p %s", filepath.Join(targetHome, ".kube")),
fmt.Sprintf("echo '%s' > %s", cluster.KubeConfig, targetKubeConfigPath),
fmt.Sprintf("chmod 0600 %s", targetKubeConfigPath),
fmt.Sprintf("chown -R %s:%s %s", targetUID, targetGID, filepath.Join(targetHome, ".kube")),
}
chownKubeConfig := fmt.Sprintf("chown -R %s:%s -R $HOME/.kube", userId, userGroupId)
if _, err := runtime.GetRunner().SudoCmd(chownKubeConfig, false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "chown user kube config failed")
if _, err := runtime.GetRunner().SudoCmd(strings.Join(cmds, " && "), false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "sync kube config failed")
}
}
return nil
@@ -660,91 +596,6 @@ func (k *KubectlDeleteCurrentWorkerNode) Execute(runtime connector.Runtime) erro
return nil
}
type SaveKubeConfig struct {
common.KubeAction
}
func (s *SaveKubeConfig) Execute(runtime connector.Runtime) error {
status, ok := s.PipelineCache.Get(common.ClusterStatus)
if !ok {
return errors.New("get kubernetes status failed by pipeline cache")
}
cluster := status.(*KubernetesStatus)
kubeConfigStr := cluster.KubeConfig
clusterPublicAddress := s.KubeConf.Cluster.ControlPlaneEndpoint.Address
master1 := runtime.GetHostsByRole(common.Master)[0]
if clusterPublicAddress == master1.GetInternalAddress() {
clusterPublicAddress = master1.GetAddress()
}
oldServer := fmt.Sprintf("https://%s:%d", s.KubeConf.Cluster.ControlPlaneEndpoint.Domain, s.KubeConf.Cluster.ControlPlaneEndpoint.Port)
newServer := fmt.Sprintf("https://%s:%d", clusterPublicAddress, s.KubeConf.Cluster.ControlPlaneEndpoint.Port)
newKubeConfigStr := strings.Replace(kubeConfigStr, oldServer, newServer, -1)
kubeConfigBase64 := base64.StdEncoding.EncodeToString([]byte(newKubeConfigStr))
config, err := clientcmd.NewClientConfigFromBytes([]byte(newKubeConfigStr))
if err != nil {
return err
}
restConfig, err := config.ClientConfig()
if err != nil {
return err
}
clientsetForCluster, err := kube.NewForConfig(restConfig)
if err != nil {
return err
}
namespace := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "kubekey-system",
},
}
if _, err := clientsetForCluster.
CoreV1().
Namespaces().
Get(context.TODO(), namespace.Name, metav1.GetOptions{}); kubeerrors.IsNotFound(err) {
if _, err := clientsetForCluster.
CoreV1().
Namespaces().
Create(context.TODO(), namespace, metav1.CreateOptions{}); err != nil {
return err
}
} else {
return err
}
cm := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s-kubeconfig", s.KubeConf.ClusterName),
},
Data: map[string]string{
"kubeconfig": kubeConfigBase64,
},
}
if _, err := clientsetForCluster.
CoreV1().
ConfigMaps("kubekey-system").
Get(context.TODO(), cm.Name, metav1.GetOptions{}); kubeerrors.IsNotFound(err) {
if _, err := clientsetForCluster.
CoreV1().
ConfigMaps("kubekey-system").
Create(context.TODO(), cm, metav1.CreateOptions{}); err != nil {
return err
}
} else {
if _, err := clientsetForCluster.
CoreV1().
ConfigMaps("kubekey-system").
Update(context.TODO(), cm, metav1.UpdateOptions{}); err != nil {
return err
}
}
return nil
}
type ConfigureKubernetes struct {
common.KubeAction
}

View File

@@ -296,8 +296,10 @@ func GetKubeletConfiguration(runtime connector.Runtime, kubeConf *common.KubeCon
"memory": "250Mi",
},
"evictionHard": map[string]string{
"memory.available": "5%",
"pid.available": "10%",
"memory.available": "5%",
"pid.available": "10%",
"nodefs.available": "5%",
"imagefs.available": "5%",
},
"evictionSoft": map[string]string{
"memory.available": "10%",
@@ -309,8 +311,8 @@ func GetKubeletConfiguration(runtime connector.Runtime, kubeConf *common.KubeCon
"evictionPressureTransitionPeriod": "30s",
"featureGates": FeatureGatesDefaultConfiguration,
"runtimeRequestTimeout": "5m",
"imageGCHighThresholdPercent": 91,
"imageGCLowThresholdPercent": 90,
"imageGCHighThresholdPercent": 96,
"imageGCLowThresholdPercent": 95,
}
if securityEnhancement {
@@ -387,10 +389,6 @@ func GetKubeletConfiguration(runtime connector.Runtime, kubeConf *common.KubeCon
}
}
if kubeConf.Arg.Debug {
logger.Debugf("Set kubeletConfiguration: %v", kubeletConfiguration)
}
return kubeletConfiguration
}

View File

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

View File

@@ -46,11 +46,6 @@ func (m *DeleteKubeSphereCachesModule) Init() {
type DeployModule struct {
common.KubeModule
Skip bool
}
func (d *DeployModule) IsSkip() bool {
return d.Skip
}
func (d *DeployModule) Init() {
@@ -76,11 +71,6 @@ func (d *DeployModule) Init() {
type CheckResultModule struct {
common.KubeModule
Skip bool
}
func (c *CheckResultModule) IsSkip() bool {
return c.Skip
}
func (c *CheckResultModule) Init() {

View File

@@ -7,7 +7,6 @@ import (
kubekeyapiv1alpha2 "github.com/beclab/Olares/cli/apis/kubekey/v1alpha2"
"github.com/beclab/Olares/cli/pkg/bootstrap/confirm"
"github.com/beclab/Olares/cli/pkg/bootstrap/os"
"github.com/beclab/Olares/cli/pkg/bootstrap/precheck"
"github.com/beclab/Olares/cli/pkg/certs"
@@ -36,11 +35,11 @@ func NewDarwinClusterPhase(runtime *common.KubeRuntime, manifestMap manifest.Ins
},
},
&kubesphere.DeployMiniKubeModule{},
&kubesphere.DeployModule{Skip: !runtime.Cluster.KubeSphere.Enabled},
&kubesphere.DeployModule{},
&ksplugins.DeployKsCoreConfigModule{}, // ks-core-config
&ksplugins.DeployPrometheusModule{},
&ksplugins.DeployKsCoreModule{},
&kubesphere.CheckResultModule{Skip: !runtime.Cluster.KubeSphere.Enabled},
&kubesphere.CheckResultModule{},
}
return m
@@ -53,13 +52,6 @@ func NewK3sCreateClusterPhase(runtime *common.KubeRuntime, manifestMap manifest.
baseDir = path.Join(runtime.Arg.GetWslUserPath(), cc.DefaultBaseDir)
}
skipLocalStorage := true
if runtime.Arg.DeployLocalStorage != nil {
skipLocalStorage = !*runtime.Arg.DeployLocalStorage
} else if runtime.Cluster.KubeSphere.Enabled {
skipLocalStorage = false
}
m := []module.Module{
&k3s.StatusModule{},
&os.ConfigureOSModule{},
@@ -87,13 +79,12 @@ func NewK3sCreateClusterPhase(runtime *common.KubeRuntime, manifestMap manifest.
&kubernetes.ConfigureKubernetesModule{},
&filesystem.ChownModule{},
&certs.AutoRenewCertsModule{Skip: !runtime.Cluster.Kubernetes.EnableAutoRenewCerts()},
&k3s.SaveKubeConfigModule{},
&storage.DeployLocalVolumeModule{Skip: skipLocalStorage},
&kubesphere.DeployModule{Skip: !runtime.Cluster.KubeSphere.Enabled},
&storage.DeployLocalVolumeModule{},
&kubesphere.DeployModule{},
&ksplugins.DeployKsCoreConfigModule{},
&ksplugins.DeployPrometheusModule{},
&ksplugins.DeployKsCoreModule{},
&kubesphere.CheckResultModule{Skip: !runtime.Cluster.KubeSphere.Enabled},
&kubesphere.CheckResultModule{},
}
return m
@@ -106,16 +97,8 @@ func NewCreateClusterPhase(runtime *common.KubeRuntime, manifestMap manifest.Ins
baseDir = path.Join(runtime.Arg.GetWslUserPath(), cc.DefaultBaseDir)
}
skipLocalStorage := true
if runtime.Arg.DeployLocalStorage != nil {
skipLocalStorage = !*runtime.Arg.DeployLocalStorage
} else if runtime.Cluster.KubeSphere.Enabled {
skipLocalStorage = false
}
m := []module.Module{
&precheck.NodePreCheckModule{},
&confirm.InstallConfirmModule{Skip: runtime.Arg.SkipConfirmCheck},
&kubernetes.StatusModule{},
&os.ConfigureOSModule{},
&etcd.PreCheckModule{Skip: runtime.Cluster.Etcd.Type != kubekeyapiv1alpha2.KubeKey},
@@ -144,13 +127,12 @@ func NewCreateClusterPhase(runtime *common.KubeRuntime, manifestMap manifest.Ins
&filesystem.ChownModule{},
&certs.AutoRenewCertsModule{Skip: !runtime.Cluster.Kubernetes.EnableAutoRenewCerts()},
&kubernetes.SecurityEnhancementModule{Skip: !runtime.Arg.SecurityEnhancement},
&kubernetes.SaveKubeConfigModule{},
&storage.DeployLocalVolumeModule{Skip: skipLocalStorage},
&kubesphere.DeployModule{Skip: !runtime.Cluster.KubeSphere.Enabled},
&storage.DeployLocalVolumeModule{},
&kubesphere.DeployModule{},
&ksplugins.DeployKsCoreConfigModule{}, // ! ks-core-config
&ksplugins.DeployPrometheusModule{},
&ksplugins.DeployKsCoreModule{},
&kubesphere.CheckResultModule{Skip: !runtime.Cluster.KubeSphere.Enabled}, // check ks-apiserver phase
&kubesphere.CheckResultModule{}, // check ks-apiserver phase
}
return m

View File

@@ -111,6 +111,7 @@ func (p *phaseBuilder) phaseInstall() *phaseBuilder {
PhaseFile: common.TerminusStateFileInstalled,
BaseDir: p.runtime.GetBaseDir(),
},
&terminus.WriteReleaseFileModule{WithoutName: true},
)
}
return p

View File

@@ -3,8 +3,7 @@ package system
import (
"strings"
"github.com/beclab/Olares/cli/pkg/gpu"
"github.com/beclab/Olares/cli/pkg/amdgpu"
"github.com/beclab/Olares/cli/pkg/bootstrap/os"
"github.com/beclab/Olares/cli/pkg/bootstrap/patch"
"github.com/beclab/Olares/cli/pkg/bootstrap/precheck"
@@ -12,6 +11,7 @@ import (
"github.com/beclab/Olares/cli/pkg/container"
"github.com/beclab/Olares/cli/pkg/core/module"
"github.com/beclab/Olares/cli/pkg/daemon"
"github.com/beclab/Olares/cli/pkg/gpu"
"github.com/beclab/Olares/cli/pkg/images"
"github.com/beclab/Olares/cli/pkg/k3s"
"github.com/beclab/Olares/cli/pkg/manifest"
@@ -82,6 +82,7 @@ func (l *linuxPhaseBuilder) build() []module.Module {
addModule(&terminus.WriteReleaseFileModule{}).
addModule(gpuModuleBuilder(func() []module.Module {
return []module.Module{
&amdgpu.InstallAmdRocmModule{},
&gpu.InstallDriversModule{
ManifestModule: manifest.ManifestModule{
Manifest: l.manifestMap,

View File

@@ -5,32 +5,26 @@ import (
"os"
"path"
"github.com/beclab/Olares/cli/cmd/ctl/options"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/phase/cluster"
"github.com/pkg/errors"
"github.com/spf13/viper"
)
func AddNodePipeline(opts *options.AddNodeOptions) error {
func AddNodePipeline() error {
arg := common.NewArgument()
if !arg.SystemInfo.IsLinux() {
fmt.Println("error: Only Linux nodes can be added to an Olares cluster!")
os.Exit(1)
}
arg.SetBaseDir(opts.BaseDir)
if opts.Version == "" {
return errors.New("Olares version must be specified")
}
arg.SetOlaresVersion(opts.Version)
if err := arg.LoadMasterHostConfigIfAny(); err != nil {
return errors.Wrap(err, "failed to load master host config")
}
arg.SetMasterHostOverride(opts.MasterHostConfig)
arg.SetOlaresVersion(viper.GetString(common.FlagVersion))
arg.SetConsoleLog("addnode.log", true)
if err := arg.MasterHostConfig.Validate(); err != nil {
return fmt.Errorf("invalid master host config: %w", err)
}
arg.SetConsoleLog("addnode.log", true)
runtime, err := common.NewKubeRuntime(common.AllInOne, *arg)
runtime, err := common.NewKubeRuntime(*arg)
if err != nil {
return fmt.Errorf("error creating runtime: %v", err)
}

101
cli/pkg/pipelines/amdgpu.go Normal file
View File

@@ -0,0 +1,101 @@
package pipelines
import (
"strings"
"github.com/beclab/Olares/cli/pkg/amdgpu"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/core/action"
"github.com/beclab/Olares/cli/pkg/core/connector"
"github.com/beclab/Olares/cli/pkg/core/logger"
"github.com/beclab/Olares/cli/pkg/core/module"
"github.com/beclab/Olares/cli/pkg/core/pipeline"
"github.com/beclab/Olares/cli/pkg/core/task"
)
type singleTaskModule struct {
common.KubeModule
name string
act action.Action
}
func (m *singleTaskModule) Init() {
m.Name = m.name
m.Tasks = []task.Interface{
&task.LocalTask{
Name: m.name,
Action: m.act,
},
}
}
func AmdGpuInstall() error {
arg := common.NewArgument()
arg.SetConsoleLog("amdgpuinstall.log", true)
runtime, err := common.NewKubeRuntime(*arg)
if err != nil {
return err
}
p := &pipeline.Pipeline{
Name: "InstallAMDGPUDrivers",
Runtime: runtime,
Modules: []module.Module{
&amdgpu.InstallAmdRocmModule{},
},
}
return p.Start()
}
func AmdGpuUninstall() error {
arg := common.NewArgument()
arg.SetConsoleLog("amdgpuuninstall.log", true)
runtime, err := common.NewKubeRuntime(*arg)
if err != nil {
return err
}
p := &pipeline.Pipeline{
Name: "UninstallAMDGPUDrivers",
Runtime: runtime,
Modules: []module.Module{
&singleTaskModule{name: "AmdgpuUninstall", act: new(amdgpu.AmdgpuUninstallAction)},
},
}
return p.Start()
}
func AmdGpuStatus() error {
arg := common.NewArgument()
runtime, err := common.NewKubeRuntime(*arg)
if err != nil {
return err
}
runtime.SetRunner(
&connector.Runner{
Host: &connector.BaseHost{
Name: common.LocalHost,
Arch: runtime.GetSystemInfo().GetOsArch(),
Os: runtime.GetSystemInfo().GetOsType(),
},
},
)
amdModel, _ := runtime.GetRunner().SudoCmd("lspci | grep -iE 'VGA|3D|Display' | grep -iE 'AMD|ATI' | head -1 || true", false, false)
drvVer, _ := runtime.GetRunner().SudoCmd("modinfo amdgpu 2>/dev/null | awk -F': ' '/^version:/{print $2}' || true", false, false)
rocmVer, _ := runtime.GetRunner().SudoCmd("cat /opt/rocm/.info/version 2>/dev/null || true", false, false)
if strings.TrimSpace(amdModel) != "" {
logger.Infof("AMD GPU: %s", strings.TrimSpace(amdModel))
} else {
logger.Info("AMD GPU: not detected")
}
if strings.TrimSpace(drvVer) != "" {
logger.Infof("AMDGPU driver %s", strings.TrimSpace(drvVer))
} else {
logger.Info("AMDGPU driver version: unknown")
}
if strings.TrimSpace(rocmVer) != "" {
logger.Infof("ROCm version: %s", strings.TrimSpace(rocmVer))
} else {
logger.Info("ROCm version: not installed")
}
return nil
}

View File

@@ -2,19 +2,16 @@ package pipelines
import (
"fmt"
"net"
"github.com/beclab/Olares/cli/cmd/ctl/options"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/core/logger"
"github.com/beclab/Olares/cli/pkg/core/util"
"github.com/beclab/Olares/cli/pkg/phase"
"github.com/beclab/Olares/cli/pkg/phase/cluster"
"github.com/pkg/errors"
"github.com/spf13/viper"
)
func ChangeIPPipeline(opt *options.ChangeIPOptions) error {
terminusVersion := opt.Version
func ChangeIPPipeline() error {
terminusVersion := viper.GetString(common.FlagVersion)
kubeType := phase.GetKubeType()
if terminusVersion == "" {
terminusVersion, _ = phase.GetOlaresVersion()
@@ -22,29 +19,19 @@ func ChangeIPPipeline(opt *options.ChangeIPOptions) error {
var arg = common.NewArgument()
arg.SetOlaresVersion(terminusVersion)
arg.SetBaseDir(opt.BaseDir)
arg.SetConsoleLog("changeip.log", true)
arg.SetKubeVersion(kubeType)
arg.SetMinikubeProfile(opt.MinikubeProfile)
arg.SetWSLDistribution(opt.WSLDistribution)
if err := arg.LoadMasterHostConfigIfAny(); err != nil {
return errors.Wrap(err, "failed to load master host config")
}
if opt.NewMasterHost != "" {
if ip := net.ParseIP(opt.NewMasterHost); !util.IsValidIPv4Addr(ip) {
return fmt.Errorf("master host %s is not a valid IPv4 address", opt.NewMasterHost)
} else {
arg.MasterHost = opt.NewMasterHost
}
}
//only run validation if it's a worker node with master host config set
arg.SetMinikubeProfile(viper.GetString(common.FlagMiniKubeProfile))
arg.SetWSLDistribution(viper.GetString(common.FlagWSLDistribution))
// Validate master host config only if it's a worker node with master host set
if arg.MasterHost != "" {
if err := arg.MasterHostConfig.Validate(); err != nil {
return fmt.Errorf("invalid master host config: %w", err)
}
}
runtime, err := common.NewKubeRuntime(common.AllInOne, *arg)
runtime, err := common.NewKubeRuntime(*arg)
if err != nil {
return err
}
@@ -56,5 +43,4 @@ func ChangeIPPipeline(opt *options.ChangeIPOptions) error {
}
return nil
}

View File

@@ -3,23 +3,22 @@ package pipelines
import (
"path"
"github.com/beclab/Olares/cli/cmd/ctl/options"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/core/logger"
"github.com/beclab/Olares/cli/pkg/phase/download"
"github.com/spf13/viper"
)
func CheckDownloadInstallationPackage(opts *options.CliDownloadOptions) error {
func CheckDownloadInstallationPackage() error {
arg := common.NewArgument()
arg.SetOlaresVersion(opts.Version)
arg.SetBaseDir(opts.BaseDir)
arg.SetOlaresVersion(viper.GetString(common.FlagVersion))
runtime, err := common.NewKubeRuntime(common.AllInOne, *arg)
runtime, err := common.NewKubeRuntime(*arg)
if err != nil {
return err
}
manifest := opts.Manifest
manifest := viper.GetString(common.FlagManifest)
if manifest == "" {
manifest = path.Join(runtime.GetInstallerDir(), "installation.manifest")
}

View File

@@ -4,30 +4,28 @@ import (
"fmt"
"path"
"github.com/beclab/Olares/cli/cmd/ctl/options"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/core/logger"
"github.com/beclab/Olares/cli/pkg/phase/download"
"github.com/beclab/Olares/cli/pkg/utils"
"github.com/spf13/viper"
)
func DownloadInstallationPackage(opts *options.CliDownloadOptions) error {
func DownloadInstallationPackage() error {
arg := common.NewArgument()
arg.SetBaseDir(opts.BaseDir)
arg.SetKubeVersion(opts.KubeType)
arg.SetOlaresVersion(opts.Version)
arg.SetOlaresCDNService(opts.CDNService)
arg.SetOlaresVersion(viper.GetString(common.FlagVersion))
arg.SetOlaresCDNService(viper.GetString(common.FlagCDNService))
runtime, err := common.NewKubeRuntime(common.AllInOne, *arg)
runtime, err := common.NewKubeRuntime(*arg)
if err != nil {
return err
}
if ok := utils.CheckUrl(arg.OlaresCDNService); !ok {
return fmt.Errorf("--cdn-service invalid")
return fmt.Errorf("invalid cdn service")
}
manifest := opts.Manifest
manifest := viper.GetString(common.FlagManifest)
if manifest == "" {
manifest = path.Join(runtime.GetInstallerDir(), "installation.manifest")
}

View File

@@ -3,30 +3,28 @@ package pipelines
import (
"fmt"
"github.com/beclab/Olares/cli/cmd/ctl/options"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/core/logger"
"github.com/beclab/Olares/cli/pkg/phase/download"
"github.com/beclab/Olares/cli/pkg/utils"
"github.com/spf13/viper"
)
func DownloadInstallationWizard(opts *options.CliDownloadWizardOptions) error {
func DownloadInstallationWizard() error {
arg := common.NewArgument()
arg.SetKubeVersion(opts.KubeType)
arg.SetOlaresVersion(opts.Version)
arg.SetBaseDir(opts.BaseDir)
arg.SetOlaresCDNService(opts.CDNService)
arg.SetOlaresVersion(viper.GetString(common.FlagVersion))
arg.SetOlaresCDNService(viper.GetString(common.FlagCDNService))
runtime, err := common.NewKubeRuntime(common.AllInOne, *arg)
runtime, err := common.NewKubeRuntime(*arg)
if err != nil {
return err
}
if ok := utils.CheckUrl(arg.OlaresCDNService); !ok {
return fmt.Errorf("--cdn-service invalid")
return fmt.Errorf("invalid cdn service")
}
p := download.NewDownloadWizard(runtime, opts.UrlOverride, opts.ReleaseID)
p := download.NewDownloadWizard(runtime, viper.GetString(common.FlagURLOverride), viper.GetString(common.FlagReleaseID))
if err := p.Start(); err != nil {
logger.Errorf("download wizard failed %v", err)
return err

View File

@@ -12,7 +12,7 @@ func DisableGpuNode() error {
arg := common.NewArgument()
arg.SetConsoleLog("gpudisable.log", true)
runtime, err := common.NewKubeRuntime(common.AllInOne, *arg)
runtime, err := common.NewKubeRuntime(*arg)
if err != nil {
return err
}

View File

@@ -11,7 +11,7 @@ func DisableNouveau() error {
arg := common.NewArgument()
arg.SetConsoleLog("gpudisable-nouveau.log", true)
runtime, err := common.NewKubeRuntime(common.AllInOne, *arg)
runtime, err := common.NewKubeRuntime(*arg)
if err != nil {
return err
}
@@ -26,5 +26,3 @@ func DisableNouveau() error {
return p.Start()
}

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