Compare commits

...

67 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
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
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
319 changed files with 5373 additions and 8214 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

@@ -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.7.1
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

View File

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

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

@@ -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,6 +3,7 @@ package os
import (
"archive/tar"
"compress/gzip"
"context"
"fmt"
"io"
"log"
@@ -13,6 +14,9 @@ import (
"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"
@@ -20,6 +24,7 @@ import (
"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
@@ -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
@@ -399,6 +404,126 @@ func collectKubernetesLogs(tw *tar.Writer, options *LogCollectOptions) error {
}
}
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
}
@@ -485,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

@@ -24,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
@@ -37,7 +35,8 @@ 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
@@ -114,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
@@ -171,6 +171,7 @@ require (
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/opencontainers/runtime-spec v1.2.1 // 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
@@ -181,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

View File

@@ -181,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=
@@ -226,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=
@@ -268,8 +268,6 @@ github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2E
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=
@@ -316,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=
@@ -342,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=
@@ -382,6 +376,8 @@ github.com/opencontainers/selinux v1.13.1 h1:A8nNeceYngH9Ow++M+VVEwJVpdFmrlxsN22
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=
@@ -422,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=
@@ -440,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=
@@ -466,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=

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,58 +186,38 @@ 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(withoutName bool) error {
if a.BaseDir == "" {
return errors.New("invalid: empty base directory")
@@ -372,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
}
@@ -411,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
@@ -434,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"
}
}
@@ -467,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())
@@ -530,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)
@@ -546,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

@@ -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") {

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 {
@@ -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

@@ -389,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

@@ -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()
}

View File

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

View File

@@ -3,22 +3,20 @@ 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/core/module"
"github.com/beclab/Olares/cli/pkg/core/pipeline"
"github.com/beclab/Olares/cli/pkg/gpu"
"github.com/beclab/Olares/cli/pkg/manifest"
"github.com/spf13/viper"
)
func InstallGpuDrivers(opt *options.InstallGpuOptions) error {
func InstallGpuDrivers() error {
arg := common.NewArgument()
arg.SetOlaresVersion(opt.Version)
arg.SetCudaVersion(opt.Cuda)
arg.SetBaseDir(opt.BaseDir)
arg.SetOlaresVersion(viper.GetString(common.FlagVersion))
arg.SetConsoleLog("gpuinstall.log", true)
runtime, err := common.NewKubeRuntime(common.AllInOne, *arg)
runtime, err := common.NewKubeRuntime(*arg)
if err != nil {
return err
}

View File

@@ -9,7 +9,7 @@ import (
func GpuDriverStatus() error {
arg := common.NewArgument()
runtime, err := common.NewKubeRuntime(common.AllInOne, *arg)
runtime, err := common.NewKubeRuntime(*arg)
if err != nil {
return err
}

View File

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

View File

@@ -6,36 +6,40 @@ import (
"github.com/pkg/errors"
"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"
"github.com/beclab/Olares/cli/pkg/phase/cluster"
"github.com/spf13/viper"
)
func CliInstallTerminusPipeline(opts *options.CliTerminusInstallOptions) error {
func CliInstallTerminusPipeline() error {
var terminusVersion, _ = phase.GetOlaresVersion()
if terminusVersion != "" {
return errors.New("Olares is already installed, please uninstall it first.")
}
arg := common.NewArgument()
arg.SetBaseDir(opts.BaseDir)
arg.SetKubeVersion(opts.KubeType)
arg.SetOlaresVersion(opts.Version)
arg.SetMinikubeProfile(opts.MiniKubeProfile)
arg.SetStorage(getStorageValueFromEnv())
arg.SetSwapConfig(opts.SwapConfig)
arg.SetKubeVersion(viper.GetString(common.FlagKubeType))
arg.SetOlaresVersion(viper.GetString(common.FlagVersion))
arg.SetMinikubeProfile(viper.GetString(common.FlagMiniKubeProfile))
arg.SetStorage(getStorageConfig())
arg.SetSwapConfig(common.SwapConfig{
EnablePodSwap: viper.GetBool(common.FlagEnablePodSwap),
Swappiness: viper.GetInt(common.FlagSwappiness),
EnableZRAM: viper.GetBool(common.FlagEnableZRAM),
ZRAMSize: viper.GetString(common.FlagZRAMSize),
ZRAMSwapPriority: viper.GetInt(common.FlagZRAMSwapPriority),
})
if err := arg.SwapConfig.Validate(); err != nil {
return err
}
if opts.WithJuiceFS {
arg.WithJuiceFS = true
arg.WithJuiceFS = viper.GetBool(common.FlagEnableJuiceFS)
if viper.IsSet(common.FlagEnableReverseProxy) {
val := viper.GetBool(common.FlagEnableReverseProxy)
arg.NetworkSettings.EnableReverseProxy = &val
}
if opts.EnableReverseProxy != nil {
arg.NetworkSettings.EnableReverseProxy = opts.EnableReverseProxy
}
runtime, err := common.NewKubeRuntime(common.AllInOne, *arg)
runtime, err := common.NewKubeRuntime(*arg)
if err != nil {
return fmt.Errorf("error creating runtime: %v", err)
}

View File

@@ -4,32 +4,25 @@ import (
"fmt"
"os"
"github.com/beclab/Olares/cli/cmd/ctl/options"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/core/module"
"github.com/beclab/Olares/cli/pkg/core/pipeline"
"github.com/beclab/Olares/cli/pkg/terminus"
"github.com/pkg/errors"
)
func MasterInfoPipeline(opts *options.MasterInfoOptions) error {
func MasterInfoPipeline() 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)
arg.SetConsoleLog("masterinfo.log", true)
if err := arg.LoadMasterHostConfigIfAny(); err != nil {
return errors.Wrap(err, "failed to load master host config")
}
arg.SetMasterHostOverride(opts.MasterHostConfig)
if err := arg.MasterHostConfig.Validate(); err != nil {
return fmt.Errorf("invalid master host config: %w", err)
}
arg.SetConsoleLog("masterinfo.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)
}

View File

@@ -1,22 +1,19 @@
package pipelines
import (
"github.com/beclab/Olares/cli/cmd/ctl/options"
"github.com/beclab/Olares/cli/pkg/bootstrap/precheck"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/core/module"
"github.com/beclab/Olares/cli/pkg/core/pipeline"
"github.com/spf13/viper"
)
func StartPreCheckPipeline(opt *options.PreCheckOptions) error {
terminusVersion := opt.Version
func StartPreCheckPipeline() error {
var arg = common.NewArgument()
arg.SetOlaresVersion(terminusVersion)
arg.SetBaseDir(opt.BaseDir)
arg.SetOlaresVersion(viper.GetString(common.FlagVersion))
arg.SetConsoleLog("precheck.log", true)
runtime, err := common.NewKubeRuntime(common.AllInOne, *arg)
runtime, err := common.NewKubeRuntime(*arg)
if err != nil {
return err
}

View File

@@ -3,13 +3,11 @@ package pipelines
import (
"errors"
"fmt"
"os"
"path"
"github.com/beclab/Olares/cli/pkg/core/logger"
"github.com/beclab/Olares/cli/pkg/daemon"
"github.com/beclab/Olares/cli/cmd/ctl/options"
bootstrapos "github.com/beclab/Olares/cli/pkg/bootstrap/os"
"github.com/beclab/Olares/cli/pkg/bootstrap/patch"
"github.com/beclab/Olares/cli/pkg/common"
@@ -20,23 +18,22 @@ import (
"github.com/beclab/Olares/cli/pkg/manifest"
"github.com/beclab/Olares/cli/pkg/phase"
"github.com/beclab/Olares/cli/pkg/phase/system"
"github.com/spf13/viper"
)
func PrepareSystemPipeline(opts *options.CliPrepareSystemOptions, components []string) error {
func PrepareSystemPipeline(components []string) error {
var terminusVersion, _ = phase.GetOlaresVersion()
if terminusVersion != "" && len(components) == 0 {
return errors.New("Olares is already installed, please uninstall it first.")
}
var arg = common.NewArgument()
arg.SetBaseDir(opts.BaseDir)
arg.SetKubeVersion(opts.KubeType)
arg.SetMinikubeProfile(opts.MinikubeProfile)
arg.SetOlaresVersion(opts.Version)
arg.SetRegistryMirrors(opts.RegistryMirrors)
arg.SetStorage(getStorageValueFromEnv())
arg.SetKubeVersion(viper.GetString(common.FlagKubeType))
arg.SetMinikubeProfile(viper.GetString(common.FlagMiniKubeProfile))
arg.SetOlaresVersion(viper.GetString(common.FlagVersion))
arg.SetStorage(getStorageConfig())
runtime, err := common.NewKubeRuntime(common.AllInOne, *arg)
runtime, err := common.NewKubeRuntime(*arg)
if err != nil {
return fmt.Errorf("error creating runtime: %w", err)
}
@@ -133,24 +130,3 @@ func PrepareSystemPipeline(opts *options.CliPrepareSystemOptions, components []s
return nil
}
func getStorageValueFromEnv() *common.Storage {
storageType := os.Getenv(common.ENV_STORAGE)
switch storageType {
case "":
storageType = common.ManagedMinIO
}
return &common.Storage{
StorageType: storageType,
StorageBucket: os.Getenv(common.ENV_S3_BUCKET),
StoragePrefix: os.Getenv(common.ENV_BACKUP_KEY_PREFIX),
StorageAccessKey: os.Getenv(common.ENV_AWS_ACCESS_KEY_ID_SETUP),
StorageSecretKey: os.Getenv(common.ENV_AWS_SECRET_ACCESS_KEY_SETUP),
StorageToken: os.Getenv(common.ENV_AWS_SESSION_TOKEN_SETUP),
StorageClusterId: os.Getenv(common.ENV_CLUSTER_ID),
StorageSyncSecret: os.Getenv(common.ENV_BACKUP_SECRET),
StorageVendor: os.Getenv(common.ENV_TERMINUS_IS_CLOUD_VERSION),
BackupClusterBucket: os.Getenv(common.ENV_BACKUP_CLUSTER_BUCKET),
}
}

View File

@@ -12,7 +12,7 @@ import (
func StartOlares() error {
arg := common.NewArgument()
arg.SetConsoleLog("start.log", true)
runtime, err := common.NewKubeRuntime(common.AllInOne, *arg)
runtime, err := common.NewKubeRuntime(*arg)
if err != nil {
return err
}
@@ -31,7 +31,7 @@ func StartOlares() error {
func StopOlares(timeout, checkInterval time.Duration) error {
arg := common.NewArgument()
arg.SetConsoleLog("stop.log", true)
runtime, err := common.NewKubeRuntime(common.AllInOne, *arg)
runtime, err := common.NewKubeRuntime(*arg)
if err != nil {
return err
}

View File

@@ -4,25 +4,24 @@ import (
"fmt"
"path"
"github.com/beclab/Olares/cli/cmd/ctl/options"
"github.com/beclab/Olares/cli/pkg/common"
"github.com/beclab/Olares/cli/pkg/phase"
"github.com/beclab/Olares/cli/pkg/phase/system"
"github.com/pkg/errors"
"github.com/spf13/viper"
)
func CliInstallStoragePipeline(opts *options.InstallStorageOptions) error {
func CliInstallStoragePipeline() error {
var terminusVersion, _ = phase.GetOlaresVersion()
if terminusVersion != "" {
return errors.New("Olares is already installed, please uninstall it first.")
}
arg := common.NewArgument()
arg.SetBaseDir(opts.BaseDir)
arg.SetOlaresVersion(opts.Version)
arg.SetStorage(getStorageValueFromEnv())
arg.SetOlaresVersion(viper.GetString(common.FlagVersion))
arg.SetStorage(getStorageConfig())
runtime, err := common.NewKubeRuntime(common.AllInOne, *arg)
runtime, err := common.NewKubeRuntime(*arg)
if err != nil {
return fmt.Errorf("error creating runtime: %v", err)
}
@@ -32,3 +31,22 @@ func CliInstallStoragePipeline(opts *options.InstallStorageOptions) error {
return system.InstallStoragePipeline(runtime).Start()
}
func getStorageConfig() *common.Storage {
storageType := viper.GetString(common.FlagStorageType)
if storageType == "" {
storageType = common.ManagedMinIO
}
return &common.Storage{
StorageType: storageType,
StorageBucket: viper.GetString(common.FlagS3Bucket),
StoragePrefix: viper.GetString(common.FlagBackupKeyPrefix),
StorageAccessKey: viper.GetString(common.FlagAWSAccessKeyIDSetup),
StorageSecretKey: viper.GetString(common.FlagAWSSecretAccessKeySetup),
StorageToken: viper.GetString(common.FlagAWSSessionTokenSetup),
StorageClusterId: viper.GetString(common.FlagClusterID),
StorageSyncSecret: viper.GetString(common.FlagBackupSecret),
StorageVendor: viper.GetString(common.FlagIsCloudVersion),
BackupClusterBucket: viper.GetString(common.FlagBackupClusterBucket),
}
}

View File

@@ -2,50 +2,45 @@ package pipelines
import (
"fmt"
"os"
"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"
"github.com/beclab/Olares/cli/pkg/phase/cluster"
"github.com/spf13/viper"
)
func UninstallTerminusPipeline(opt *options.CliTerminusUninstallOptions) error {
terminusVersion := opt.Version
func UninstallTerminusPipeline() error {
version := viper.GetString(common.FlagVersion)
kubeType := phase.GetKubeType()
if terminusVersion == "" {
terminusVersion, _ = phase.GetOlaresVersion()
if version == "" {
version, _ = phase.GetOlaresVersion()
}
var arg = common.NewArgument()
arg.SetOlaresVersion(terminusVersion)
arg.SetBaseDir(opt.BaseDir)
arg.SetOlaresVersion(version)
arg.SetConsoleLog("uninstall.log", true)
arg.SetKubeVersion(kubeType)
arg.SetDeleteCRI(opt.All || (opt.Phase == cluster.PhasePrepare.String() || opt.Phase == cluster.PhaseDownload.String()))
arg.SetStorage(&common.Storage{
StorageVendor: os.Getenv(common.ENV_TERMINUS_IS_CLOUD_VERSION),
StorageType: os.Getenv(common.ENV_STORAGE),
StorageBucket: os.Getenv(common.ENV_S3_BUCKET),
})
arg.SetStorage(getStorageConfig())
if err := checkPhase(opt.Phase, opt.All, arg.SystemInfo.GetOsType()); err != nil {
phase := viper.GetString(common.FlagUninstallPhase)
all := viper.GetBool(common.FlagUninstallAll)
if err := checkPhase(phase, all, arg.SystemInfo.GetOsType()); err != nil {
return err
}
runtime, err := common.NewKubeRuntime(common.AllInOne, *arg)
runtime, err := common.NewKubeRuntime(*arg)
if err != nil {
return err
}
phaseName := opt.Phase
if opt.All {
phaseName = cluster.PhaseDownload.String()
if all {
phase = cluster.PhaseDownload.String()
}
var p = cluster.UninstallTerminus(phaseName, runtime)
var p = cluster.UninstallTerminus(phase, runtime)
if err := p.Start(); err != nil {
logger.Errorf("uninstall Olares failed: %v", err)
return err

View File

@@ -2,12 +2,13 @@ package pipelines
import (
"fmt"
"path"
"github.com/beclab/Olares/cli/pkg/upgrade"
"github.com/beclab/Olares/cli/pkg/utils"
"github.com/beclab/Olares/cli/version"
"path"
"github.com/spf13/viper"
"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/module"
@@ -16,7 +17,7 @@ import (
"github.com/pkg/errors"
)
func UpgradeOlaresPipeline(opts *options.UpgradeOptions) error {
func UpgradeOlaresPipeline() error {
currentVersionString, err := phase.GetOlaresVersion()
if err != nil {
return errors.Wrap(err, "failed to get current Olares version")
@@ -31,10 +32,11 @@ func UpgradeOlaresPipeline(opts *options.UpgradeOptions) error {
// should only be and defaults to the current cli version
// this argument is for backwards-compatibility with older olaresd
if opts.Version == "" {
opts.Version = version.VERSION
targetVersionStr := viper.GetString(common.FlagVersion)
if targetVersionStr == "" {
targetVersionStr = version.VERSION
}
targetVersion, err := utils.ParseOlaresVersionString(opts.Version)
targetVersion, err := utils.ParseOlaresVersionString(targetVersionStr)
if err != nil {
return fmt.Errorf("error parsing target Olares version: %v", err)
}
@@ -44,12 +46,11 @@ func UpgradeOlaresPipeline(opts *options.UpgradeOptions) error {
}
arg := common.NewArgument()
arg.SetBaseDir(opts.BaseDir)
arg.SetOlaresVersion(opts.Version)
arg.SetOlaresVersion(viper.GetString(common.FlagVersion))
arg.SetConsoleLog("upgrade.log", true)
arg.SetKubeVersion(phase.GetKubeType())
runtime, err := common.NewKubeRuntime(common.AllInOne, *arg)
runtime, err := common.NewKubeRuntime(*arg)
if err != nil {
return fmt.Errorf("error creating runtime: %v", err)
}
@@ -67,7 +68,7 @@ func UpgradeOlaresPipeline(opts *options.UpgradeOptions) error {
Runtime: runtime,
}
logger.Infof("Starting Olares upgrade from %s to %s...", currentVersion, opts.Version)
logger.Infof("Starting Olares upgrade from %s to %s...", currentVersion, targetVersion)
if err := p.Start(); err != nil {
return errors.Wrap(err, "upgrade failed")
}
@@ -80,7 +81,7 @@ func UpgradePreCheckPipeline() error {
var arg = common.NewArgument()
arg.SetConsoleLog("upgrade-precheck.log", true)
runtime, err := common.NewKubeRuntime(common.AllInOne, *arg)
runtime, err := common.NewKubeRuntime(*arg)
if err != nil {
return err
}

View File

@@ -30,11 +30,6 @@ import (
type DeployLocalVolumeModule struct {
common.KubeModule
Skip bool
}
func (d *DeployLocalVolumeModule) IsSkip() bool {
return d.Skip
}
func (d *DeployLocalVolumeModule) Init() {

View File

@@ -396,3 +396,17 @@ func (t *DeleteTerminusData) Execute(runtime connector.Runtime) error {
return nil
}
type CreateSharedLibDir struct {
common.KubeAction
}
func (t *CreateSharedLibDir) Execute(runtime connector.Runtime) error {
if runtime.GetSystemInfo().IsDarwin() {
return nil
}
if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("mkdir -p %s && chown 1000:1000 %s", OlaresSharedLibDir, OlaresSharedLibDir), false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "failed to create shared lib dir")
}
return nil
}

View File

@@ -33,13 +33,13 @@ type ValidateStorageConfig struct {
func (a *ValidateStorageConfig) Execute(runtime connector.Runtime) error {
storageConf := a.KubeConf.Arg.Storage
if storageConf.StorageBucket == "" {
return fmt.Errorf("missing storage bucket, please set it in env %s", common.ENV_S3_BUCKET)
return fmt.Errorf("missing storage bucket")
}
if storageConf.StorageAccessKey == "" {
return fmt.Errorf("missing storage access key, please set it in env %s", common.ENV_AWS_ACCESS_KEY_ID_SETUP)
return fmt.Errorf("missing storage access key")
}
if storageConf.StorageSecretKey == "" {
return fmt.Errorf("missing storage secret key, please set it in env %s", common.ENV_AWS_SECRET_ACCESS_KEY_SETUP)
return fmt.Errorf("missing storage secret key")
}
return nil
}

View File

@@ -30,20 +30,16 @@ type GetUserInfo struct {
func (s *GetUserInfo) Execute(runtime connector.Runtime) error {
var err error
if len(s.KubeConf.Arg.User.DomainName) == 0 {
s.KubeConf.Arg.User.DomainName, err = s.getDomainName()
if err != nil {
return err
}
logger.Infof("using Domain Name: %s", s.KubeConf.Arg.User.DomainName)
s.KubeConf.Arg.User.DomainName, err = s.getDomainName()
if err != nil {
return err
}
if len(s.KubeConf.Arg.User.UserName) == 0 {
s.KubeConf.Arg.User.UserName, err = s.getUserName()
if err != nil {
return err
}
logger.Infof("using Olares Local Name: %s", s.KubeConf.Arg.User.UserName)
logger.Infof("using Domain Name: %s", s.KubeConf.Arg.User.DomainName)
s.KubeConf.Arg.User.UserName, err = s.getUserName()
if err != nil {
return err
}
logger.Infof("using Olares Local Name: %s", s.KubeConf.Arg.User.UserName)
s.KubeConf.Arg.User.Email, err = s.getUserEmail()
if err != nil {
return err
@@ -53,16 +49,20 @@ func (s *GetUserInfo) Execute(runtime connector.Runtime) error {
if err != nil {
return err
}
logger.Infof("using password: %s", s.KubeConf.Arg.User.Password)
if s.KubeConf.Arg.User.Password != "" {
logger.Infof("using password: %s", s.KubeConf.Arg.User.Password)
} else {
logger.Infof("using already encrypted password")
}
return nil
}
func (s *GetUserInfo) getDomainName() (string, error) {
domainName := strings.TrimSpace(os.Getenv("TERMINUS_OS_DOMAINNAME"))
domainName := s.KubeConf.Arg.User.DomainName
if len(domainName) > 0 {
if !utils.IsValidDomain(domainName) {
return "", errors.New(fmt.Sprintf("invalid domain name \"%s\" set in env, please reset", domainName))
return "", errors.New(fmt.Sprintf("invalid domain name \"%s\", please reset", domainName))
}
return domainName, nil
}
@@ -90,14 +90,14 @@ LOOP:
}
func (s *GetUserInfo) getUserName() (string, error) {
userName := os.Getenv("TERMINUS_OS_USERNAME")
userName := s.KubeConf.Arg.User.UserName
if strings.Contains(userName, "@") {
userName = strings.Split(userName, "@")[0]
}
userName = strings.TrimSpace(userName)
if len(userName) > 0 {
if err := utils.ValidateUserName(userName); err != nil {
return "", fmt.Errorf("invalid username \"%s\" set in env: %s, please reset", userName, err.Error())
return "", fmt.Errorf("invalid username \"%s\": %s, please reset", userName, err.Error())
}
return userName, nil
}
@@ -135,15 +135,23 @@ func (s *GetUserInfo) getUserEmail() (string, error) {
}
func (s *GetUserInfo) getUserPassword() (string, string, error) {
userPassword := strings.TrimSpace(os.Getenv("TERMINUS_OS_PASSWORD"))
if len(userPassword) != 32 && len(userPassword) != 0 {
return "", "", fmt.Errorf("invalid password \"%s\" set in env: length should be equal 32, please reset", userPassword)
// currently only used in the installation flow by LarePass -> Olaresd,
// when this env var is passed in, it is already encrypted
// make this one priority over the password set in the arg specailly
// to ensure the larepass installation flow works as expected
encryptedPassword := strings.TrimSpace(os.Getenv(common.EnvLegacyEncryptedOSPassword))
if len(encryptedPassword) != 32 && len(encryptedPassword) != 0 {
return "", "", fmt.Errorf("invalid password \"%s\" set in env: length should be equal 32, please reset", encryptedPassword)
}
if len(userPassword) == 0 {
return utils.GenerateEncryptedPassword(8)
if len(encryptedPassword) == 0 {
if s.KubeConf.Arg.User.Password != "" {
return s.KubeConf.Arg.User.Password, utils.EncryptPassword(s.KubeConf.Arg.User.Password), nil
} else {
return utils.GenerateEncryptedPassword(8)
}
}
return userPassword, userPassword, nil
return "", encryptedPassword, nil
}
type SetAccountValues struct {

View File

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

View File

@@ -38,12 +38,6 @@ type InstallOsSystem struct {
}
func (t *InstallOsSystem) Execute(runtime connector.Runtime) error {
if !runtime.GetSystemInfo().IsDarwin() {
if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("mkdir -p %s && chown 1000:1000 %s", storage.OlaresSharedLibDir, storage.OlaresSharedLibDir), false, false); err != nil {
return errors.Wrap(errors.WithStack(err), "failed to create shared lib dir")
}
}
config, err := ctrl.GetConfig()
if err != nil {
return err
@@ -367,6 +361,11 @@ func (m *InstallOsSystemModule) Init() {
Action: &CreateUserEnvConfigMap{},
}
createSharedLibDir := &task.LocalTask{
Name: "CreateSharedLibDir",
Action: &storage.CreateSharedLibDir{},
}
installOsSystem := &task.LocalTask{
Name: "InstallOsSystem",
Action: &InstallOsSystem{},
@@ -399,6 +398,7 @@ func (m *InstallOsSystemModule) Init() {
m.Tasks = []task.Interface{
applySystemEnv,
createUserEnvConfigMap,
createSharedLibDir,
installOsSystem,
createBackupConfigMap,
checkSystemService,

View File

@@ -9,6 +9,7 @@ import (
"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"
)
type WelcomeMessage struct {
@@ -68,6 +69,15 @@ func (t *WelcomeMessage) Execute(runtime connector.Runtime) error {
logger.Infof("Username: %s", t.KubeConf.Arg.User.UserName)
logger.Infof("Password: %s", t.KubeConf.Arg.User.Password)
fmt.Printf("\n------------------------------------------------\n\n\n\n\n")
fmt.Println()
// If AMD GPU on Ubuntu 22.04/24.04, print warning about reboot for ROCm
if si := runtime.GetSystemInfo(); si.IsUbuntu() && (si.IsUbuntuVersionEqual(connector.Ubuntu2204) || si.IsUbuntuVersionEqual(connector.Ubuntu2404)) {
if hasAmd, _ := utils.HasAmdIGPU(runtime); hasAmd {
logger.Warnf("\x1b[31mWarning: To enable ROCm, please reboot your machine after activation.\x1b[0m")
fmt.Println()
}
}
return nil
}

View File

@@ -0,0 +1,32 @@
package upgrade
import (
"time"
"github.com/Masterminds/semver/v3"
"github.com/beclab/Olares/cli/pkg/core/task"
)
type upgrader_1_12_6_20260122 struct {
breakingUpgraderBase
}
func (u upgrader_1_12_6_20260122) Version() *semver.Version {
return semver.MustParse("1.12.6-20260122")
}
func (u upgrader_1_12_6_20260122) UpgradeSystemComponents() []task.Interface {
pre := []task.Interface{
&task.LocalTask{
Name: "UpgradeL4BFLProxy",
Action: &upgradeL4BFLProxy{Tag: "v0.3.10"},
Retry: 3,
Delay: 5 * time.Second,
},
}
return append(pre, u.upgraderBase.UpgradeSystemComponents()...)
}
func init() {
registerDailyUpgrader(upgrader_1_12_6_20260122{})
}

67
cli/pkg/utils/amdgpu.go Normal file
View File

@@ -0,0 +1,67 @@
package utils
import (
"fmt"
"os"
"strings"
"github.com/Masterminds/semver/v3"
"github.com/beclab/Olares/cli/pkg/core/connector"
)
func HasAmdIGPU(execRuntime connector.Runtime) (bool, error) {
// Detect by CPU model names that bundle AMD AI NPU/graphics
targets := []string{
"AMD Ryzen AI Max+ 395",
"AMD Ryzen AI Max 390",
"AMD Ryzen AI Max 385",
"AMD Ryzen AI 9 HX 375",
"AMD Ryzen AI 9 HX 370",
"AMD Ryzen AI 9 365",
}
// try lscpu first: extract 'Model name' field
out, err := execRuntime.GetRunner().SudoCmd("lscpu 2>/dev/null | awk -F': *' '/^Model name/{print $2; exit}' || true", false, false)
if err != nil {
return false, err
}
if out != "" {
lo := strings.ToLower(strings.TrimSpace(out))
for _, t := range targets {
if strings.Contains(lo, strings.ToLower(t)) {
return true, nil
}
}
}
// fallback to /proc/cpuinfo
out, err = execRuntime.GetRunner().SudoCmd("awk -F': *' '/^model name/{print $2; exit}' /proc/cpuinfo 2>/dev/null || true", false, false)
if err != nil {
return false, err
}
if out != "" {
lo := strings.ToLower(strings.TrimSpace(out))
for _, t := range targets {
if strings.Contains(lo, strings.ToLower(t)) {
return true, nil
}
}
}
return false, nil
}
func RocmVersion() (*semver.Version, error) {
const rocmVersionFile = "/opt/rocm/.info/version"
data, err := os.ReadFile(rocmVersionFile)
if err != nil {
// no ROCm installed, nothing to check
if os.IsNotExist(err) {
return nil, err
}
return nil, err
}
curStr := strings.TrimSpace(string(data))
cur, err := semver.NewVersion(curStr)
if err != nil {
return nil, fmt.Errorf("invalid rocm version: %s", curStr)
}
return cur, nil
}

View File

@@ -224,7 +224,11 @@ func GenerateEncryptedPassword(length int) (string, string, error) {
if err != nil {
return "", "", err
}
return plainText, utils.MD5(plainText + "@Olares2025"), nil
return plainText, EncryptPassword(plainText), nil
}
func EncryptPassword(plainText string) string {
return utils.MD5(plainText + "@Olares2025")
}
func RemoveAnsiCodes(input string) string {
@@ -321,3 +325,54 @@ func GetBufIOReaderOfTerminalInput() (*bufio.Reader, error) {
}
return bufio.NewReader(tty), nil
}
// ResolveSudoUserHomeAndIDs resolves the home directory, uid, and gid for the user
// who invoked sudo. If not running under sudo, it falls back to the current user.
// This is useful for commands that need to operate on the invoking user's home
// directory rather than /root when running with sudo.
func ResolveSudoUserHomeAndIDs(runtime connector.Runtime) (home, uid, gid string, err error) {
uid, err = runtime.GetRunner().Cmd("echo ${SUDO_UID:-}", false, false)
if err != nil {
return "", "", "", errors.Wrap(errors.WithStack(err), "get SUDO_UID failed")
}
gid, err = runtime.GetRunner().Cmd("echo ${SUDO_GID:-}", false, false)
if err != nil {
return "", "", "", errors.Wrap(errors.WithStack(err), "get SUDO_GID failed")
}
uid = strings.TrimSpace(uid)
gid = strings.TrimSpace(gid)
if uid == "" {
uid, err = runtime.GetRunner().Cmd("id -u", false, false)
if err != nil {
return "", "", "", errors.Wrap(errors.WithStack(err), "get current uid failed")
}
gid, err = runtime.GetRunner().Cmd("id -g", false, false)
if err != nil {
return "", "", "", errors.Wrap(errors.WithStack(err), "get current gid failed")
}
uid = strings.TrimSpace(uid)
gid = strings.TrimSpace(gid)
}
home, err = runtime.GetRunner().Cmd(fmt.Sprintf(`getent passwd %s | awk -F: 'NR==1{print $6; exit}'`, uid), false, false)
if err != nil {
home = ""
}
home = strings.TrimSpace(home)
if home == "" {
home, _ = runtime.GetRunner().Cmd(fmt.Sprintf(`awk -F: -v uid=%s '$3==uid {print $6; exit}' /etc/passwd 2>/dev/null`, uid), false, false)
home = strings.TrimSpace(home)
}
if home == "" {
home, err = runtime.GetRunner().Cmd("echo $HOME", false, false)
if err != nil {
return "", "", "", errors.Wrap(errors.WithStack(err), "get HOME failed")
}
home = strings.TrimSpace(home)
}
if home == "" {
return "", "", "", errors.New("resolve user home failed")
}
return home, uid, gid, nil
}

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