Compare commits
14 Commits
cli/fix/ch
...
feat/sort-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
833d480466 | ||
|
|
4ed649bff7 | ||
|
|
e383c22fe5 | ||
|
|
ce15e2ce00 | ||
|
|
957dff10a6 | ||
|
|
da35df9280 | ||
|
|
14edf88acb | ||
|
|
939a9b5ba3 | ||
|
|
3bd0705742 | ||
|
|
6662923b87 | ||
|
|
f39fec6c68 | ||
|
|
e1362a43f7 | ||
|
|
6ec7f214cb | ||
|
|
543328fa6e |
29
.github/workflows/module_kubesphere_build_main.yaml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
name: Kubesphere Build Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "module-kubesphere"
|
||||
paths:
|
||||
- 'infrastructure/kubesphere/**'
|
||||
- '!infrastructure/kubesphere/.olares/**'
|
||||
- '!infrastructure/kubesphere/README.md'
|
||||
pull_request:
|
||||
branches:
|
||||
- "module-kubesphere"
|
||||
paths:
|
||||
- 'infrastructure/kubesphere/**'
|
||||
- '!infrastructure/kubesphere/.olares/**'
|
||||
- '!infrastructure/kubesphere/README.md'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.24'
|
||||
- run: make binary
|
||||
working-directory: infrastructure/kubesphere
|
||||
36
.github/workflows/module_kubesphere_publish_docker.yaml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
name: Publish Kubesphere to Dockerhub
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tags:
|
||||
description: 'Release Tags'
|
||||
|
||||
jobs:
|
||||
publish_dockerhub:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
push: true
|
||||
tags: beclab/ks-apiserver:${{ github.event.inputs.tags }}
|
||||
file: infrastructure/kubesphere/build/ks-apiserver/Dockerfile
|
||||
context: infrastructure/kubesphere
|
||||
platforms: linux/amd64,linux/arm64
|
||||
@@ -318,7 +318,7 @@ spec:
|
||||
chown -R 1000:1000 /uploadstemp && \
|
||||
chown -R 1000:1000 /appdata
|
||||
- name: olares-app-init
|
||||
image: beclab/system-frontend:v1.6.22
|
||||
image: beclab/system-frontend:v1.6.23
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- /bin/sh
|
||||
@@ -440,7 +440,7 @@ spec:
|
||||
- name: NATS_SUBJECT_VAULT
|
||||
value: os.vault.{{ .Values.bfl.username}}
|
||||
- name: user-service
|
||||
image: beclab/user-service:v0.0.77
|
||||
image: beclab/user-service:v0.0.78
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
|
||||
@@ -17,7 +17,7 @@ for mod in "${PACKAGE_MODULE[@]}";do
|
||||
chart_path="${mod}/${app}"
|
||||
|
||||
if [ -d $chart_path ]; then
|
||||
find $chart_path -type f -name *.yaml | while read p; do
|
||||
find $chart_path -type f -path '*/.olares/*.yaml' | while read p; do
|
||||
bash ${BASE_DIR}/yaml2prop.sh -f $p | while read l;do
|
||||
if [[ "$l" == *".image = "* || "$l" == "output.containers."*".name"* ]]; then
|
||||
echo "$l"
|
||||
|
||||
@@ -25,7 +25,6 @@ const (
|
||||
DefaultK3sVersion = "v1.33.3-k3s"
|
||||
DefaultKubernetesVersion = ""
|
||||
DefaultKubeSphereVersion = "v3.3.0"
|
||||
DefaultTokenMaxAge = 31536000
|
||||
CurrentVerifiedCudaVersion = "13.0"
|
||||
)
|
||||
|
||||
@@ -236,7 +235,6 @@ const (
|
||||
CacheNodeNum = "node_num"
|
||||
CacheRedisPassword = "redis_password"
|
||||
CacheSecretsNum = "secrets_num"
|
||||
CacheJwtSecret = "jwt_secret"
|
||||
CacheCrdsNUm = "users_iam_num"
|
||||
|
||||
CacheMinioPath = "minio_binary_path"
|
||||
@@ -295,7 +293,6 @@ const (
|
||||
ENV_BACKUP_SECRET = "BACKUP_SECRET"
|
||||
ENV_CLUSTER_ID = "CLUSTER_ID"
|
||||
ENV_BACKUP_CLUSTER_BUCKET = "BACKUP_CLUSTER_BUCKET"
|
||||
ENV_TOKEN_MAX_AGE = "TOKEN_MAX_AGE"
|
||||
ENV_HOST_IP = "HOST_IP"
|
||||
ENV_PREINSTALL = "PREINSTALL"
|
||||
ENV_DISABLE_HOST_IP_PROMPT = "DISABLE_HOST_IP_PROMPT"
|
||||
|
||||
@@ -101,7 +101,6 @@ type Argument struct {
|
||||
Storage *Storage `json:"storage"`
|
||||
NetworkSettings *NetworkSettings `json:"network_settings"`
|
||||
GPU *GPU `json:"gpu"`
|
||||
TokenMaxAge int64 `json:"token_max_age"` // nanosecond
|
||||
|
||||
Request any `json:"-"`
|
||||
|
||||
@@ -353,15 +352,6 @@ func (a *Argument) SetOlaresCDNService(url string) {
|
||||
a.OlaresCDNService = u
|
||||
}
|
||||
|
||||
func (a *Argument) SetTokenMaxAge() {
|
||||
s := os.Getenv(ENV_TOKEN_MAX_AGE)
|
||||
age, err := strconv.ParseInt(s, 10, 64)
|
||||
if err != nil || age == 0 {
|
||||
age = DefaultTokenMaxAge
|
||||
}
|
||||
a.TokenMaxAge = age
|
||||
}
|
||||
|
||||
func (a *Argument) SetGPU(enable bool) {
|
||||
if a.GPU == nil {
|
||||
a.GPU = new(GPU)
|
||||
|
||||
@@ -6,9 +6,9 @@ const (
|
||||
NamespaceKubePublic = "kube-public"
|
||||
NamespaceKubeSystem = "kube-system"
|
||||
NamespaceKubekeySystem = "kubekey-system"
|
||||
NamespaceKubesphereControlsSystem = "kubesphere-controls-system"
|
||||
NamespaceKubesphereMonitoringSystem = "kubesphere-monitoring-system"
|
||||
NamespaceKubesphereSystem = "kubesphere-system"
|
||||
NamespaceKubesphereControlsSystem = "kubesphere-controls-system"
|
||||
NamespaceOsFramework = "os-framework"
|
||||
NamespaceOsPlatform = "os-platform"
|
||||
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/beclab/Olares/cli/pkg/core/connector"
|
||||
"github.com/beclab/Olares/cli/pkg/core/prepare"
|
||||
"github.com/beclab/Olares/cli/pkg/core/util"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type Skip struct {
|
||||
KubePrepare
|
||||
Not bool
|
||||
}
|
||||
|
||||
func (p *Skip) PreCheck(runtime connector.Runtime) (bool, error) {
|
||||
return !p.Not, nil
|
||||
}
|
||||
|
||||
type Stop struct {
|
||||
prepare.BasePrepare
|
||||
}
|
||||
|
||||
func (p *Stop) PreCheck(runtime connector.Runtime) (bool, error) {
|
||||
return true, nil
|
||||
// return false, fmt.Errorf("STOP !!!!!!")
|
||||
}
|
||||
|
||||
type GetCommandKubectl struct {
|
||||
prepare.BasePrepare
|
||||
}
|
||||
|
||||
func (p *GetCommandKubectl) PreCheck(runtime connector.Runtime) (bool, error) {
|
||||
|
||||
cmd, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("command -v %s", CommandKubectl), false, false)
|
||||
if err != nil {
|
||||
return true, nil
|
||||
}
|
||||
if cmd != "" {
|
||||
p.PipelineCache.Set(CacheKubectlKey, cmd)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
type GetMasterNum struct {
|
||||
prepare.BasePrepare
|
||||
}
|
||||
|
||||
func (p *GetMasterNum) PreCheck(runtime connector.Runtime) (bool, error) {
|
||||
var kubectlpath, err = util.GetCommand(CommandKubectl)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("kubectl not found")
|
||||
}
|
||||
|
||||
var cmd = fmt.Sprintf("%s get node | awk '{if(NR>1){print $3}}' | grep master | wc -l", kubectlpath)
|
||||
stdout, err := runtime.GetRunner().SudoCmd(cmd, false, false)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(errors.WithStack(err), "get master num failed")
|
||||
}
|
||||
|
||||
masterNum, _ := strconv.ParseInt(stdout, 10, 64)
|
||||
|
||||
p.PipelineCache.Set(CacheMasterNum, masterNum)
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
type GetNodeNum struct {
|
||||
prepare.BasePrepare
|
||||
}
|
||||
|
||||
func (p *GetNodeNum) PreCheck(runtime connector.Runtime) (bool, error) {
|
||||
var kubectlpath, err = util.GetCommand(CommandKubectl)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("kubectl not found")
|
||||
}
|
||||
|
||||
var cmd = fmt.Sprintf("%s get node | wc -l", kubectlpath)
|
||||
stdout, err := runtime.GetRunner().SudoCmd(cmd, false, false)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(errors.WithStack(err), "get node num failed")
|
||||
}
|
||||
|
||||
nodeNum, _ := strconv.ParseInt(stdout, 10, 64)
|
||||
|
||||
p.PipelineCache.Set(CacheNodeNum, nodeNum)
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
type ClusterType struct {
|
||||
KubePrepare
|
||||
ClusterType string
|
||||
Not bool
|
||||
}
|
||||
|
||||
func (p *ClusterType) PreCheck(runtime connector.Runtime) (bool, error) {
|
||||
if p.KubeConf == nil || p.KubeConf.Cluster == nil {
|
||||
return false, nil
|
||||
}
|
||||
var isK3s = p.KubeConf.Cluster.Kubernetes.Type == p.ClusterType
|
||||
if p.Not {
|
||||
return !isK3s, nil
|
||||
}
|
||||
|
||||
return isK3s, nil
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var header = JWTHeader{
|
||||
Alg: "HS256",
|
||||
Typ: "JWT",
|
||||
}
|
||||
|
||||
var payload = JWTPayload{
|
||||
Email: "admin@kubesphere.io",
|
||||
Username: "admin",
|
||||
TokenType: "static_token",
|
||||
}
|
||||
|
||||
type JWTHeader struct {
|
||||
Alg string `json:"alg"`
|
||||
Typ string `json:"typ"`
|
||||
}
|
||||
|
||||
type JWTPayload struct {
|
||||
Email string `json:"email"`
|
||||
Username string `json:"username"`
|
||||
TokenType string `json:"token_type"`
|
||||
}
|
||||
|
||||
func EncryptToken(secret string) (string, error) {
|
||||
headerJson, _ := json.Marshal(header)
|
||||
headerBase64 := Base64URLEncode(headerJson)
|
||||
|
||||
payloadJson, _ := json.Marshal(payload)
|
||||
payloadBase64 := Base64URLEncode(payloadJson)
|
||||
|
||||
headerPayload := fmt.Sprintf("%s.%s", headerBase64, payloadBase64)
|
||||
|
||||
var secretBytes = []byte(secret)
|
||||
|
||||
signature := HMACSHA256([]byte(headerPayload), secretBytes)
|
||||
|
||||
// Encode the signature to base64 URL encoding.
|
||||
signatureBase64 := Base64URLEncode(signature)
|
||||
|
||||
return fmt.Sprintf("%s.%s", headerPayload, signatureBase64), nil
|
||||
}
|
||||
|
||||
func Base64URLEncode(data []byte) string {
|
||||
return strings.TrimRight(base64.URLEncoding.EncodeToString(data), "=")
|
||||
|
||||
}
|
||||
|
||||
// HMACSHA256 signs a message using a secret key with HMAC SHA256.
|
||||
func HMACSHA256(message, secret []byte) []byte {
|
||||
h := hmac.New(sha256.New, secret)
|
||||
h.Write(message)
|
||||
return h.Sum(nil)
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestToken(t *testing.T) {
|
||||
var a = "n7X2dggXApH91fnVUzgPr1Fr1vAO0Upo"
|
||||
// var b = `{"email": "admin@kubesphere.io","username": "admin","token_type": "static_token"}`
|
||||
|
||||
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImFkbWluQGt1YmVzcGhlcmUuaW8iLCJ1c2VybmFtZSI6ImFkbWluIiwidG9rZW5fdHlwZSI6InN0YXRpY190b2tlbiJ9.iwsRH37tcqE8HyI_S98AEM6KUH7bVdxDasR3V8QasXI
|
||||
var data, _ = EncryptToken(a)
|
||||
|
||||
fmt.Println("---data---", data)
|
||||
}
|
||||
@@ -74,7 +74,6 @@ func (g *GenerateTerminusdServiceEnv) Execute(runtime connector.Runtime) error {
|
||||
"RegistryMirrors": g.KubeConf.Arg.RegistryMirrors,
|
||||
"BaseDir": baseDir,
|
||||
"GpuEnable": utils.FormatBoolToInt(g.KubeConf.Arg.GPU.Enable),
|
||||
"TokenMaxAge": g.KubeConf.Arg.TokenMaxAge,
|
||||
},
|
||||
PrintContent: true,
|
||||
}
|
||||
|
||||
@@ -14,5 +14,4 @@ KUBE_TYPE={{ .KubeType }}
|
||||
REGISTRY_MIRRORS={{ .RegistryMirrors }}
|
||||
BASE_DIR={{ .BaseDir }}
|
||||
LOCAL_GPU_ENABLE={{ .GpuEnable }}
|
||||
TOKEN_MAX_AGE={{ .TokenMaxAge }}
|
||||
`)))
|
||||
|
||||
@@ -3,13 +3,14 @@ package kubesphere
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/beclab/Olares/cli/pkg/storage"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/beclab/Olares/cli/pkg/storage"
|
||||
|
||||
"github.com/containerd/containerd/plugin"
|
||||
"github.com/pelletier/go-toml"
|
||||
|
||||
@@ -470,6 +471,7 @@ func (t *InitMinikubeNs) Execute(runtime connector.Runtime) error {
|
||||
common.NamespaceKubekeySystem,
|
||||
common.NamespaceKubesphereSystem,
|
||||
common.NamespaceKubesphereMonitoringSystem,
|
||||
common.NamespaceKubesphereControlsSystem,
|
||||
}
|
||||
|
||||
for _, ns := range allNs {
|
||||
|
||||
@@ -17,12 +17,9 @@
|
||||
package kubesphere
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/beclab/Olares/cli/pkg/core/action"
|
||||
"github.com/beclab/Olares/cli/pkg/core/logger"
|
||||
"github.com/beclab/Olares/cli/pkg/version/kubesphere/templates"
|
||||
|
||||
"github.com/beclab/Olares/cli/pkg/common"
|
||||
"github.com/beclab/Olares/cli/pkg/core/prepare"
|
||||
@@ -61,81 +58,19 @@ func (d *DeployModule) Init() {
|
||||
d.Name = "DeployKubeSphereModule"
|
||||
d.Desc = "Deploy KubeSphere"
|
||||
|
||||
generateManifests := &task.RemoteTask{
|
||||
Name: "GenerateKsInstallerCRD",
|
||||
Desc: "Generate KubeSphere ks-installer crd manifests",
|
||||
Hosts: d.Runtime.GetHostsByRole(common.Master),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
new(common.OnlyFirstMaster),
|
||||
new(NotEqualDesiredVersion),
|
||||
},
|
||||
Action: &action.Template{
|
||||
Name: "GenerateKsInstallerCRD",
|
||||
Template: templates.KsInstaller,
|
||||
Dst: filepath.Join(common.KubeAddonsDir, templates.KsInstaller.Name()),
|
||||
},
|
||||
Parallel: false,
|
||||
}
|
||||
|
||||
addConfig := &task.RemoteTask{
|
||||
Name: "AddKsInstallerConfig",
|
||||
Desc: "Add config to ks-installer manifests",
|
||||
Hosts: d.Runtime.GetHostsByRole(common.Master),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
new(common.OnlyFirstMaster),
|
||||
new(NotEqualDesiredVersion),
|
||||
},
|
||||
Action: new(AddInstallerConfig),
|
||||
Parallel: false,
|
||||
}
|
||||
|
||||
createNamespace := &task.RemoteTask{
|
||||
Name: "CreateKubeSphereNamespace",
|
||||
Desc: "Create the kubesphere namespace",
|
||||
Hosts: d.Runtime.GetHostsByRole(common.Master),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
new(common.OnlyFirstMaster),
|
||||
new(NotEqualDesiredVersion),
|
||||
},
|
||||
Action: new(CreateNamespace),
|
||||
Parallel: false,
|
||||
}
|
||||
|
||||
setup := &task.RemoteTask{
|
||||
Name: "SetupKsInstallerConfig",
|
||||
Desc: "Setup ks-installer config",
|
||||
Hosts: d.Runtime.GetHostsByRole(common.Master),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
new(common.OnlyFirstMaster),
|
||||
new(NotEqualDesiredVersion),
|
||||
},
|
||||
Action: new(Setup), // todo
|
||||
Parallel: false,
|
||||
Retry: 1,
|
||||
}
|
||||
|
||||
apply := &task.RemoteTask{
|
||||
Name: "ApplyKsInstaller",
|
||||
Desc: "Apply ks-installer",
|
||||
Hosts: d.Runtime.GetHostsByRole(common.Master),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
new(common.OnlyFirstMaster),
|
||||
new(NotEqualDesiredVersion),
|
||||
},
|
||||
Action: new(Apply),
|
||||
Parallel: false,
|
||||
Retry: 10,
|
||||
Delay: 5 * time.Second,
|
||||
}
|
||||
|
||||
d.Tasks = []task.Interface{
|
||||
generateManifests,
|
||||
// apply crd installer.kubesphere.io/v1alpha1
|
||||
// apply,
|
||||
addConfig,
|
||||
createNamespace,
|
||||
setup,
|
||||
apply,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +92,6 @@ func (c *CheckResultModule) Init() {
|
||||
Hosts: c.Runtime.GetHostsByRole(common.Master),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
new(common.OnlyFirstMaster),
|
||||
new(NotEqualDesiredVersion),
|
||||
},
|
||||
Action: new(Check),
|
||||
Parallel: false,
|
||||
@@ -170,7 +104,6 @@ func (c *CheckResultModule) Init() {
|
||||
Hosts: c.Runtime.GetHostsByRole(common.Master),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
new(common.OnlyFirstMaster),
|
||||
new(NotEqualDesiredVersion),
|
||||
},
|
||||
Action: new(GetKubeCommand),
|
||||
Parallel: false,
|
||||
|
||||
@@ -1,243 +0,0 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: system:kubesphere-router-clusterrole
|
||||
annotations:
|
||||
kubernetes.io/created-by: kubesphere.io/ks-router
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- configmaps
|
||||
- endpoints
|
||||
- nodes
|
||||
- pods
|
||||
- secrets
|
||||
- namespaces
|
||||
verbs:
|
||||
- list
|
||||
- watch
|
||||
- get
|
||||
- update
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- nodes
|
||||
verbs:
|
||||
- get
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- services
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- "extensions"
|
||||
resources:
|
||||
- ingresses
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- "networking.k8s.io"
|
||||
resources:
|
||||
- ingresses
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- events
|
||||
verbs:
|
||||
- create
|
||||
- patch
|
||||
- apiGroups:
|
||||
- "extensions"
|
||||
resources:
|
||||
- ingresses/status
|
||||
verbs:
|
||||
- update
|
||||
- apiGroups:
|
||||
- "networking.k8s.io"
|
||||
resources:
|
||||
- ingresses/status
|
||||
verbs:
|
||||
- update
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: system:kubesphere-router-role
|
||||
namespace: kubesphere-controls-system
|
||||
annotations:
|
||||
kubernetes.io/created-by: kubesphere.io/ks-router
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- configmaps
|
||||
- pods
|
||||
- secrets
|
||||
- namespaces
|
||||
verbs:
|
||||
- get
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- configmaps
|
||||
resourceNames:
|
||||
# Defaults to "<election-id>-<ingress-class>"
|
||||
# Here: "<ingress-controller-leader>-<nginx>"
|
||||
# This has to be adapted if you change either parameter
|
||||
# when launching the nginx-ingress-controller.
|
||||
- "ingress-controller-leader-nginx"
|
||||
verbs:
|
||||
- get
|
||||
- update
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- configmaps
|
||||
verbs:
|
||||
- create
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- endpoints
|
||||
verbs:
|
||||
- get
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: kubesphere-router-serviceaccount
|
||||
namespace: kubesphere-controls-system
|
||||
annotations:
|
||||
kubernetes.io/created-by: kubesphere.io/ks-router
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: system:nginx-ingress-clusterrole-nisa-binding
|
||||
annotations:
|
||||
kubernetes.io/created-by: kubesphere.io/ks-router
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: system:kubesphere-router-clusterrole
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: kubesphere-router-serviceaccount
|
||||
namespace: kubesphere-controls-system
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: nginx-ingress-role-nisa-binding
|
||||
namespace: kubesphere-controls-system
|
||||
annotations:
|
||||
kubernetes.io/created-by: kubesphere.io/ks-router
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: system:kubesphere-router-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: kubesphere-router-serviceaccount
|
||||
namespace: kubesphere-controls-system
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: default-http-backend
|
||||
namespace: kubesphere-controls-system
|
||||
labels:
|
||||
app: kubesphere
|
||||
component: kubesphere-router
|
||||
version: express-1.0.alpha
|
||||
annotations:
|
||||
kubernetes.io/created-by: kubesphere.io/ks-router
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: kubesphere
|
||||
component: kubesphere-router
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: kubesphere
|
||||
component: kubesphere-router
|
||||
spec:
|
||||
terminationGracePeriodSeconds: 60
|
||||
containers:
|
||||
- name: default-http-backend
|
||||
# Any image is permissible as long as:
|
||||
# 1. It serves a 404 page at /
|
||||
# 2. It serves 200 on a /healthz endpoint
|
||||
image: {{ .Values.image.defaultbackend_repo }}:{{ .Values.image.defaultbackend_tag | default "latest" }}
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: 8080
|
||||
scheme: HTTP
|
||||
initialDelaySeconds: 30
|
||||
timeoutSeconds: 5
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
resources:
|
||||
limits:
|
||||
cpu: 10m
|
||||
memory: 20Mi
|
||||
requests:
|
||||
cpu: 10m
|
||||
memory: 20Mi
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: default-http-backend
|
||||
namespace: kubesphere-controls-system
|
||||
labels:
|
||||
app: kubesphere
|
||||
component: kubesphere-router
|
||||
annotations:
|
||||
kubernetes.io/created-by: kubesphere.io/ks-router
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app: kubesphere
|
||||
component: kubesphere-router
|
||||
|
||||
---
|
||||
# create a seviceaccount for kubectl pod
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: kubesphere-cluster-admin
|
||||
namespace: kubesphere-controls-system
|
||||
annotations:
|
||||
kubernetes.io/created-by: kubesphere.io/kubectl
|
||||
---
|
||||
# bind kubesphere-cluster-admin sa to clusterrole cluster-admin
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: system:kubesphere-cluster-admin
|
||||
annotations:
|
||||
kubernetes.io/created-by: kubesphere.io/kubectl
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: cluster-admin
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: kubesphere-cluster-admin
|
||||
namespace: kubesphere-controls-system
|
||||
@@ -1,466 +0,0 @@
|
||||
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.6.1
|
||||
creationTimestamp: null
|
||||
name: clusterdashboards.monitoring.kubesphere.io
|
||||
spec:
|
||||
group: monitoring.kubesphere.io
|
||||
names:
|
||||
kind: ClusterDashboard
|
||||
listKind: ClusterDashboardList
|
||||
plural: clusterdashboards
|
||||
singular: clusterdashboard
|
||||
scope: Cluster
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: ClusterDashboard is the Schema for the culsterdashboards API
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: DashboardSpec defines the desired state of Dashboard
|
||||
properties:
|
||||
datasource:
|
||||
description: Dashboard datasource
|
||||
type: string
|
||||
description:
|
||||
description: Dashboard description
|
||||
type: string
|
||||
panels:
|
||||
description: Collection of panels. Panel is one of [Row](row.md),
|
||||
[Singlestat](#singlestat.md) or [Graph](graph.md)
|
||||
items:
|
||||
description: Supported panel
|
||||
properties:
|
||||
bars:
|
||||
description: A collection of queries Targets []Target `json:"targets,omitempty"`
|
||||
Display as a bar chart
|
||||
type: boolean
|
||||
colors:
|
||||
description: Set series color
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
decimals:
|
||||
description: Name of the signlestat panel Title string `json:"title,omitempty"`
|
||||
Must be `singlestat` Type string `json:"type"` Panel ID Id
|
||||
int64 `json:"id,omitempty"` A collection of queries Targets
|
||||
[]Target `json:"targets,omitempty"` Limit the decimal numbers
|
||||
format: int64
|
||||
type: integer
|
||||
description:
|
||||
description: Name of the graph panel Title string `json:"title,omitempty"`
|
||||
Must be `graph` Type string `json:"type"` Panel ID Id int64
|
||||
`json:"id,omitempty"` Panel description
|
||||
type: string
|
||||
format:
|
||||
description: Display unit
|
||||
type: string
|
||||
id:
|
||||
description: Panel ID
|
||||
format: int64
|
||||
type: integer
|
||||
lines:
|
||||
description: Display as a line chart
|
||||
type: boolean
|
||||
stack:
|
||||
description: Display as a stacked chart
|
||||
type: boolean
|
||||
targets:
|
||||
description: A collection of queries Only for panels with `graph`
|
||||
or `singlestat` type
|
||||
items:
|
||||
description: Query editor options
|
||||
properties:
|
||||
expr:
|
||||
description: Input for fetching metrics.
|
||||
type: string
|
||||
legendFormat:
|
||||
description: Legend format for outputs. You can make a
|
||||
dynamic legend with templating variables.
|
||||
type: string
|
||||
refId:
|
||||
description: Reference ID
|
||||
format: int64
|
||||
type: integer
|
||||
step:
|
||||
description: Set series time interval
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
title:
|
||||
description: Name of the panel
|
||||
type: string
|
||||
type:
|
||||
description: Panel Type, one of `row`, `graph`, `singlestat`
|
||||
type: string
|
||||
yaxes:
|
||||
description: Y-axis options
|
||||
items:
|
||||
properties:
|
||||
decimals:
|
||||
description: Limit the decimal numbers
|
||||
format: int64
|
||||
type: integer
|
||||
format:
|
||||
description: Display unit
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
required:
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
templating:
|
||||
description: Templating variables
|
||||
items:
|
||||
description: Templating defines a variable, which can be used as
|
||||
a placeholder in query
|
||||
properties:
|
||||
name:
|
||||
description: Variable name
|
||||
type: string
|
||||
query:
|
||||
description: Set variable values to be the return result of
|
||||
the query
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
time:
|
||||
description: Time range for display
|
||||
properties:
|
||||
from:
|
||||
description: Start time in the format of `^now([+-][0-9]+[smhdwMy])?$`,
|
||||
eg. `now-1M`. It denotes the end time is set to the last month
|
||||
since now.
|
||||
type: string
|
||||
to:
|
||||
description: End time in the format of `^now([+-][0-9]+[smhdwMy])?$`,
|
||||
eg. `now-1M`. It denotes the start time is set to the last month
|
||||
since now.
|
||||
type: string
|
||||
type: object
|
||||
title:
|
||||
description: Dashboard title
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: false
|
||||
- name: v1alpha2
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: ClusterDashboard is the Schema for the culsterdashboards API
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: DashboardSpec defines the desired state of Dashboard
|
||||
properties:
|
||||
annotations:
|
||||
description: Annotations
|
||||
items:
|
||||
properties:
|
||||
datasource:
|
||||
type: string
|
||||
enable:
|
||||
type: boolean
|
||||
expr:
|
||||
type: string
|
||||
iconColor:
|
||||
type: string
|
||||
iconSize:
|
||||
type: integer
|
||||
lineColor:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
query:
|
||||
type: string
|
||||
showLine:
|
||||
type: boolean
|
||||
step:
|
||||
type: string
|
||||
tagKeys:
|
||||
type: string
|
||||
tags:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
tagsField:
|
||||
type: string
|
||||
textField:
|
||||
type: string
|
||||
textFormat:
|
||||
type: string
|
||||
titleFormat:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
auto_refresh:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
editable:
|
||||
type: boolean
|
||||
id:
|
||||
type: integer
|
||||
panels:
|
||||
items:
|
||||
properties:
|
||||
bars:
|
||||
description: Display as a bar chart
|
||||
type: boolean
|
||||
colors:
|
||||
description: Set series color
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
content:
|
||||
type: string
|
||||
datasource:
|
||||
description: Datasource
|
||||
type: string
|
||||
decimals:
|
||||
format: int64
|
||||
type: integer
|
||||
description:
|
||||
description: Description
|
||||
type: string
|
||||
format:
|
||||
description: Display unit
|
||||
type: string
|
||||
gauge:
|
||||
description: gauge
|
||||
properties:
|
||||
maxValue:
|
||||
format: int64
|
||||
type: integer
|
||||
minValue:
|
||||
format: int64
|
||||
type: integer
|
||||
show:
|
||||
type: boolean
|
||||
thresholdLabels:
|
||||
type: boolean
|
||||
thresholdMarkers:
|
||||
type: boolean
|
||||
type: object
|
||||
height:
|
||||
description: Height
|
||||
type: string
|
||||
id:
|
||||
description: Panel ID
|
||||
format: int64
|
||||
type: integer
|
||||
legend:
|
||||
description: legend
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
lines:
|
||||
description: Display as a line chart
|
||||
type: boolean
|
||||
mode:
|
||||
type: string
|
||||
options:
|
||||
properties:
|
||||
colorMode:
|
||||
type: string
|
||||
content:
|
||||
type: string
|
||||
displayMode:
|
||||
type: string
|
||||
graphMode:
|
||||
type: string
|
||||
justifyMode:
|
||||
type: string
|
||||
mode:
|
||||
type: string
|
||||
orientation:
|
||||
type: string
|
||||
textMode:
|
||||
type: string
|
||||
type: object
|
||||
scroll:
|
||||
type: boolean
|
||||
sort:
|
||||
properties:
|
||||
col:
|
||||
type: integer
|
||||
desc:
|
||||
type: boolean
|
||||
type: object
|
||||
sparkline:
|
||||
description: 'spark line: full or bottom'
|
||||
type: string
|
||||
stack:
|
||||
description: Display as a stacked chart
|
||||
type: boolean
|
||||
targets:
|
||||
description: A collection of queries
|
||||
items:
|
||||
description: Query editor options Referers to https://pkg.go.dev/github.com/grafana-tools/sdk#Target
|
||||
properties:
|
||||
expr:
|
||||
description: 'only support prometheus,and the corresponding
|
||||
fields are as follows: Input for fetching metrics.'
|
||||
type: string
|
||||
legendFormat:
|
||||
description: Legend format for outputs. You can make a
|
||||
dynamic legend with templating variables.
|
||||
type: string
|
||||
refId:
|
||||
description: Reference ID
|
||||
format: int64
|
||||
type: integer
|
||||
step:
|
||||
description: Set series time interval
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
title:
|
||||
description: Name of the panel
|
||||
type: string
|
||||
type:
|
||||
description: Type of the panel
|
||||
type: string
|
||||
valueName:
|
||||
description: value name
|
||||
type: string
|
||||
xaxis:
|
||||
properties:
|
||||
decimals:
|
||||
description: Limit the decimal numbers
|
||||
format: int64
|
||||
type: integer
|
||||
format:
|
||||
description: Display unit
|
||||
type: string
|
||||
type: object
|
||||
yaxes:
|
||||
description: Y-axis options
|
||||
items:
|
||||
properties:
|
||||
decimals:
|
||||
description: Limit the decimal numbers
|
||||
format: int64
|
||||
type: integer
|
||||
format:
|
||||
description: Display unit
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
type: array
|
||||
shared_crosshair:
|
||||
type: boolean
|
||||
tags:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
templatings:
|
||||
description: // Templating variables
|
||||
items:
|
||||
properties:
|
||||
allFormat:
|
||||
type: string
|
||||
allValue:
|
||||
type: string
|
||||
auto:
|
||||
type: boolean
|
||||
auto_count:
|
||||
type: integer
|
||||
datasource:
|
||||
type: string
|
||||
hide:
|
||||
type: integer
|
||||
includeAll:
|
||||
type: boolean
|
||||
label:
|
||||
type: string
|
||||
multi:
|
||||
type: boolean
|
||||
multiFormat:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
options:
|
||||
items:
|
||||
properties:
|
||||
selected:
|
||||
type: boolean
|
||||
text:
|
||||
type: string
|
||||
value:
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
query:
|
||||
type: string
|
||||
regex:
|
||||
type: string
|
||||
sort:
|
||||
type: integer
|
||||
type:
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
time:
|
||||
description: Time range
|
||||
properties:
|
||||
from:
|
||||
description: Start time in the format of `^now([+-][0-9]+[smhdwMy])?$`,
|
||||
eg. `now-1M`. It denotes the end time is set to the last month
|
||||
since now.
|
||||
type: string
|
||||
to:
|
||||
description: End time in the format of `^now([+-][0-9]+[smhdwMy])?$`,
|
||||
eg. `now-1M`. It denotes the start time is set to the last month
|
||||
since now.
|
||||
type: string
|
||||
type: object
|
||||
timezone:
|
||||
type: string
|
||||
title:
|
||||
type: string
|
||||
uid:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
@@ -1,470 +0,0 @@
|
||||
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.6.1
|
||||
creationTimestamp: null
|
||||
name: dashboards.monitoring.kubesphere.io
|
||||
spec:
|
||||
group: monitoring.kubesphere.io
|
||||
names:
|
||||
kind: Dashboard
|
||||
listKind: DashboardList
|
||||
plural: dashboards
|
||||
singular: dashboard
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: Dashboard is the Schema for the dashboards API
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: DashboardSpec defines the desired state of Dashboard
|
||||
properties:
|
||||
datasource:
|
||||
description: Dashboard datasource
|
||||
type: string
|
||||
description:
|
||||
description: Dashboard description
|
||||
type: string
|
||||
panels:
|
||||
description: Collection of panels. Panel is one of [Row](row.md),
|
||||
[Singlestat](#singlestat.md) or [Graph](graph.md)
|
||||
items:
|
||||
description: Supported panel
|
||||
properties:
|
||||
bars:
|
||||
description: A collection of queries Targets []Target `json:"targets,omitempty"`
|
||||
Display as a bar chart
|
||||
type: boolean
|
||||
colors:
|
||||
description: Set series color
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
decimals:
|
||||
description: Name of the signlestat panel Title string `json:"title,omitempty"`
|
||||
Must be `singlestat` Type string `json:"type"` Panel ID Id
|
||||
int64 `json:"id,omitempty"` A collection of queries Targets
|
||||
[]Target `json:"targets,omitempty"` Limit the decimal numbers
|
||||
format: int64
|
||||
type: integer
|
||||
description:
|
||||
description: Name of the graph panel Title string `json:"title,omitempty"`
|
||||
Must be `graph` Type string `json:"type"` Panel ID Id int64
|
||||
`json:"id,omitempty"` Panel description
|
||||
type: string
|
||||
format:
|
||||
description: Display unit
|
||||
type: string
|
||||
id:
|
||||
description: Panel ID
|
||||
format: int64
|
||||
type: integer
|
||||
lines:
|
||||
description: Display as a line chart
|
||||
type: boolean
|
||||
stack:
|
||||
description: Display as a stacked chart
|
||||
type: boolean
|
||||
targets:
|
||||
description: A collection of queries Only for panels with `graph`
|
||||
or `singlestat` type
|
||||
items:
|
||||
description: Query editor options
|
||||
properties:
|
||||
expr:
|
||||
description: Input for fetching metrics.
|
||||
type: string
|
||||
legendFormat:
|
||||
description: Legend format for outputs. You can make a
|
||||
dynamic legend with templating variables.
|
||||
type: string
|
||||
refId:
|
||||
description: Reference ID
|
||||
format: int64
|
||||
type: integer
|
||||
step:
|
||||
description: Set series time interval
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
title:
|
||||
description: Name of the panel
|
||||
type: string
|
||||
type:
|
||||
description: Panel Type, one of `row`, `graph`, `singlestat`
|
||||
type: string
|
||||
yaxes:
|
||||
description: Y-axis options
|
||||
items:
|
||||
properties:
|
||||
decimals:
|
||||
description: Limit the decimal numbers
|
||||
format: int64
|
||||
type: integer
|
||||
format:
|
||||
description: Display unit
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
required:
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
templating:
|
||||
description: Templating variables
|
||||
items:
|
||||
description: Templating defines a variable, which can be used as
|
||||
a placeholder in query
|
||||
properties:
|
||||
name:
|
||||
description: Variable name
|
||||
type: string
|
||||
query:
|
||||
description: Set variable values to be the return result of
|
||||
the query
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
time:
|
||||
description: Time range for display
|
||||
properties:
|
||||
from:
|
||||
description: Start time in the format of `^now([+-][0-9]+[smhdwMy])?$`,
|
||||
eg. `now-1M`. It denotes the end time is set to the last month
|
||||
since now.
|
||||
type: string
|
||||
to:
|
||||
description: End time in the format of `^now([+-][0-9]+[smhdwMy])?$`,
|
||||
eg. `now-1M`. It denotes the start time is set to the last month
|
||||
since now.
|
||||
type: string
|
||||
type: object
|
||||
title:
|
||||
description: Dashboard title
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: false
|
||||
subresources:
|
||||
status: {}
|
||||
- name: v1alpha2
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: Dashboard is the Schema for the dashboards API
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: DashboardSpec defines the desired state of Dashboard
|
||||
properties:
|
||||
annotations:
|
||||
description: Annotations
|
||||
items:
|
||||
properties:
|
||||
datasource:
|
||||
type: string
|
||||
enable:
|
||||
type: boolean
|
||||
expr:
|
||||
type: string
|
||||
iconColor:
|
||||
type: string
|
||||
iconSize:
|
||||
type: integer
|
||||
lineColor:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
query:
|
||||
type: string
|
||||
showLine:
|
||||
type: boolean
|
||||
step:
|
||||
type: string
|
||||
tagKeys:
|
||||
type: string
|
||||
tags:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
tagsField:
|
||||
type: string
|
||||
textField:
|
||||
type: string
|
||||
textFormat:
|
||||
type: string
|
||||
titleFormat:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
auto_refresh:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
editable:
|
||||
type: boolean
|
||||
id:
|
||||
type: integer
|
||||
panels:
|
||||
items:
|
||||
properties:
|
||||
bars:
|
||||
description: Display as a bar chart
|
||||
type: boolean
|
||||
colors:
|
||||
description: Set series color
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
content:
|
||||
type: string
|
||||
datasource:
|
||||
description: Datasource
|
||||
type: string
|
||||
decimals:
|
||||
format: int64
|
||||
type: integer
|
||||
description:
|
||||
description: Description
|
||||
type: string
|
||||
format:
|
||||
description: Display unit
|
||||
type: string
|
||||
gauge:
|
||||
description: gauge
|
||||
properties:
|
||||
maxValue:
|
||||
format: int64
|
||||
type: integer
|
||||
minValue:
|
||||
format: int64
|
||||
type: integer
|
||||
show:
|
||||
type: boolean
|
||||
thresholdLabels:
|
||||
type: boolean
|
||||
thresholdMarkers:
|
||||
type: boolean
|
||||
type: object
|
||||
height:
|
||||
description: Height
|
||||
type: string
|
||||
id:
|
||||
description: Panel ID
|
||||
format: int64
|
||||
type: integer
|
||||
legend:
|
||||
description: legend
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
lines:
|
||||
description: Display as a line chart
|
||||
type: boolean
|
||||
mode:
|
||||
type: string
|
||||
options:
|
||||
properties:
|
||||
colorMode:
|
||||
type: string
|
||||
content:
|
||||
type: string
|
||||
displayMode:
|
||||
type: string
|
||||
graphMode:
|
||||
type: string
|
||||
justifyMode:
|
||||
type: string
|
||||
mode:
|
||||
type: string
|
||||
orientation:
|
||||
type: string
|
||||
textMode:
|
||||
type: string
|
||||
type: object
|
||||
scroll:
|
||||
type: boolean
|
||||
sort:
|
||||
properties:
|
||||
col:
|
||||
type: integer
|
||||
desc:
|
||||
type: boolean
|
||||
type: object
|
||||
sparkline:
|
||||
description: 'spark line: full or bottom'
|
||||
type: string
|
||||
stack:
|
||||
description: Display as a stacked chart
|
||||
type: boolean
|
||||
targets:
|
||||
description: A collection of queries
|
||||
items:
|
||||
description: Query editor options Referers to https://pkg.go.dev/github.com/grafana-tools/sdk#Target
|
||||
properties:
|
||||
expr:
|
||||
description: 'only support prometheus,and the corresponding
|
||||
fields are as follows: Input for fetching metrics.'
|
||||
type: string
|
||||
legendFormat:
|
||||
description: Legend format for outputs. You can make a
|
||||
dynamic legend with templating variables.
|
||||
type: string
|
||||
refId:
|
||||
description: Reference ID
|
||||
format: int64
|
||||
type: integer
|
||||
step:
|
||||
description: Set series time interval
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
title:
|
||||
description: Name of the panel
|
||||
type: string
|
||||
type:
|
||||
description: Type of the panel
|
||||
type: string
|
||||
valueName:
|
||||
description: value name
|
||||
type: string
|
||||
xaxis:
|
||||
properties:
|
||||
decimals:
|
||||
description: Limit the decimal numbers
|
||||
format: int64
|
||||
type: integer
|
||||
format:
|
||||
description: Display unit
|
||||
type: string
|
||||
type: object
|
||||
yaxes:
|
||||
description: Y-axis options
|
||||
items:
|
||||
properties:
|
||||
decimals:
|
||||
description: Limit the decimal numbers
|
||||
format: int64
|
||||
type: integer
|
||||
format:
|
||||
description: Display unit
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
type: array
|
||||
shared_crosshair:
|
||||
type: boolean
|
||||
tags:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
templatings:
|
||||
description: // Templating variables
|
||||
items:
|
||||
properties:
|
||||
allFormat:
|
||||
type: string
|
||||
allValue:
|
||||
type: string
|
||||
auto:
|
||||
type: boolean
|
||||
auto_count:
|
||||
type: integer
|
||||
datasource:
|
||||
type: string
|
||||
hide:
|
||||
type: integer
|
||||
includeAll:
|
||||
type: boolean
|
||||
label:
|
||||
type: string
|
||||
multi:
|
||||
type: boolean
|
||||
multiFormat:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
options:
|
||||
items:
|
||||
properties:
|
||||
selected:
|
||||
type: boolean
|
||||
text:
|
||||
type: string
|
||||
value:
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
query:
|
||||
type: string
|
||||
regex:
|
||||
type: string
|
||||
sort:
|
||||
type: integer
|
||||
type:
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
time:
|
||||
description: Time range
|
||||
properties:
|
||||
from:
|
||||
description: Start time in the format of `^now([+-][0-9]+[smhdwMy])?$`,
|
||||
eg. `now-1M`. It denotes the end time is set to the last month
|
||||
since now.
|
||||
type: string
|
||||
to:
|
||||
description: End time in the format of `^now([+-][0-9]+[smhdwMy])?$`,
|
||||
eg. `now-1M`. It denotes the start time is set to the last month
|
||||
since now.
|
||||
type: string
|
||||
type: object
|
||||
timezone:
|
||||
type: string
|
||||
title:
|
||||
type: string
|
||||
uid:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
@@ -21,24 +21,6 @@ type CreateKsCore struct {
|
||||
}
|
||||
|
||||
func (t *CreateKsCore) Execute(runtime connector.Runtime) error {
|
||||
//var kubectlpath, err = util.GetCommand(common.CommandKubectl)
|
||||
//if err != nil {
|
||||
// return fmt.Errorf("kubectl not found")
|
||||
//}
|
||||
|
||||
//var cmd = fmt.Sprintf("%s get pod -n %s -l 'app=redis,tier=database,version=redis-4.0' -o jsonpath='{.items[0].status.phase}'", kubectlpath,
|
||||
// common.NamespaceKubesphereSystem)
|
||||
//rphase, err := runtime.GetRunner().Host.SudoCmd(cmd, false, false)
|
||||
//if rphase != "Running" {
|
||||
// return fmt.Errorf("Redis State %s", rphase)
|
||||
//}
|
||||
|
||||
masterNumIf, ok := t.PipelineCache.Get(common.CacheMasterNum)
|
||||
if !ok || masterNumIf == nil {
|
||||
return fmt.Errorf("failed to get master num")
|
||||
}
|
||||
masterNum := masterNumIf.(int64)
|
||||
|
||||
config, err := ctrl.GetConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -55,7 +37,7 @@ func (t *CreateKsCore) Execute(runtime connector.Runtime) error {
|
||||
var values = make(map[string]interface{})
|
||||
values["Release"] = map[string]string{
|
||||
"Namespace": common.NamespaceKubesphereSystem,
|
||||
"ReplicaCount": fmt.Sprintf("%d", masterNum),
|
||||
"ReplicaCount": fmt.Sprintf("%d", 1),
|
||||
}
|
||||
if err := utils.UpgradeCharts(context.Background(), actionConfig, settings, appKsCoreName,
|
||||
appPath, "", common.NamespaceKubesphereSystem, values, false); err != nil {
|
||||
@@ -78,7 +60,6 @@ func (m *DeployKsCoreModule) Init() {
|
||||
Hosts: m.Runtime.GetHostsByRole(common.Master),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
new(common.OnlyFirstMaster),
|
||||
new(NotEqualDesiredVersion),
|
||||
},
|
||||
Action: new(CreateKsCore),
|
||||
Parallel: false,
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/beclab/Olares/cli/pkg/common"
|
||||
@@ -21,129 +20,6 @@ import (
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
)
|
||||
|
||||
var kscorecrds = []map[string]string{
|
||||
{
|
||||
"ns": "kubesphere-controls-system",
|
||||
"kind": "serviceaccounts",
|
||||
"resource": "kubesphere-cluster-admin",
|
||||
"release": "ks-core",
|
||||
},
|
||||
{
|
||||
"ns": "kubesphere-controls-system",
|
||||
"kind": "serviceaccounts",
|
||||
"resource": "kubesphere-router-serviceaccount",
|
||||
"release": "ks-core",
|
||||
},
|
||||
{
|
||||
"ns": "kubesphere-controls-system",
|
||||
"kind": "role",
|
||||
"resource": "system:kubesphere-router-role",
|
||||
"release": "ks-core",
|
||||
},
|
||||
{
|
||||
"ns": "kubesphere-controls-system",
|
||||
"kind": "rolebinding",
|
||||
"resource": "nginx-ingress-role-nisa-binding",
|
||||
"release": "ks-core",
|
||||
},
|
||||
{
|
||||
"ns": "kubesphere-controls-system",
|
||||
"kind": "deployment",
|
||||
"resource": "default-http-backend",
|
||||
"release": "ks-core",
|
||||
},
|
||||
{
|
||||
"ns": "kubesphere-controls-system",
|
||||
"kind": "service",
|
||||
"resource": "default-http-backend",
|
||||
"release": "ks-core",
|
||||
},
|
||||
//{
|
||||
// "ns": "kubesphere-system",
|
||||
// "kind": "secrets",
|
||||
// "resource": "ks-controller-manager-webhook-cert",
|
||||
// "release": "ks-core",
|
||||
//},
|
||||
{
|
||||
"ns": "kubesphere-system",
|
||||
"kind": "serviceaccounts",
|
||||
"resource": "kubesphere",
|
||||
"release": "ks-core",
|
||||
},
|
||||
{
|
||||
"ns": "kubesphere-system",
|
||||
"kind": "clusterroles",
|
||||
"resource": "system:kubesphere-router-clusterrole",
|
||||
"release": "ks-core",
|
||||
},
|
||||
{
|
||||
"ns": "kubesphere-system",
|
||||
"kind": "clusterrolebindings",
|
||||
"resource": "system:nginx-ingress-clusterrole-nisa-binding",
|
||||
"release": "ks-core",
|
||||
},
|
||||
{
|
||||
"ns": "kubesphere-system",
|
||||
"kind": "clusterrolebindings",
|
||||
"resource": "system:kubesphere-cluster-admin",
|
||||
"release": "ks-core",
|
||||
},
|
||||
{
|
||||
"ns": "kubesphere-system",
|
||||
"kind": "clusterrolebindings",
|
||||
"resource": "kubesphere",
|
||||
"release": "ks-core",
|
||||
},
|
||||
{
|
||||
"ns": "kubesphere-system",
|
||||
"kind": "services",
|
||||
"resource": "ks-apiserver",
|
||||
"release": "ks-core",
|
||||
},
|
||||
//{
|
||||
// "ns": "kubesphere-system",
|
||||
// "kind": "services",
|
||||
// "resource": "ks-controller-manager",
|
||||
// "release": "ks-core",
|
||||
//},
|
||||
{
|
||||
"ns": "kubesphere-system",
|
||||
"kind": "deployments",
|
||||
"resource": "ks-apiserver",
|
||||
"release": "ks-core",
|
||||
},
|
||||
//{
|
||||
// "ns": "kubesphere-system",
|
||||
// "kind": "deployments",
|
||||
// "resource": "ks-controller-manager",
|
||||
// "release": "ks-core",
|
||||
//},
|
||||
//{
|
||||
// "ns": "kubesphere-system",
|
||||
// "kind": "validatingwebhookconfigurations",
|
||||
// "resource": "users.iam.kubesphere.io",
|
||||
// "release": "ks-core",
|
||||
//},
|
||||
{
|
||||
"ns": "kubesphere-system",
|
||||
"kind": "validatingwebhookconfigurations",
|
||||
"resource": "resourcesquotas.quota.kubesphere.io",
|
||||
"release": "ks-core",
|
||||
},
|
||||
{
|
||||
"ns": "kubesphere-system",
|
||||
"kind": "validatingwebhookconfigurations",
|
||||
"resource": "network.kubesphere.io",
|
||||
"release": "ks-core",
|
||||
},
|
||||
{
|
||||
"ns": "kubesphere-system",
|
||||
"kind": "users.iam.kubesphere.io",
|
||||
"resource": "admin",
|
||||
"release": "ks-core",
|
||||
},
|
||||
}
|
||||
|
||||
type CreateKsRole struct {
|
||||
common.KubeAction
|
||||
}
|
||||
@@ -167,42 +43,11 @@ func (t *CreateKsRole) Execute(runtime connector.Runtime) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type PatchKsCoreStatus struct {
|
||||
common.KubeAction
|
||||
}
|
||||
|
||||
func (t *PatchKsCoreStatus) Execute(runtime connector.Runtime) error {
|
||||
//var kubectlpath, _ = t.PipelineCache.GetMustString(common.CacheCommandKubectlPath)
|
||||
//if kubectlpath == "" {
|
||||
// kubectlpath = path.Join(common.BinDir, common.CommandKubectl)
|
||||
//}
|
||||
//
|
||||
//var jsonPath = fmt.Sprintf(`{\"status\": {\"core\": {\"status\": \"enabled\", \"enabledTime\": \"%s\"}}}`, time.Now().Format("2006-01-02T15:04:05Z"))
|
||||
//var cmd = fmt.Sprintf("%s patch cc ks-installer --type merge -p '%s' -n %s", kubectlpath, jsonPath, common.NamespaceKubesphereSystem)
|
||||
//
|
||||
//_, err := runtime.GetRunner().Host.SudoCmd(cmd, false, true)
|
||||
//if err != nil {
|
||||
// return errors.Wrap(errors.WithStack(err), "patch ks-core status failed")
|
||||
//}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type CreateKsCoreConfig struct {
|
||||
common.KubeAction
|
||||
}
|
||||
|
||||
func (t *CreateKsCoreConfig) Execute(runtime connector.Runtime) error {
|
||||
jwtSecretIf, ok := t.PipelineCache.Get(common.CacheJwtSecret)
|
||||
if !ok || jwtSecretIf == nil {
|
||||
return fmt.Errorf("failed to get jwt secret")
|
||||
}
|
||||
|
||||
kubeVersionIf, ok := t.PipelineCache.Get(common.CacheKubeletVersion)
|
||||
if !ok || kubeVersionIf == nil {
|
||||
return fmt.Errorf("failed to get kubelet version")
|
||||
}
|
||||
|
||||
config, err := ctrl.GetConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -230,13 +75,8 @@ func (t *CreateKsCoreConfig) Execute(runtime connector.Runtime) error {
|
||||
// create ks-config
|
||||
var appKsConfigName = common.ChartNameKsConfig
|
||||
appPath = path.Join(runtime.GetInstallerDir(), cc.BuildFilesCacheDir, cc.BuildDir, appKsConfigName)
|
||||
values = make(map[string]interface{})
|
||||
values["Release"] = map[string]interface{}{
|
||||
"JwtSecret": jwtSecretIf.(string),
|
||||
"TokenMaxAge": t.KubeConf.Arg.TokenMaxAge * int64(time.Second),
|
||||
}
|
||||
if err := utils.UpgradeCharts(context.Background(), actionConfig, settings, appKsConfigName,
|
||||
appPath, "", common.NamespaceKubesphereSystem, values, false); err != nil {
|
||||
appPath, "", common.NamespaceKubesphereSystem, nil, false); err != nil {
|
||||
logger.Errorf("failed to install %s chart: %v", appKsConfigName, err)
|
||||
return err
|
||||
}
|
||||
@@ -273,82 +113,6 @@ func (t *CreateKsCoreConfigManifests) Execute(runtime connector.Runtime) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type PacthKsCore struct {
|
||||
common.KubeAction
|
||||
}
|
||||
|
||||
func (t *PacthKsCore) Execute(runtime connector.Runtime) error {
|
||||
var secretsNum int64
|
||||
var crdNum int64
|
||||
var secretsNumIf, ok = t.PipelineCache.Get(common.CacheSecretsNum)
|
||||
if ok && secretsNumIf != nil {
|
||||
secretsNum = secretsNumIf.(int64)
|
||||
}
|
||||
|
||||
crdNumIf, ok := t.PipelineCache.Get(common.CacheCrdsNUm)
|
||||
if ok && crdNumIf != nil {
|
||||
crdNum = crdNumIf.(int64)
|
||||
}
|
||||
|
||||
var kubectlpath, err = util.GetCommand(common.CommandKubectl)
|
||||
if err != nil {
|
||||
return fmt.Errorf("kubectl not found")
|
||||
}
|
||||
|
||||
if secretsNum == 0 && crdNum != 0 {
|
||||
for _, item := range kscorecrds {
|
||||
var cmd = fmt.Sprintf("%s -n %s annotate --overwrite %s %s meta.helm.sh/release-name=%s && %s -n %s annotate --overwrite %s %s meta.helm.sh/release-namespace=%s && %s -n %s label --overwrite %s %s app.kubernetes.io/managed-by=Helm",
|
||||
kubectlpath, item["ns"], item["kind"], item["resource"], item["release"],
|
||||
kubectlpath, item["ns"], item["kind"], item["resource"], common.NamespaceKubesphereSystem,
|
||||
kubectlpath, item["ns"], item["kind"], item["resource"])
|
||||
|
||||
if _, err := runtime.GetRunner().SudoCmd(cmd, false, true); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "patch ks-core crd")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type CheckKsCoreExist struct {
|
||||
common.KubeAction
|
||||
}
|
||||
|
||||
func (t *CheckKsCoreExist) Execute(runtime connector.Runtime) error {
|
||||
var kubectlpath, err = util.GetCommand(common.CommandKubectl)
|
||||
if err != nil {
|
||||
return fmt.Errorf("kubectl not found")
|
||||
}
|
||||
|
||||
var cmd string
|
||||
|
||||
cmd = fmt.Sprintf("%s -n %s get secrets --field-selector=type=helm.sh/release.v1 | grep ks-core |wc -l",
|
||||
kubectlpath,
|
||||
common.NamespaceKubesphereSystem)
|
||||
stdout, _ := runtime.GetRunner().SudoCmd(cmd, false, false)
|
||||
|
||||
secretNum, err := strconv.ParseInt(stdout, 10, 64)
|
||||
if err != nil {
|
||||
secretNum = 0
|
||||
}
|
||||
|
||||
cmd = fmt.Sprintf("%s get crd users.iam.kubesphere.io | grep 'users.iam.kubesphere.io' |wc -l", kubectlpath)
|
||||
stdout, _ = runtime.GetRunner().SudoCmd(cmd, false, false)
|
||||
|
||||
usersCrdNum, err := strconv.ParseInt(stdout, 10, 64)
|
||||
if err != nil {
|
||||
usersCrdNum = 0
|
||||
}
|
||||
|
||||
logger.Debugf("secretNum: %d, usersCrdNum: %d", secretNum, usersCrdNum)
|
||||
|
||||
t.ModuleCache.Set(common.CacheSecretsNum, secretNum)
|
||||
t.ModuleCache.Set(common.CacheCrdsNUm, usersCrdNum)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type DeployKsCoreConfigModule struct {
|
||||
common.KubeModule
|
||||
}
|
||||
@@ -356,37 +120,11 @@ type DeployKsCoreConfigModule struct {
|
||||
func (m *DeployKsCoreConfigModule) Init() {
|
||||
m.Name = "DeployKsCoreConfig"
|
||||
|
||||
checkKsCoreExist := &task.RemoteTask{
|
||||
Name: "CheckKsCoreExist",
|
||||
Hosts: m.Runtime.GetHostsByRole(common.Master),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
new(common.OnlyFirstMaster),
|
||||
new(NotEqualDesiredVersion),
|
||||
new(common.GetMasterNum),
|
||||
},
|
||||
Action: new(CheckKsCoreExist),
|
||||
Parallel: false,
|
||||
Retry: 0,
|
||||
}
|
||||
|
||||
pacthKsCore := &task.RemoteTask{
|
||||
Name: "PacthKsCore",
|
||||
Hosts: m.Runtime.GetHostsByRole(common.Master),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
new(common.OnlyFirstMaster),
|
||||
new(NotEqualDesiredVersion),
|
||||
},
|
||||
Action: new(PacthKsCore),
|
||||
Parallel: false,
|
||||
Retry: 0,
|
||||
}
|
||||
|
||||
createKsCoreConfigManifests := &task.RemoteTask{
|
||||
Name: "CreateKsCoreConfigManifests",
|
||||
Hosts: m.Runtime.GetHostsByRole(common.Master),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
new(common.OnlyFirstMaster),
|
||||
new(NotEqualDesiredVersion),
|
||||
},
|
||||
Action: new(CreateKsCoreConfigManifests),
|
||||
Parallel: false,
|
||||
@@ -399,31 +137,17 @@ func (m *DeployKsCoreConfigModule) Init() {
|
||||
Hosts: m.Runtime.GetHostsByRole(common.Master),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
new(common.OnlyFirstMaster),
|
||||
new(NotEqualDesiredVersion),
|
||||
},
|
||||
Action: new(CreateKsCoreConfig),
|
||||
Parallel: true,
|
||||
Retry: 0,
|
||||
}
|
||||
|
||||
patchKsCoreStatus := &task.RemoteTask{
|
||||
Name: "PatchKsCoreStatus",
|
||||
Hosts: m.Runtime.GetHostsByRole(common.Master),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
new(common.OnlyFirstMaster),
|
||||
new(NotEqualDesiredVersion),
|
||||
},
|
||||
Action: new(PatchKsCoreStatus),
|
||||
Parallel: true,
|
||||
Retry: 0,
|
||||
}
|
||||
|
||||
createKsRole := &task.RemoteTask{
|
||||
Name: "CreateKsRole",
|
||||
Hosts: m.Runtime.GetHostsByRole(common.Master),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
new(common.OnlyFirstMaster),
|
||||
new(NotEqualDesiredVersion),
|
||||
},
|
||||
Action: new(CreateKsRole),
|
||||
Parallel: true,
|
||||
@@ -431,11 +155,8 @@ func (m *DeployKsCoreConfigModule) Init() {
|
||||
}
|
||||
|
||||
m.Tasks = []task.Interface{
|
||||
checkKsCoreExist,
|
||||
pacthKsCore,
|
||||
createKsCoreConfigManifests,
|
||||
createKsCoreConfig,
|
||||
patchKsCoreStatus,
|
||||
createKsRole,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
package plugins
|
||||
|
||||
// ! Y ./ks-monitor/files/federated --> notification-manager
|
||||
// ~ N ./ks-monitor/files/gpu-monitoring
|
||||
// ~ Y ./ks-monitor/files/ks-istio-monitoring
|
||||
// ! Y ./ks-monitor/files/monitoring-dashboard
|
||||
// ! Y ./ks-monitor/files/notification-manager
|
||||
// ! Y ./ks-monitor/files/prometheus/alertmanager
|
||||
// ~ N ./ks-monitor/files/prometheus/etcd
|
||||
// ~ N ./ks-monitor/files/prometheus/grafana
|
||||
// ~ N ./ks-monitor/files/prometheus/kube-prometheus
|
||||
// ! Y ./ks-monitor/files/prometheus/kube-state-metrics
|
||||
// ! Y ./ks-monitor/files/prometheus/kubernetes
|
||||
// ! Y ./ks-monitor/files/prometheus/node-exporter
|
||||
// ! Y ./ks-monitor/files/prometheus/prometheus
|
||||
// ! Y ./ks-monitor/files/prometheus/prometheus-operator
|
||||
// ~ N ./ks-monitor/files/prometheus/thanos-ruler
|
||||
@@ -1,10 +1,7 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/beclab/Olares/cli/pkg/common"
|
||||
"github.com/beclab/Olares/cli/pkg/core/prepare"
|
||||
"github.com/beclab/Olares/cli/pkg/core/task"
|
||||
)
|
||||
|
||||
@@ -24,40 +21,3 @@ func (t *CopyEmbed) Init() {
|
||||
copyEmbed,
|
||||
}
|
||||
}
|
||||
|
||||
type DeployKsPluginsModule struct {
|
||||
common.KubeModule
|
||||
}
|
||||
|
||||
func (t *DeployKsPluginsModule) Init() {
|
||||
t.Name = "DeployKsPlugins"
|
||||
|
||||
checkNodeState := &task.RemoteTask{
|
||||
Name: "CheckNodeState",
|
||||
Hosts: t.Runtime.GetHostsByRole(common.Master),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
new(common.OnlyFirstMaster),
|
||||
new(NotEqualDesiredVersion),
|
||||
},
|
||||
Action: new(CheckNodeState),
|
||||
Parallel: false,
|
||||
Retry: 20,
|
||||
Delay: 10 * time.Second,
|
||||
}
|
||||
|
||||
initNs := &task.RemoteTask{
|
||||
Name: "InitKsNamespace",
|
||||
Hosts: t.Runtime.GetHostsByRole(common.Master),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
new(common.OnlyFirstMaster),
|
||||
new(NotEqualDesiredVersion),
|
||||
},
|
||||
Action: new(InitNamespace),
|
||||
Parallel: false,
|
||||
}
|
||||
|
||||
t.Tasks = []task.Interface{
|
||||
checkNodeState,
|
||||
initNs,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
|
||||
"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/prepare"
|
||||
"github.com/beclab/Olares/cli/pkg/core/task"
|
||||
"github.com/beclab/Olares/cli/pkg/core/util"
|
||||
)
|
||||
|
||||
type InstallMonitorDashboardCrd struct {
|
||||
common.KubeAction
|
||||
}
|
||||
|
||||
func (t *InstallMonitorDashboardCrd) Execute(runtime connector.Runtime) error {
|
||||
var kubectlpath, err = util.GetCommand(common.CommandKubectl)
|
||||
if err != nil {
|
||||
return fmt.Errorf("kubectl not found")
|
||||
}
|
||||
|
||||
var p = path.Join(runtime.GetInstallerDir(), cc.BuildFilesCacheDir, cc.BuildDir, "ks-monitor", "monitoring-dashboard")
|
||||
var cmd = fmt.Sprintf("%s apply -f %s", kubectlpath, p)
|
||||
if _, err := runtime.GetRunner().SudoCmd(cmd, false, true); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type CreateMonitorDashboardModule struct {
|
||||
common.KubeModule
|
||||
}
|
||||
|
||||
func (m *CreateMonitorDashboardModule) Init() {
|
||||
m.Name = "CreateMonitorDashboardModule"
|
||||
|
||||
installMonitorDashboardCrd := &task.RemoteTask{
|
||||
Name: "InstallMonitorDashboardCrd",
|
||||
Hosts: m.Runtime.GetHostsByRole(common.Master),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
new(common.OnlyFirstMaster),
|
||||
new(NotEqualDesiredVersion),
|
||||
},
|
||||
Action: new(InstallMonitorDashboardCrd),
|
||||
Parallel: false,
|
||||
Retry: 0,
|
||||
}
|
||||
|
||||
m.Tasks = []task.Interface{
|
||||
installMonitorDashboardCrd,
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,14 +17,8 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/beclab/Olares/cli/pkg/common"
|
||||
"github.com/beclab/Olares/cli/pkg/core/connector"
|
||||
"github.com/beclab/Olares/cli/pkg/utils"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type IsCloudInstance struct {
|
||||
@@ -43,72 +37,3 @@ func (p *IsCloudInstance) PreCheck(runtime connector.Runtime) (bool, error) {
|
||||
}
|
||||
return p.Not, nil
|
||||
}
|
||||
|
||||
type CheckStorageClass struct {
|
||||
common.KubePrepare
|
||||
}
|
||||
|
||||
func (p *CheckStorageClass) PreCheck(runtime connector.Runtime) (bool, error) {
|
||||
var kubectlpath, _ = p.PipelineCache.GetMustString(common.CacheCommandKubectlPath)
|
||||
if kubectlpath == "" {
|
||||
kubectlpath = path.Join(common.BinDir, common.CommandKubectl)
|
||||
}
|
||||
|
||||
var cmd = fmt.Sprintf("%s get sc | awk '{if(NR>1){print $1}}'", kubectlpath)
|
||||
stdout, err := runtime.GetRunner().SudoCmd(cmd, false, true)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(errors.WithStack(err), "get storageclass failed")
|
||||
}
|
||||
if stdout == "" {
|
||||
return false, fmt.Errorf("no storageclass found")
|
||||
}
|
||||
|
||||
cmd = fmt.Sprintf("%s get sc --no-headers", kubectlpath)
|
||||
stdout, err = runtime.GetRunner().SudoCmd(cmd, false, true)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(errors.WithStack(err), "get storageclass failed")
|
||||
}
|
||||
|
||||
if stdout == "" {
|
||||
return false, fmt.Errorf("no storageclass found")
|
||||
}
|
||||
|
||||
if !strings.Contains(stdout, "(default)") {
|
||||
return false, fmt.Errorf("default storageclass was not found")
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
type GenerateRedisPassword struct {
|
||||
common.KubePrepare
|
||||
}
|
||||
|
||||
func (p *GenerateRedisPassword) PreCheck(runtime connector.Runtime) (bool, error) {
|
||||
pass, err := utils.GeneratePassword(15)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if pass == "" {
|
||||
return false, fmt.Errorf("failed to generate redis password")
|
||||
}
|
||||
|
||||
p.PipelineCache.Set(common.CacheRedisPassword, pass)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
type NotEqualDesiredVersion struct {
|
||||
common.KubePrepare
|
||||
}
|
||||
|
||||
func (n *NotEqualDesiredVersion) PreCheck(runtime connector.Runtime) (bool, error) {
|
||||
ksVersion, ok := n.PipelineCache.GetMustString(common.KubeSphereVersion)
|
||||
if !ok {
|
||||
ksVersion = ""
|
||||
}
|
||||
|
||||
if n.KubeConf.Cluster.KubeSphere.Version == ksVersion {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -118,7 +118,6 @@ func (m *DeployPrometheusModule) Init() {
|
||||
Hosts: m.Runtime.GetHostsByRole(common.Master),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
new(common.OnlyFirstMaster),
|
||||
new(NotEqualDesiredVersion),
|
||||
},
|
||||
Action: new(CreateOperator),
|
||||
Parallel: false,
|
||||
@@ -130,7 +129,6 @@ func (m *DeployPrometheusModule) Init() {
|
||||
Hosts: m.Runtime.GetHostsByRole(common.Master),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
new(common.OnlyFirstMaster),
|
||||
new(NotEqualDesiredVersion),
|
||||
},
|
||||
Action: &CreatePrometheusComponent{
|
||||
Component: "node-exporter",
|
||||
@@ -145,7 +143,6 @@ func (m *DeployPrometheusModule) Init() {
|
||||
Hosts: m.Runtime.GetHostsByRole(common.Master),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
new(common.OnlyFirstMaster),
|
||||
new(NotEqualDesiredVersion),
|
||||
},
|
||||
Action: &CreatePrometheusComponent{
|
||||
Component: "kube-state-metrics",
|
||||
@@ -160,7 +157,6 @@ func (m *DeployPrometheusModule) Init() {
|
||||
Hosts: m.Runtime.GetHostsByRole(common.Master),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
new(common.OnlyFirstMaster),
|
||||
new(NotEqualDesiredVersion),
|
||||
},
|
||||
Action: &CreatePrometheusComponent{
|
||||
Component: "prometheus",
|
||||
@@ -173,7 +169,6 @@ func (m *DeployPrometheusModule) Init() {
|
||||
Hosts: m.Runtime.GetHostsByRole(common.Master),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
new(common.OnlyFirstMaster),
|
||||
new(NotEqualDesiredVersion),
|
||||
},
|
||||
Action: &CreatePrometheusComponent{
|
||||
Component: "kubernetes",
|
||||
@@ -182,26 +177,12 @@ func (m *DeployPrometheusModule) Init() {
|
||||
Parallel: false,
|
||||
}
|
||||
|
||||
//createAlertManager := &task.RemoteTask{
|
||||
// Name: "CreateAlertManager",
|
||||
// Hosts: m.Runtime.GetHostsByRole(common.Master),
|
||||
// Prepare: &prepare.PrepareCollection{
|
||||
// new(common.OnlyFirstMaster),
|
||||
// new(NotEqualDesiredVersion),
|
||||
// },
|
||||
// Action: &CreatePrometheusComponent{
|
||||
// Component: "alertmanager",
|
||||
// },
|
||||
// Parallel: false,
|
||||
//}
|
||||
|
||||
m.Tasks = []task.Interface{
|
||||
createOperator,
|
||||
createNodeExporter,
|
||||
createKubeStateMetrics,
|
||||
createPrometheus,
|
||||
createKubeMonitor,
|
||||
//createAlertManager,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"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/prepare"
|
||||
"github.com/beclab/Olares/cli/pkg/core/task"
|
||||
"github.com/beclab/Olares/cli/pkg/core/util"
|
||||
"github.com/beclab/Olares/cli/pkg/utils"
|
||||
"github.com/pkg/errors"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
)
|
||||
|
||||
type CreateRedisSecret struct {
|
||||
common.KubeAction
|
||||
}
|
||||
|
||||
func (t *CreateRedisSecret) Execute(runtime connector.Runtime) error {
|
||||
kubectlpath, err := util.GetCommand(common.CommandKubectl)
|
||||
if err != nil {
|
||||
return fmt.Errorf("kubectl not found")
|
||||
}
|
||||
|
||||
redisPwd, ok := t.PipelineCache.Get(common.CacheRedisPassword)
|
||||
if !ok {
|
||||
return fmt.Errorf("get redis password from module cache failed")
|
||||
}
|
||||
|
||||
if stdout, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("%s -n %s create secret generic redis-secret --from-literal=auth=%s", kubectlpath, common.NamespaceKubesphereSystem, redisPwd), false, true); err != nil {
|
||||
if err != nil && !strings.Contains(stdout, "already exists") {
|
||||
return errors.Wrap(errors.WithStack(err), "create redis secret failed")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type BackupRedisManifests struct {
|
||||
common.KubeAction
|
||||
}
|
||||
|
||||
func (t *BackupRedisManifests) Execute(runtime connector.Runtime) error {
|
||||
kubectlpath, err := util.GetCommand(common.CommandKubectl)
|
||||
if err != nil {
|
||||
return fmt.Errorf("kubectl not found")
|
||||
}
|
||||
|
||||
rver, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("%s get pod -n %s -l app=%s,tier=database,version=%s-4.0 | wc -l",
|
||||
kubectlpath, common.NamespaceKubesphereSystem, common.ChartNameRedis, common.ChartNameRedis), false, false)
|
||||
|
||||
if err != nil || strings.Contains(rver, "No resources found") {
|
||||
return nil
|
||||
}
|
||||
rver = strings.ReplaceAll(rver, "No resources found in kubesphere-system namespace.", "")
|
||||
rver = strings.ReplaceAll(rver, "\r\n", "")
|
||||
rver = strings.ReplaceAll(rver, "\n", "")
|
||||
if rver != "0" {
|
||||
var cmd = fmt.Sprintf("%s get svc -n %s %s -o yaml > %s/redis-svc-backup.yaml && %s delete svc -n %s %s",
|
||||
kubectlpath,
|
||||
common.NamespaceKubesphereSystem, common.ChartNameRedis,
|
||||
common.KubeManifestDir, // todo need fix cross platforms
|
||||
kubectlpath,
|
||||
common.NamespaceKubesphereSystem, common.ChartNameRedis)
|
||||
|
||||
if _, err := runtime.GetRunner().SudoCmd(cmd, false, true); err != nil {
|
||||
logger.Errorf("failed to backup %s svc: %v", common.ChartNameRedis, err)
|
||||
return errors.Wrap(errors.WithStack(err), "backup redis svc failed")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type DeployRedis struct {
|
||||
common.KubeAction
|
||||
}
|
||||
|
||||
func (t *DeployRedis) Execute(runtime connector.Runtime) error {
|
||||
config, err := ctrl.GetConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var appName = common.ChartNameRedis
|
||||
var appPath = path.Join(runtime.GetInstallerDir(), cc.BuildFilesCacheDir, cc.BuildDir, appName)
|
||||
|
||||
actionConfig, settings, err := utils.InitConfig(config, common.NamespaceKubesphereSystem)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var ctx, cancel = context.WithTimeout(context.Background(), 3*time.Minute)
|
||||
defer cancel()
|
||||
|
||||
if err := utils.UpgradeCharts(ctx, actionConfig, settings, appName, appPath, "", common.NamespaceKubesphereSystem, nil, false); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// +++++
|
||||
|
||||
type DeployRedisModule struct {
|
||||
common.KubeModule
|
||||
}
|
||||
|
||||
func (m *DeployRedisModule) Init() {
|
||||
m.Name = "DeployRedis"
|
||||
|
||||
createRedisSecret := &task.RemoteTask{
|
||||
Name: "CreateRedisSecret",
|
||||
Hosts: m.Runtime.GetHostsByRole(common.Master),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
new(common.OnlyFirstMaster),
|
||||
new(NotEqualDesiredVersion),
|
||||
new(GenerateRedisPassword),
|
||||
},
|
||||
Action: new(CreateRedisSecret),
|
||||
Parallel: false,
|
||||
Retry: 0,
|
||||
}
|
||||
|
||||
backupRedisManifests := &task.RemoteTask{
|
||||
Name: "BackupRedisManifests",
|
||||
Hosts: m.Runtime.GetHostsByRole(common.Master),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
new(common.OnlyFirstMaster),
|
||||
new(NotEqualDesiredVersion),
|
||||
},
|
||||
Action: new(BackupRedisManifests),
|
||||
Parallel: false,
|
||||
Retry: 0,
|
||||
}
|
||||
|
||||
deployRedis := &task.RemoteTask{
|
||||
Name: "DeployRedis",
|
||||
Hosts: m.Runtime.GetHostsByRole(common.Master),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
new(common.OnlyFirstMaster),
|
||||
new(NotEqualDesiredVersion),
|
||||
new(CheckStorageClass),
|
||||
},
|
||||
Action: new(DeployRedis),
|
||||
Parallel: false,
|
||||
Retry: 0,
|
||||
}
|
||||
|
||||
m.Tasks = []task.Interface{
|
||||
createRedisSecret,
|
||||
backupRedisManifests,
|
||||
deployRedis,
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,12 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"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/utils"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type CopyEmbedFiles struct {
|
||||
@@ -21,97 +17,3 @@ func (t *CopyEmbedFiles) Execute(runtime connector.Runtime) error {
|
||||
var dst = path.Join(runtime.GetInstallerDir(), cc.BuildFilesCacheDir)
|
||||
return utils.CopyEmbed(assets, ".", dst)
|
||||
}
|
||||
|
||||
type CheckNodeState struct {
|
||||
common.KubeAction
|
||||
}
|
||||
|
||||
func (t *CheckNodeState) Execute(runtime connector.Runtime) error {
|
||||
var kubectlpath, _ = t.PipelineCache.GetMustString(common.CacheCommandKubectlPath)
|
||||
if kubectlpath == "" {
|
||||
kubectlpath = path.Join(common.BinDir, common.CommandKubectl)
|
||||
}
|
||||
var cmd = fmt.Sprintf("%s get node --no-headers", kubectlpath)
|
||||
stdout, err := runtime.GetRunner().SudoCmd(cmd, false, false)
|
||||
|
||||
if err != nil || stdout == "" {
|
||||
return fmt.Errorf("Node Pending")
|
||||
}
|
||||
|
||||
var nodeInfo = strings.Fields(stdout)
|
||||
if len(nodeInfo) != 5 {
|
||||
logger.Errorf("node info invalid: %s", stdout)
|
||||
return fmt.Errorf("Node Pending")
|
||||
}
|
||||
|
||||
var state = nodeInfo[1]
|
||||
var version = nodeInfo[4]
|
||||
|
||||
if state != "Ready" {
|
||||
return fmt.Errorf("Node Pending")
|
||||
}
|
||||
t.PipelineCache.Set(common.CacheKubeletVersion, version)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type InitNamespace struct {
|
||||
common.KubeAction
|
||||
}
|
||||
|
||||
func (t *InitNamespace) Execute(runtime connector.Runtime) error {
|
||||
var kubectlpath, _ = t.PipelineCache.GetMustString(common.CacheCommandKubectlPath)
|
||||
if kubectlpath == "" {
|
||||
kubectlpath = path.Join(common.BinDir, common.CommandKubectl)
|
||||
}
|
||||
|
||||
for _, ns := range []string{common.NamespaceKubesphereControlsSystem} {
|
||||
if stdout, err := runtime.GetRunner().Cmd(fmt.Sprintf("%s create ns %s", kubectlpath, ns), false, true); err != nil {
|
||||
if !strings.Contains(stdout, "already exists") {
|
||||
logger.Errorf("create ns %s failed: %v", ns, err)
|
||||
return errors.Wrap(errors.WithStack(err), fmt.Sprintf("create namespace %s failed: %v", ns, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
// _, err := runtime.GetRunner().SudoCmd(
|
||||
// fmt.Sprintf(`cat <<EOF | /usr/local/bin/kubectl apply -f -
|
||||
// apiVersion: v1
|
||||
// kind: Namespace
|
||||
// metadata:
|
||||
// name: %s
|
||||
// ---
|
||||
// apiVersion: v1
|
||||
// kind: Namespace
|
||||
// metadata:
|
||||
// name: %s
|
||||
// EOF
|
||||
// `, common.NamespaceKubesphereControlsSystem, common.NamespaceKubesphereMonitoringFederated), false, true)
|
||||
// if err != nil {
|
||||
// return errors.Wrap(errors.WithStack(err), fmt.Sprintf("create namespace: %s and %s",
|
||||
// common.NamespaceKubesphereControlsSystem, common.NamespaceKubesphereMonitoringFederated))
|
||||
// }
|
||||
|
||||
var allNs = []string{
|
||||
common.NamespaceDefault,
|
||||
common.NamespaceKubeNodeLease,
|
||||
common.NamespaceKubePublic,
|
||||
common.NamespaceKubeSystem,
|
||||
common.NamespaceKubekeySystem,
|
||||
common.NamespaceKubesphereControlsSystem,
|
||||
common.NamespaceKubesphereSystem,
|
||||
}
|
||||
|
||||
for _, ns := range allNs {
|
||||
if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("%s label ns %s kubesphere.io/workspace=system-workspace --overwrite", kubectlpath, ns), false, true); err != nil {
|
||||
logger.Errorf("label ns %s kubesphere.io/workspace=system-workspace failed: %v", ns, err)
|
||||
return errors.Wrap(errors.WithStack(err), fmt.Sprintf("label namespace %s kubesphere.io/workspace=system-workspace failed: %v", ns, err))
|
||||
}
|
||||
|
||||
if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("%s label ns %s kubesphere.io/namespace=%s --overwrite", kubectlpath, ns, ns), false, true); err != nil {
|
||||
logger.Errorf("label ns %s kubesphere.io/namespace=%s failed: %v", ns, ns, err)
|
||||
return errors.Wrap(errors.WithStack(err), fmt.Sprintf("label namespace %s kubesphere.io/namespace=%s failed: %v", ns, ns, err))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/beclab/Olares/cli/pkg/common"
|
||||
"github.com/beclab/Olares/cli/pkg/core/connector"
|
||||
"github.com/beclab/Olares/cli/pkg/core/logger"
|
||||
"github.com/beclab/Olares/cli/pkg/core/prepare"
|
||||
"github.com/beclab/Olares/cli/pkg/core/task"
|
||||
"github.com/beclab/Olares/cli/pkg/core/util"
|
||||
"github.com/beclab/Olares/cli/pkg/utils"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type GenerateKubeSphereToken struct {
|
||||
common.KubeAction
|
||||
}
|
||||
|
||||
func (t *GenerateKubeSphereToken) Execute(runtime connector.Runtime) error {
|
||||
var kubectlpath, _ = t.PipelineCache.GetMustString(common.CacheCommandKubectlPath)
|
||||
if kubectlpath == "" {
|
||||
kubectlpath = path.Join(common.BinDir, common.CommandKubectl)
|
||||
}
|
||||
|
||||
var random, err = utils.GeneratePassword(32)
|
||||
if err != nil {
|
||||
logger.Errorf("failed to generate password: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
token, err := util.EncryptToken(random)
|
||||
if err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "create kubesphere token failed")
|
||||
}
|
||||
|
||||
var cmd = fmt.Sprintf("%s get secrets -n %s --no-headers", kubectlpath, common.NamespaceKubesphereSystem)
|
||||
stdout, _ := runtime.GetRunner().SudoCmd(cmd, false, false)
|
||||
if strings.Contains(stdout, "kubesphere-secret") {
|
||||
cmd = fmt.Sprintf("%s delete secrets -n %s kubesphere-secret", kubectlpath, common.NamespaceKubesphereSystem)
|
||||
runtime.GetRunner().SudoCmd(cmd, false, true)
|
||||
}
|
||||
|
||||
cmd = fmt.Sprintf("%s create secret generic kubesphere-secret --from-literal=token=%s --from-literal=secret=%s -n %s", kubectlpath,
|
||||
token, random, common.NamespaceKubesphereSystem)
|
||||
if _, err := runtime.GetRunner().SudoCmd(cmd, false, true); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "create kubesphere token failed")
|
||||
}
|
||||
|
||||
t.PipelineCache.Set(common.CacheJwtSecret, random)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// +++++
|
||||
|
||||
type CreateKubeSphereSecretModule struct {
|
||||
common.KubeModule
|
||||
}
|
||||
|
||||
func (m *CreateKubeSphereSecretModule) Init() {
|
||||
m.Name = "CreateKubeSphereSecret"
|
||||
|
||||
generateKubeSphereToken := &task.RemoteTask{
|
||||
Name: "GenerateKubeSphereToken",
|
||||
Hosts: m.Runtime.GetHostsByRole(common.Master),
|
||||
Prepare: &prepare.PrepareCollection{
|
||||
new(common.OnlyFirstMaster),
|
||||
new(NotEqualDesiredVersion),
|
||||
},
|
||||
Action: new(GenerateKubeSphereToken),
|
||||
Parallel: false,
|
||||
Retry: 0,
|
||||
}
|
||||
|
||||
m.Tasks = []task.Interface{generateKubeSphereToken}
|
||||
}
|
||||
@@ -1,57 +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 kubesphere
|
||||
|
||||
import (
|
||||
"github.com/beclab/Olares/cli/pkg/common"
|
||||
"github.com/beclab/Olares/cli/pkg/core/connector"
|
||||
"github.com/pkg/errors"
|
||||
versionutil "k8s.io/apimachinery/pkg/util/version"
|
||||
)
|
||||
|
||||
type VersionBelowV3 struct {
|
||||
common.KubePrepare
|
||||
}
|
||||
|
||||
func (v *VersionBelowV3) PreCheck(runtime connector.Runtime) (bool, error) {
|
||||
versionStr, ok := v.PipelineCache.GetMustString(common.KubeSphereVersion)
|
||||
if !ok {
|
||||
return false, errors.New("get current kubesphere version failed by pipeline cache")
|
||||
}
|
||||
version := versionutil.MustParseSemantic(versionStr)
|
||||
v300 := versionutil.MustParseSemantic("v3.0.0")
|
||||
if v.KubeConf.Cluster.KubeSphere.Enabled && v.KubeConf.Cluster.KubeSphere.Version == "v3.0.0" && version.LessThan(v300) {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
type NotEqualDesiredVersion struct {
|
||||
common.KubePrepare
|
||||
}
|
||||
|
||||
func (n *NotEqualDesiredVersion) PreCheck(runtime connector.Runtime) (bool, error) {
|
||||
ksVersion, ok := n.PipelineCache.GetMustString(common.KubeSphereVersion)
|
||||
if !ok {
|
||||
ksVersion = ""
|
||||
}
|
||||
|
||||
if n.KubeConf.Cluster.KubeSphere.Version == ksVersion {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
@@ -18,18 +18,12 @@ package kubesphere
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
kubekeyapiv1alpha2 "github.com/beclab/Olares/cli/apis/kubekey/v1alpha2"
|
||||
"github.com/beclab/Olares/cli/pkg/common"
|
||||
"github.com/beclab/Olares/cli/pkg/core/connector"
|
||||
"github.com/beclab/Olares/cli/pkg/core/logger"
|
||||
"github.com/beclab/Olares/cli/pkg/core/util"
|
||||
"github.com/beclab/Olares/cli/pkg/version/kubesphere"
|
||||
"github.com/beclab/Olares/cli/pkg/version/kubesphere/templates"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -52,27 +46,6 @@ func (d *DeleteKubeSphereCaches) Execute(runtime connector.Runtime) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type AddInstallerConfig struct {
|
||||
common.KubeAction
|
||||
}
|
||||
|
||||
func (a *AddInstallerConfig) Execute(runtime connector.Runtime) error {
|
||||
//var ksFilename string
|
||||
|
||||
// if runtime.GetSystemInfo().IsDarwin() {
|
||||
// ksFilename = path.Join(common.TmpDir, "/etc/kubernetes/addons/kubesphere.yaml")
|
||||
// } else {
|
||||
//ksFilename = "/etc/kubernetes/addons/kubesphere.yaml"
|
||||
//// }
|
||||
//configurationBase64 := base64.StdEncoding.EncodeToString([]byte(a.KubeConf.Cluster.KubeSphere.Configurations))
|
||||
//if _, err := runtime.GetRunner().SudoCmd(
|
||||
// fmt.Sprintf("echo %s | base64 -d >> %s", configurationBase64, ksFilename),
|
||||
// false, false); err != nil {
|
||||
// return errors.Wrap(errors.WithStack(err), "add config to ks-installer manifests failed")
|
||||
//}
|
||||
return nil
|
||||
}
|
||||
|
||||
type CreateNamespace struct {
|
||||
common.KubeAction
|
||||
}
|
||||
@@ -91,6 +64,11 @@ metadata:
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: kubesphere-controls-system
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: kubesphere-monitoring-system
|
||||
EOF`, kubectl)
|
||||
@@ -101,235 +79,6 @@ EOF`, kubectl)
|
||||
return nil
|
||||
}
|
||||
|
||||
type Setup struct {
|
||||
common.KubeAction
|
||||
}
|
||||
|
||||
func (s *Setup) Execute(runtime connector.Runtime) error {
|
||||
nodeIp, _ := s.PipelineCache.GetMustString(common.CacheMinikubeNodeIp)
|
||||
filePath := filepath.Join(common.KubeAddonsDir, templates.KsInstaller.Name())
|
||||
|
||||
var minikubepath, ok = s.PipelineCache.GetMustString(common.CacheCommandMinikubePath)
|
||||
if !ok || minikubepath == "" {
|
||||
minikubepath = path.Join(common.BinDir, common.CommandMinikube)
|
||||
}
|
||||
|
||||
kubectlpath, ok := s.PipelineCache.GetMustString(common.CacheCommandKubectlPath)
|
||||
if !ok || kubectlpath == "" {
|
||||
kubectlpath = path.Join(common.BinDir, common.CommandKubectl)
|
||||
}
|
||||
|
||||
var addrList []string
|
||||
var tlsDisable bool
|
||||
var port string
|
||||
switch s.KubeConf.Cluster.Etcd.Type {
|
||||
case kubekeyapiv1alpha2.KubeKey:
|
||||
for _, host := range runtime.GetHostsByRole(common.ETCD) {
|
||||
addrList = append(addrList, host.GetInternalAddress())
|
||||
}
|
||||
|
||||
caFile := "/etc/ssl/etcd/ssl/ca.pem"
|
||||
certFile := fmt.Sprintf("/etc/ssl/etcd/ssl/node-%s.pem", runtime.RemoteHost().GetName())
|
||||
keyFile := fmt.Sprintf("/etc/ssl/etcd/ssl/node-%s-key.pem", runtime.RemoteHost().GetName())
|
||||
if output, err := runtime.GetRunner().SudoCmd(
|
||||
fmt.Sprintf("/usr/local/bin/kubectl -n kubesphere-monitoring-system create secret generic kube-etcd-client-certs "+
|
||||
"--from-file=etcd-client-ca.crt=%s "+
|
||||
"--from-file=etcd-client.crt=%s "+
|
||||
"--from-file=etcd-client.key=%s", caFile, certFile, keyFile), false, false); err != nil {
|
||||
if !strings.Contains(output, "exists") {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case kubekeyapiv1alpha2.MiniKube:
|
||||
var etcdPath = common.KubeEtcdCertDir // path.Join(common.TmpDir, common.KubeEtcdCertDir)
|
||||
if !util.IsExist(etcdPath) {
|
||||
if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("mkdir -p %s", etcdPath), false, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
var certfiles = []string{
|
||||
"ca.crt",
|
||||
"server.crt",
|
||||
"server.key",
|
||||
}
|
||||
|
||||
for _, certfile := range certfiles {
|
||||
var cfile = path.Join(common.MinikubeEtcdCertDir, certfile)
|
||||
var cmd = fmt.Sprintf("%s -p %s ssh sudo chmod 644 %s && minikube -p %s cp %s:%s %s", minikubepath,
|
||||
runtime.RemoteHost().GetMinikubeProfile(), cfile,
|
||||
runtime.RemoteHost().GetMinikubeProfile(), runtime.RemoteHost().GetMinikubeProfile(),
|
||||
cfile, path.Join(etcdPath, certfile))
|
||||
if _, err := runtime.GetRunner().SudoCmd(cmd, false, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
caFile := path.Join(etcdPath, "ca.crt")
|
||||
certFile := path.Join(etcdPath, "server.crt")
|
||||
keyFile := path.Join(etcdPath, "server.key")
|
||||
|
||||
addrList = append(addrList, nodeIp)
|
||||
if output, err := runtime.GetRunner().SudoCmd(
|
||||
fmt.Sprintf("%s -n kubesphere-monitoring-system create secret generic kube-etcd-client-certs "+
|
||||
"--from-file=%s "+
|
||||
"--from-file=%s "+
|
||||
"--from-file=%s", kubectlpath, caFile, certFile, keyFile), false, false); err != nil {
|
||||
if !strings.Contains(output, "already exists") {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
//path.Join(common.TmpDir, filepath.Join(common.KubeAddonsDir, templates.KsInstaller.Name()))
|
||||
filePath = path.Join(filepath.Join(common.KubeAddonsDir, templates.KsInstaller.Name()))
|
||||
case kubekeyapiv1alpha2.Kubeadm:
|
||||
for _, host := range runtime.GetHostsByRole(common.Master) {
|
||||
addrList = append(addrList, host.GetInternalAddress())
|
||||
}
|
||||
|
||||
caFile := "/etc/kubernetes/pki/etcd/ca.crt"
|
||||
certFile := "/etc/kubernetes/pki/etcd/healthcheck-client.crt"
|
||||
keyFile := "/etc/kubernetes/pki/etcd/healthcheck-client.key"
|
||||
if output, err := runtime.GetRunner().SudoCmd(
|
||||
fmt.Sprintf("/usr/local/bin/kubectl -n kubesphere-monitoring-system create secret generic kube-etcd-client-certs "+
|
||||
"--from-file=etcd-client-ca.crt=%s "+
|
||||
"--from-file=etcd-client.crt=%s "+
|
||||
"--from-file=etcd-client.key=%s", caFile, certFile, keyFile), false, false); err != nil {
|
||||
if !strings.Contains(output, "exists") {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case kubekeyapiv1alpha2.External:
|
||||
for _, endpoint := range s.KubeConf.Cluster.Etcd.External.Endpoints {
|
||||
e := strings.Split(strings.TrimSpace(endpoint), "://")
|
||||
s := strings.Split(e[1], ":")
|
||||
port = s[1]
|
||||
addrList = append(addrList, s[0])
|
||||
if e[0] == "http" {
|
||||
tlsDisable = true
|
||||
}
|
||||
}
|
||||
if tlsDisable {
|
||||
if output, err := runtime.GetRunner().SudoCmd("/usr/local/bin/kubectl -n kubesphere-monitoring-system create secret generic kube-etcd-client-certs", true, false); err != nil {
|
||||
if !strings.Contains(output, "exists") {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
caFile := fmt.Sprintf("/etc/ssl/etcd/ssl/%s", filepath.Base(s.KubeConf.Cluster.Etcd.External.CAFile))
|
||||
certFile := fmt.Sprintf("/etc/ssl/etcd/ssl/%s", filepath.Base(s.KubeConf.Cluster.Etcd.External.CertFile))
|
||||
keyFile := fmt.Sprintf("/etc/ssl/etcd/ssl/%s", filepath.Base(s.KubeConf.Cluster.Etcd.External.KeyFile))
|
||||
if output, err := runtime.GetRunner().SudoCmd(
|
||||
fmt.Sprintf("/usr/local/bin/kubectl -n kubesphere-monitoring-system create secret generic kube-etcd-client-certs "+
|
||||
"--from-file=etcd-client-ca.crt=%s "+
|
||||
"--from-file=etcd-client.crt=%s "+
|
||||
"--from-file=etcd-client.key=%s", caFile, certFile, keyFile), true, false); err != nil {
|
||||
if !strings.Contains(output, "exists") {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var sedCommand = runtime.GetCommandSed()
|
||||
etcdEndPoint := strings.Join(addrList, ",")
|
||||
var cmdEndpoint = fmt.Sprintf("%s '/endpointIps/s/\\:.*/\\: %s/g' %s", sedCommand, etcdEndPoint, filePath)
|
||||
if _, err := runtime.GetRunner().SudoCmd(cmdEndpoint, false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), fmt.Sprintf("update etcd endpoint failed"))
|
||||
}
|
||||
|
||||
if tlsDisable {
|
||||
if _, err := runtime.GetRunner().SudoCmd(
|
||||
fmt.Sprintf("%s '/tlsEnable/s/\\:.*/\\: false/g' %s", sedCommand, filePath),
|
||||
false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), fmt.Sprintf("update etcd tls failed"))
|
||||
}
|
||||
}
|
||||
|
||||
if len(port) != 0 {
|
||||
if _, err := runtime.GetRunner().SudoCmd(
|
||||
fmt.Sprintf("%s 's/2379/%s/g' %s", sedCommand, port, filePath),
|
||||
false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), fmt.Sprintf("update etcd tls failed"))
|
||||
}
|
||||
}
|
||||
|
||||
if s.KubeConf.Cluster.Registry.PrivateRegistry != "" {
|
||||
PrivateRegistry := strings.Replace(s.KubeConf.Cluster.Registry.PrivateRegistry, "/", "\\/", -1)
|
||||
if _, err := runtime.GetRunner().SudoCmd(
|
||||
fmt.Sprintf("%s '/local_registry/s/\\:.*/\\: %s/g' %s", sedCommand, PrivateRegistry, filePath),
|
||||
false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), fmt.Sprintf("add private registry: %s failed", s.KubeConf.Cluster.Registry.PrivateRegistry))
|
||||
}
|
||||
} else {
|
||||
if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("%s '/local_registry/d' %s", sedCommand, filePath), false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), fmt.Sprintf("remove private registry failed"))
|
||||
}
|
||||
}
|
||||
|
||||
if s.KubeConf.Cluster.Registry.NamespaceOverride != "" {
|
||||
if _, err := runtime.GetRunner().SudoCmd(
|
||||
fmt.Sprintf("%s '/namespace_override/s/\\:.*/\\: %s/g' %s", sedCommand, s.KubeConf.Cluster.Registry.NamespaceOverride, filePath),
|
||||
false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), fmt.Sprintf("add namespace override: %s failed", s.KubeConf.Cluster.Registry.NamespaceOverride))
|
||||
}
|
||||
} else {
|
||||
if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("%s '/namespace_override/d' %s", sedCommand, filePath), false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), fmt.Sprintf("remove namespace override failed"))
|
||||
}
|
||||
}
|
||||
|
||||
_, ok = kubesphere.CNSource[s.KubeConf.Cluster.KubeSphere.Version]
|
||||
if ok && (os.Getenv("KKZONE") == "cn" || s.KubeConf.Cluster.Registry.PrivateRegistry == "registry.cn-beijing.aliyuncs.com") {
|
||||
if _, err := runtime.GetRunner().SudoCmd(
|
||||
fmt.Sprintf("%s '/zone/s/\\:.*/\\: %s/g' %s", sedCommand, "cn", filePath),
|
||||
false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), fmt.Sprintf("add kubekey zone: %s failed", s.KubeConf.Cluster.Registry.PrivateRegistry))
|
||||
}
|
||||
} else {
|
||||
if _, err := runtime.GetRunner().SudoCmd(
|
||||
fmt.Sprintf("%s '/zone/d' %s", sedCommand, filePath),
|
||||
false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), fmt.Sprintf("remove kubekey zone failed"))
|
||||
}
|
||||
}
|
||||
|
||||
switch s.KubeConf.Cluster.Kubernetes.ContainerManager {
|
||||
case "docker", "containerd", "crio":
|
||||
if _, err := runtime.GetRunner().SudoCmd(
|
||||
fmt.Sprintf("%s '/containerruntime/s/\\:.*/\\: %s/g' %s", sedCommand, s.KubeConf.Cluster.Kubernetes.ContainerManager, filePath), false, false); err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), fmt.Sprintf("set container runtime: %s failed", s.KubeConf.Cluster.Kubernetes.ContainerManager))
|
||||
}
|
||||
default:
|
||||
logger.Infof(
|
||||
fmt.Sprintf("%s Currently, the logging module of KubeSphere does not support %s. If %s is used, the logging module will be unavailable.", runtime.RemoteHost().GetName(),
|
||||
s.KubeConf.Cluster.Kubernetes.ContainerManager, s.KubeConf.Cluster.Kubernetes.ContainerManager))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type Apply struct {
|
||||
common.KubeAction
|
||||
}
|
||||
|
||||
func (a *Apply) Execute(runtime connector.Runtime) error {
|
||||
var kubectlpath, ok = a.PipelineCache.GetMustString(common.CacheCommandKubectlPath)
|
||||
if !ok || kubectlpath == "" {
|
||||
kubectlpath = path.Join(common.BinDir, common.CommandKubectl)
|
||||
}
|
||||
|
||||
filePath := filepath.Join(common.KubeAddonsDir, templates.KsInstaller.Name())
|
||||
// if runtime.GetSystemInfo().IsDarwin() {
|
||||
// filePath = path.Join(common.TmpDir, filePath)
|
||||
// }
|
||||
|
||||
deployKubesphereCmd := fmt.Sprintf("%s apply -f %s --force", kubectlpath, filePath)
|
||||
if _, err := runtime.GetRunner().Cmd(deployKubesphereCmd, false, true); err != nil {
|
||||
return errors.Wrapf(errors.WithStack(err), "deploy %s failed", filePath)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type GetKubeCommand struct {
|
||||
common.KubeAction
|
||||
}
|
||||
|
||||
@@ -1,109 +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 v2
|
||||
|
||||
type V2 struct {
|
||||
Persistence Persistence `yaml:"persistence"`
|
||||
Common Common `yaml:"common"`
|
||||
Etcd Etcd `yaml:"etcd"`
|
||||
MetricsServerOld MetricsServerOld `yaml:"metrics-server"`
|
||||
MetricsServerNew MetricsServerNew `yaml:"metrics_server"`
|
||||
Console Console `yaml:"console"`
|
||||
Monitoring Monitoring `yaml:"monitoring"`
|
||||
Logging Logging `yaml:"logging"`
|
||||
Openpitrix Openpitrix `yaml:"openpitrix"`
|
||||
Devops Devops `yaml:"devops"`
|
||||
Servicemesh Servicemesh `yaml:"servicemesh"`
|
||||
Notification Notification `yaml:"notification"`
|
||||
Alerting Alerting `yaml:"alerting"`
|
||||
LocalRegistry string `yaml:"local_registry"`
|
||||
}
|
||||
|
||||
type Persistence struct {
|
||||
StorageClass string `yaml:"storageClass"`
|
||||
}
|
||||
type Etcd struct {
|
||||
Monitoring bool `yaml:"monitoring"`
|
||||
EndpointIps string `yaml:"endpointIps"`
|
||||
Port int `yaml:"port"`
|
||||
TlsEnable bool `yaml:"tlsEnable"`
|
||||
}
|
||||
|
||||
type Common struct {
|
||||
MysqlVolumeSize string `yaml:"mysqlVolumeSize"`
|
||||
MinioVolumeSize string `yaml:"minioVolumeSize"`
|
||||
EtcdVolumeSize string `yaml:"etcdVolumeSize"`
|
||||
OpenldapVolumeSize string `yaml:"openldapVolumeSize"`
|
||||
RedisVolumSize string `yaml:"redisVolumSize"`
|
||||
}
|
||||
|
||||
type MetricsServerOld struct {
|
||||
Enabled string `yaml:"enabled"`
|
||||
}
|
||||
|
||||
type MetricsServerNew struct {
|
||||
Enabled string `yaml:"enabled"`
|
||||
}
|
||||
|
||||
type Console struct {
|
||||
EnableMultiLogin bool `yaml:"enableMultiLogin"`
|
||||
Port int `yaml:"port"`
|
||||
}
|
||||
|
||||
type Monitoring struct {
|
||||
PrometheusReplicas int `yaml:"prometheusReplicas"`
|
||||
PrometheusMemoryRequest string `yaml:"prometheusMemoryRequest"`
|
||||
PrometheusVolumeSize string `yaml:"prometheusVolumeSize"`
|
||||
}
|
||||
|
||||
type Logging struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
ElasticsearchMasterReplicas int `yaml:"elasticsearchMasterReplicas"`
|
||||
ElasticsearchDataReplicas int `yaml:"elasticsearchDataReplicas"`
|
||||
LogsidecarReplicas int `yaml:"logsidecarReplicas"`
|
||||
ElasticsearchVolumeSize string `yaml:"elasticsearchVolumeSize"`
|
||||
ElasticsearchMasterVolumeSize string `yaml:"elasticsearchMasterVolumeSize"`
|
||||
ElasticsearchDataVolumeSize string `yaml:"elasticsearchDataVolumeSize"`
|
||||
LogMaxAge int `yaml:"logMaxAge"`
|
||||
ElkPrefix string `yaml:"elkPrefix"`
|
||||
}
|
||||
|
||||
type Openpitrix struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
}
|
||||
|
||||
type Devops struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
JenkinsMemoryLim string `yaml:"jenkinsMemoryLim"`
|
||||
JenkinsMemoryReq string `yaml:"jenkinsMemoryReq"`
|
||||
JenkinsVolumeSize string `yaml:"jenkinsVolumeSize"`
|
||||
JenkinsjavaoptsXms string `yaml:"jenkinsJavaOpts_Xms"`
|
||||
JenkinsjavaoptsXmx string `yaml:"jenkinsJavaOpts_Xmx"`
|
||||
JenkinsjavaoptsMaxram string `yaml:"jenkinsJavaOpts_MaxRAM"`
|
||||
}
|
||||
|
||||
type Servicemesh struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
}
|
||||
|
||||
type Notification struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
}
|
||||
|
||||
type Alerting struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
}
|
||||
@@ -1,160 +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 v3
|
||||
|
||||
type ClusterConfig struct {
|
||||
ApiVersion string `yaml:"apiVersion"`
|
||||
Kind string `yaml:"kind"`
|
||||
Metadata Metadata `yaml:"metadata"`
|
||||
Spec *V3 `yaml:"spec"`
|
||||
}
|
||||
|
||||
type Metadata struct {
|
||||
Name string `yaml:"name"`
|
||||
Namespace string `yaml:"namespace"`
|
||||
Label Label `yaml:"labels"`
|
||||
}
|
||||
|
||||
type Label struct {
|
||||
Version string `yaml:"version"`
|
||||
}
|
||||
|
||||
type V3 struct {
|
||||
Persistence Persistence `yaml:"persistence"`
|
||||
Authentication Authentication `yaml:"authentication"`
|
||||
Common Common `yaml:"common"`
|
||||
Etcd Etcd `yaml:"etcd"`
|
||||
MetricsServer MetricsServer `yaml:"metrics_server"`
|
||||
Console Console `yaml:"console"`
|
||||
Monitoring Monitoring `yaml:"monitoring"`
|
||||
Logging Logging `yaml:"logging"`
|
||||
Openpitrix Openpitrix `yaml:"openpitrix"`
|
||||
Devops Devops `yaml:"devops"`
|
||||
Servicemesh Servicemesh `yaml:"servicemesh"`
|
||||
Notification Notification `yaml:"notification"`
|
||||
Alerting Alerting `yaml:"alerting"`
|
||||
Auditing Auditing `yaml:"auditing"`
|
||||
Events Events `yaml:"events"`
|
||||
Multicluster Multicluster `yaml:"multicluster"`
|
||||
Networkpolicy Networkpolicy `yaml:"networkpolicy"`
|
||||
LocalRegistry string `yaml:"local_registry"`
|
||||
}
|
||||
|
||||
type Persistence struct {
|
||||
StorageClass string `yaml:"storageClass"`
|
||||
}
|
||||
|
||||
type MetricsServer struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
}
|
||||
|
||||
type Authentication struct {
|
||||
JwtSecret string `yaml:"jwtSecret"`
|
||||
}
|
||||
type Etcd struct {
|
||||
Monitoring bool `yaml:"monitoring"`
|
||||
EndpointIps string `yaml:"endpointIps"`
|
||||
Port int `yaml:"port"`
|
||||
TlsEnable bool `yaml:"tlsEnable"`
|
||||
}
|
||||
|
||||
type Common struct {
|
||||
MysqlVolumeSize string `yaml:"mysqlVolumeSize"`
|
||||
MinioVolumeSize string `yaml:"minioVolumeSize"`
|
||||
EtcdVolumeSize string `yaml:"etcdVolumeSize"`
|
||||
OpenldapVolumeSize string `yaml:"openldapVolumeSize"`
|
||||
RedisVolumSize string `yaml:"redisVolumSize"`
|
||||
ES ES `yaml:"es"`
|
||||
}
|
||||
|
||||
type ES struct {
|
||||
//ElasticsearchMasterReplicas int `yaml:"elasticsearchMasterReplicas"`
|
||||
//ElasticsearchDataReplicas int `yaml:"elasticsearchDataReplicas"`
|
||||
ElasticsearchMasterVolumeSize string `yaml:"elasticsearchMasterVolumeSize"`
|
||||
ElasticsearchDataVolumeSize string `yaml:"elasticsearchDataVolumeSize"`
|
||||
LogMaxAge int `yaml:"logMaxAge"`
|
||||
ElkPrefix string `yaml:"elkPrefix"`
|
||||
}
|
||||
|
||||
type Console struct {
|
||||
EnableMultiLogin bool `yaml:"enableMultiLogin"`
|
||||
Port int `yaml:"port"`
|
||||
}
|
||||
|
||||
type Alerting struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
}
|
||||
|
||||
type Auditing struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
}
|
||||
|
||||
type Devops struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
JenkinsMemoryLim string `yaml:"jenkinsMemoryLim"`
|
||||
JenkinsMemoryReq string `yaml:"jenkinsMemoryReq"`
|
||||
JenkinsVolumeSize string `yaml:"jenkinsVolumeSize"`
|
||||
JenkinsjavaoptsXms string `yaml:"jenkinsJavaOpts_Xms"`
|
||||
JenkinsjavaoptsXmx string `yaml:"jenkinsJavaOpts_Xmx"`
|
||||
JenkinsjavaoptsMaxram string `yaml:"jenkinsJavaOpts_MaxRAM"`
|
||||
}
|
||||
|
||||
type Events struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
Ruler Ruler `yaml:"ruler"`
|
||||
}
|
||||
|
||||
type Ruler struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
Replicas int `yaml:"replicas"`
|
||||
}
|
||||
|
||||
type Logging struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
LogsidecarReplicas int `yaml:"logsidecarReplicas"`
|
||||
}
|
||||
|
||||
type Metrics struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
}
|
||||
|
||||
type Monitoring struct {
|
||||
//AlertmanagerReplicas int `yaml:"alertmanagerReplicas"`
|
||||
//PrometheusReplicas int `yaml:"prometheusReplicas"`
|
||||
PrometheusMemoryRequest string `yaml:"prometheusMemoryRequest"`
|
||||
PrometheusVolumeSize string `yaml:"prometheusVolumeSize"`
|
||||
}
|
||||
|
||||
type Multicluster struct {
|
||||
ClusterRole string `yaml:"clusterRole"`
|
||||
}
|
||||
|
||||
type Networkpolicy struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
}
|
||||
|
||||
type Notification struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
}
|
||||
|
||||
type Openpitrix struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
}
|
||||
|
||||
type Servicemesh struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
}
|
||||
@@ -37,12 +37,7 @@ func NewDarwinClusterPhase(runtime *common.KubeRuntime, manifestMap manifest.Ins
|
||||
},
|
||||
&kubesphere.DeployMiniKubeModule{},
|
||||
&kubesphere.DeployModule{Skip: !runtime.Cluster.KubeSphere.Enabled},
|
||||
&ksplugins.DeployKsPluginsModule{},
|
||||
//&ksplugins.DeployRedisModule{},
|
||||
&ksplugins.CreateKubeSphereSecretModule{},
|
||||
&ksplugins.DeployKsCoreConfigModule{}, // ks-core-config
|
||||
&ksplugins.CreateMonitorDashboardModule{},
|
||||
//&ksplugins.CreateNotificationModule{},
|
||||
&ksplugins.DeployPrometheusModule{},
|
||||
&ksplugins.DeployKsCoreModule{},
|
||||
&kubesphere.CheckResultModule{Skip: !runtime.Cluster.KubeSphere.Enabled},
|
||||
@@ -94,13 +89,8 @@ func NewK3sCreateClusterPhase(runtime *common.KubeRuntime, manifestMap manifest.
|
||||
&certs.AutoRenewCertsModule{Skip: !runtime.Cluster.Kubernetes.EnableAutoRenewCerts()},
|
||||
&k3s.SaveKubeConfigModule{},
|
||||
&storage.DeployLocalVolumeModule{Skip: skipLocalStorage},
|
||||
&kubesphere.DeployModule{Skip: !runtime.Cluster.KubeSphere.Enabled}, //
|
||||
&ksplugins.DeployKsPluginsModule{},
|
||||
//&ksplugins.DeployRedisModule{},
|
||||
&ksplugins.CreateKubeSphereSecretModule{},
|
||||
&ksplugins.DeployKsCoreConfigModule{}, // ks-core-config
|
||||
&ksplugins.CreateMonitorDashboardModule{},
|
||||
//&ksplugins.CreateNotificationModule{},
|
||||
&kubesphere.DeployModule{Skip: !runtime.Cluster.KubeSphere.Enabled},
|
||||
&ksplugins.DeployKsCoreConfigModule{},
|
||||
&ksplugins.DeployPrometheusModule{},
|
||||
&ksplugins.DeployKsCoreModule{},
|
||||
&kubesphere.CheckResultModule{Skip: !runtime.Cluster.KubeSphere.Enabled},
|
||||
@@ -157,12 +147,7 @@ func NewCreateClusterPhase(runtime *common.KubeRuntime, manifestMap manifest.Ins
|
||||
&kubernetes.SaveKubeConfigModule{},
|
||||
&storage.DeployLocalVolumeModule{Skip: skipLocalStorage},
|
||||
&kubesphere.DeployModule{Skip: !runtime.Cluster.KubeSphere.Enabled},
|
||||
&ksplugins.DeployKsPluginsModule{},
|
||||
//&ksplugins.DeployRedisModule{},
|
||||
&ksplugins.CreateKubeSphereSecretModule{},
|
||||
&ksplugins.DeployKsCoreConfigModule{}, // ! ks-core-config
|
||||
&ksplugins.CreateMonitorDashboardModule{},
|
||||
//&ksplugins.CreateNotificationModule{},
|
||||
&ksplugins.DeployPrometheusModule{},
|
||||
&ksplugins.DeployKsCoreModule{},
|
||||
&kubesphere.CheckResultModule{Skip: !runtime.Cluster.KubeSphere.Enabled}, // check ks-apiserver phase
|
||||
|
||||
@@ -25,7 +25,6 @@ func CliInstallTerminusPipeline(opts *options.CliTerminusInstallOptions) error {
|
||||
arg.SetOlaresVersion(opts.Version)
|
||||
arg.SetMinikubeProfile(opts.MiniKubeProfile)
|
||||
arg.SetStorage(getStorageValueFromEnv())
|
||||
arg.SetTokenMaxAge()
|
||||
arg.SetSwapConfig(opts.SwapConfig)
|
||||
if err := arg.SwapConfig.Validate(); err != nil {
|
||||
return err
|
||||
|
||||
@@ -35,7 +35,6 @@ func PrepareSystemPipeline(opts *options.CliPrepareSystemOptions, components []s
|
||||
arg.SetOlaresVersion(opts.Version)
|
||||
arg.SetRegistryMirrors(opts.RegistryMirrors)
|
||||
arg.SetStorage(getStorageValueFromEnv())
|
||||
arg.SetTokenMaxAge()
|
||||
|
||||
runtime, err := common.NewKubeRuntime(common.AllInOne, *arg)
|
||||
if err != nil {
|
||||
|
||||
@@ -16,7 +16,6 @@ import (
|
||||
"github.com/beclab/Olares/cli/pkg/core/logger"
|
||||
"github.com/beclab/Olares/cli/pkg/storage"
|
||||
|
||||
"github.com/beclab/Olares/cli/pkg/clientset"
|
||||
"github.com/beclab/Olares/cli/pkg/common"
|
||||
cc "github.com/beclab/Olares/cli/pkg/core/common"
|
||||
"github.com/beclab/Olares/cli/pkg/core/connector"
|
||||
@@ -235,50 +234,6 @@ func (p *Patch) Execute(runtime connector.Runtime) error {
|
||||
return errors.Wrap(errors.WithStack(err), "patch globalrole workspace manager failed")
|
||||
}
|
||||
|
||||
//var notificationManager = path.Join(runtime.GetInstallerDir(), "deploy", "patch-notification-manager.yaml")
|
||||
//if _, err = runtime.GetRunner().SudoCmd(fmt.Sprintf("%s apply -f %s", kubectl, notificationManager), false, true); err != nil {
|
||||
// return errors.Wrap(errors.WithStack(err), "patch notification manager failed")
|
||||
//}
|
||||
//var notificationManager = path.Join(runtime.GetInstallerDir(), "deploy", "patch-notification-manager.yaml")
|
||||
//if _, err = runtime.GetRunner().Host.SudoCmd(fmt.Sprintf("%s apply -f %s", kubectl, notificationManager), false, true); err != nil {
|
||||
// return errors.Wrap(errors.WithStack(err), "patch notification manager failed")
|
||||
//}
|
||||
//
|
||||
//patchAdminContent := `{"metadata":{"finalizers":["finalizers.kubesphere.io/users"]}}`
|
||||
//patchAdminCMD := fmt.Sprintf(
|
||||
// "%s patch user admin -p '%s' --type='merge' ",
|
||||
// kubectl,
|
||||
// patchAdminContent)
|
||||
//_, err = runtime.GetRunner().SudoCmd(patchAdminCMD, false, true)
|
||||
//if err != nil {
|
||||
// return errors.Wrap(errors.WithStack(err), "patch user admin failed")
|
||||
//}
|
||||
//patchAdminContent := "{\\\"metadata\\\":{\\\"finalizers\\\":[\\\"finalizers.kubesphere.io/users\\\"]}}"
|
||||
//patchAdminCMD := fmt.Sprintf(
|
||||
// "%s patch user admin -p '%s' --type='merge' ",
|
||||
// kubectl,
|
||||
// patchAdminContent)
|
||||
//_, err = runtime.GetRunner().Host.SudoCmd(patchAdminCMD, false, true)
|
||||
//if err != nil {
|
||||
// return errors.Wrap(errors.WithStack(err), "patch user admin failed")
|
||||
//}
|
||||
|
||||
//deleteAdminCMD := fmt.Sprintf("%s delete user admin --ignore-not-found", kubectl)
|
||||
//_, err = runtime.GetRunner().SudoCmd(deleteAdminCMD, false, true)
|
||||
//if err != nil {
|
||||
// return errors.Wrap(errors.WithStack(err), "failed to delete ks admin user")
|
||||
//}
|
||||
deleteKubectlAdminCMD := fmt.Sprintf("%s -n kubesphere-controls-system delete deploy kubectl-admin --ignore-not-found", kubectl)
|
||||
_, err = runtime.GetRunner().SudoCmd(deleteKubectlAdminCMD, false, true)
|
||||
if err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "failed to delete ks kubectl admin deployment")
|
||||
}
|
||||
deleteHTTPBackendCMD := fmt.Sprintf("%s -n kubesphere-controls-system delete deploy default-http-backend --ignore-not-found", kubectl)
|
||||
_, err = runtime.GetRunner().SudoCmd(deleteHTTPBackendCMD, false, true)
|
||||
if err != nil {
|
||||
return errors.Wrap(errors.WithStack(err), "failed to delete ks default http backend")
|
||||
}
|
||||
|
||||
patchFelixConfigContent := `{"spec":{"featureDetectOverride": "SNATFullyRandom=false,MASQFullyRandom=false"}}`
|
||||
patchFelixConfigCMD := fmt.Sprintf(
|
||||
"%s patch felixconfiguration default -p '%s' --type='merge'",
|
||||
@@ -466,19 +421,6 @@ func cloudValue(cloudInstance bool) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func getRedisPassword(client clientset.Client, runtime connector.Runtime) (string, error) {
|
||||
secret, err := client.Kubernetes().CoreV1().Secrets(common.NamespaceKubesphereSystem).Get(context.Background(), "redis-secret", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return "", errors.Wrap(errors.WithStack(err), "get redis secret failed")
|
||||
}
|
||||
if secret == nil || secret.Data == nil || secret.Data["auth"] == nil {
|
||||
return "", fmt.Errorf("redis secret not found")
|
||||
}
|
||||
|
||||
return string(secret.Data["auth"]), nil
|
||||
|
||||
}
|
||||
|
||||
type UserEnvConfig struct {
|
||||
APIVersion string `yaml:"apiVersion"`
|
||||
UserEnvs []v1alpha1.EnvVarSpec `yaml:"userEnvs"`
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
package terminus
|
||||
|
||||
import (
|
||||
"github.com/beclab/Olares/cli/pkg/common"
|
||||
"github.com/beclab/Olares/cli/pkg/core/connector"
|
||||
)
|
||||
|
||||
type NotEqualDesiredVersion struct {
|
||||
common.KubePrepare
|
||||
}
|
||||
|
||||
func (n *NotEqualDesiredVersion) PreCheck(runtime connector.Runtime) (bool, error) {
|
||||
ksVersion, ok := n.PipelineCache.GetMustString(common.KubeSphereVersion)
|
||||
if !ok {
|
||||
ksVersion = ""
|
||||
}
|
||||
|
||||
if n.KubeConf.Cluster.KubeSphere.Version == ksVersion {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
@@ -71,11 +71,10 @@ func upgradeKSCore() []task.Interface {
|
||||
Action: new(plugins.CopyEmbedFiles),
|
||||
},
|
||||
&task.LocalTask{
|
||||
Name: "UpgradeKSCore",
|
||||
Prepare: new(common.GetMasterNum),
|
||||
Action: new(plugins.CreateKsCore),
|
||||
Retry: 10,
|
||||
Delay: 10 * time.Second,
|
||||
Name: "UpgradeKSCore",
|
||||
Action: new(plugins.CreateKsCore),
|
||||
Retry: 10,
|
||||
Delay: 10 * time.Second,
|
||||
},
|
||||
&task.LocalTask{
|
||||
Name: "CheckKSCoreRunning",
|
||||
|
||||
@@ -192,7 +192,8 @@ func CheckJWS(jws string, duration int64) (*CheckJWSResult, error) {
|
||||
|
||||
// Check timestamp
|
||||
now := time.Now().UnixMilli()
|
||||
if now-timestamp > duration {
|
||||
diff := now - timestamp
|
||||
if max(diff, -diff) > duration {
|
||||
return nil, fmt.Errorf("timestamp is out of range")
|
||||
}
|
||||
|
||||
|
||||
@@ -488,7 +488,6 @@ func (i *InstallTerminus) Execute(runtime connector.Runtime) error {
|
||||
var envs = []string{
|
||||
fmt.Sprintf("export %s=%s", common.ENV_KUBE_TYPE, i.KubeConf.Arg.Kubetype),
|
||||
fmt.Sprintf("export %s=%s", common.ENV_REGISTRY_MIRRORS, i.KubeConf.Arg.RegistryMirrors),
|
||||
fmt.Sprintf("export %s=%d", common.ENV_TOKEN_MAX_AGE, i.KubeConf.Arg.TokenMaxAge),
|
||||
fmt.Sprintf("export %s=%s", common.ENV_PREINSTALL, os.Getenv(common.ENV_PREINSTALL)),
|
||||
fmt.Sprintf("export %s=%s", common.ENV_HOST_IP, systemInfo.GetLocalIp()),
|
||||
fmt.Sprintf("export %s=%s", common.ENV_DISABLE_HOST_IP_PROMPT, os.Getenv(common.ENV_DISABLE_HOST_IP_PROMPT)),
|
||||
|
||||
@@ -340,29 +340,6 @@ const side = {
|
||||
},
|
||||
{text: "Dashboard", link: "/manual/olares/resources-usage"},
|
||||
{text: "Profile", link: "/manual/olares/profile"},
|
||||
{
|
||||
text: "Studio",
|
||||
collapsed: true,
|
||||
link: "/manual/olares/studio/",
|
||||
items: [
|
||||
{
|
||||
text: "Deploy an app",
|
||||
link: "/manual/olares/studio/deploy",
|
||||
},
|
||||
{
|
||||
text: "Develop in a dev container",
|
||||
link: "/manual/olares/studio/develop",
|
||||
},
|
||||
{
|
||||
text: "Package and upload",
|
||||
link: "/manual/olares/studio/package-upload",
|
||||
},
|
||||
{
|
||||
text: "Add app assets",
|
||||
link: "/manual/olares/studio/assets",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -647,36 +624,29 @@ const side = {
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Develop Olares app",
|
||||
text: "Develop Olares apps",
|
||||
link: "/developer/develop/",
|
||||
items: [
|
||||
{
|
||||
text: "Tutorial",
|
||||
text: "Develop with Studio",
|
||||
collapsed: true,
|
||||
link: "/developer/develop/tutorial/",
|
||||
items: [
|
||||
{
|
||||
text: "Learn Studio",
|
||||
link: "/developer/develop/tutorial/studio",
|
||||
text: "Deploy an app",
|
||||
link: "/developer/develop/tutorial/deploy",
|
||||
},
|
||||
{
|
||||
text: "Create your first app",
|
||||
collapsed: true,
|
||||
link: "/developer/develop/tutorial/note/",
|
||||
items: [
|
||||
{
|
||||
text: "1. Create app",
|
||||
link: "/developer/develop/tutorial/note/create",
|
||||
},
|
||||
{
|
||||
text: "2. Develop backend",
|
||||
link: "/developer/develop/tutorial/note/backend",
|
||||
},
|
||||
{
|
||||
text: "3. Develop frontend",
|
||||
link: "/developer/develop/tutorial/note/frontend",
|
||||
},
|
||||
],
|
||||
text: "Develop in a dev container",
|
||||
link: "/developer/develop/tutorial/develop",
|
||||
},
|
||||
{
|
||||
text: "Package and upload",
|
||||
link: "/developer/develop/tutorial/package-upload",
|
||||
},
|
||||
{
|
||||
text: "Add app assets",
|
||||
link: "/developer/develop/tutorial/assets",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -13,6 +13,7 @@ import mediumZoom from "medium-zoom";
|
||||
import OSTabs from "./components/OStabs.vue";
|
||||
import VersionSwitcher from "./components/VersionSwitcher.vue";
|
||||
import _ from "lodash";
|
||||
import { redirects } from './redirects';
|
||||
|
||||
const LANGUAGE_LOCAL_KEY = "language";
|
||||
let isMenuChange = false;
|
||||
@@ -20,14 +21,27 @@ let isMenuChange = false;
|
||||
export default {
|
||||
extends: DefaultTheme,
|
||||
Layout,
|
||||
enhanceApp({ app }: { app: App }) {
|
||||
enhanceApp({ app, router }: { app: App; router: Router }) {
|
||||
app.component("Tabs", Tabs);
|
||||
app.component("LaunchCard", LaunchCard);
|
||||
app.component("FilterableList", FilterableList);
|
||||
app.component("OSTabs", OSTabs);
|
||||
app.component("VersionSwitcher", VersionSwitcher);
|
||||
|
||||
router.onBeforeRouteChange = (to: string) => {
|
||||
const path = to.replace(/\.html$/i, ''),
|
||||
toPath = redirects[path];
|
||||
|
||||
if (toPath) {
|
||||
setTimeout(() => { router.go(toPath); })
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
setup() {
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
12
docs/.vitepress/theme/redirects.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export const redirects = {
|
||||
// Refactor studio
|
||||
|
||||
// index page
|
||||
'/manual/olares/studio/': '/developer/develop/tutorial/',
|
||||
'/manual/olares/studio/deploy': '/developer/develop/tutorial/deploy',
|
||||
'/manual/olares/studio/develop': '/developer/develop/tutorial/develop',
|
||||
'/manual/olares/studio/package-upload': '/developer/develop/tutorial/package-upload',
|
||||
'/manual/olares/studio/assets': '/developer/develop/tutorial/assets',
|
||||
'/developer/develop/tutorial/studio': '/developer/develop/tutorial',
|
||||
'/zh/developer/develop/tutorial/studio': '/zh/developer/develop/tutorial',
|
||||
}
|
||||
@@ -616,32 +616,25 @@ const side = {
|
||||
link: "/zh/developer/develop/",
|
||||
items: [
|
||||
{
|
||||
text: "教程",
|
||||
text: "使用 Studio 开发",
|
||||
collapsed: true,
|
||||
link: "/zh/developer/develop/tutorial/",
|
||||
items: [
|
||||
{
|
||||
text: "了解 Studio",
|
||||
link: "/zh/developer/develop/tutorial/studio",
|
||||
text: "部署应用",
|
||||
link: "/zh/developer/develop/tutorial/deploy",
|
||||
},
|
||||
{
|
||||
text: "创建首个应用",
|
||||
collapsed: true,
|
||||
link: "/zh/developer/develop/tutorial/note/",
|
||||
items: [
|
||||
{
|
||||
text: "1. 创建应用",
|
||||
link: "/zh/developer/develop/tutorial/note/create",
|
||||
},
|
||||
{
|
||||
text: "2. 开发后端",
|
||||
link: "/zh/developer/develop/tutorial/note/backend",
|
||||
},
|
||||
{
|
||||
text: "3. 开发前端",
|
||||
link: "/zh/developer/develop/tutorial/note/frontend",
|
||||
},
|
||||
],
|
||||
text: "使用开发容器",
|
||||
link: "/zh/developer/develop/tutorial/develop",
|
||||
},
|
||||
{
|
||||
text: "打包与上传",
|
||||
link: "/zh/developer/develop/tutorial/package-upload",
|
||||
},
|
||||
{
|
||||
text: "添加应用素材",
|
||||
link: "/zh/developer/develop/tutorial/assets",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -1,15 +1,30 @@
|
||||
# Develop Olares application
|
||||
# Develop Olares applications
|
||||
|
||||
Developing applications on Olares is not much different from regular website development. Once you learn a few basic Olares concepts, you can start creating applications on his platform.
|
||||
Developing applications on Olares leverages standard web technologies and containerization. If you are familiar with building web applications or Docker containers, you already have the skills needed to build for Olares.
|
||||
|
||||
- [Core Concepts of Olares](../concepts/index.md)
|
||||
- [Understanding the Format of Olares Application Chart](./package/chart.md)
|
||||
- [The structure of the Olares Application Chart](./package/chart.md)
|
||||
- [Configuration guide and field descriptions of `OlaresManifest.yaml`](./package/manifest.md)
|
||||
- [Extensions field to Helm in Olares](./package/extension.md)
|
||||
This guide takes you through the complete lifecycle of an Olares application, from your first line of code in Studio to publishing on the Market.
|
||||
|
||||
- [Exploring Our Tutorials](./tutorial/)
|
||||
- [Learn about Studio, an Olares Development Tool](./tutorial/studio)
|
||||
- [Creating your first application](./tutorial/note/)
|
||||
- [Exploring Advanced Concepts](./advanced/)
|
||||
- [Submitting Applications to the Olares Market](./submit/)
|
||||
## Before you begin
|
||||
Before getting started, it's helpful to review some concepts:
|
||||
- [Application](../concepts/application.md)
|
||||
- [Network](../concepts/network.md)
|
||||
|
||||
## Step 1: Develop with Studio
|
||||
Olares Studio is a development platform that accelerates your build cycle. It provides a pre-configured workspace to build, debug, and test your applications directly on the platform.
|
||||
|
||||
* **[Deploy an app](./tutorial/deploy.md)**: Learn how to quickly deploy an app from an existing Docker image, configure it, and test it in Studio.
|
||||
* **[Develop in a dev container](./tutorial/develop.md)**: Spin up a remote development environment (Dev Container) and connect it to VS Code for a seamless coding experience.
|
||||
* **[Package and upload](./tutorial/package-upload.md)**: Convert your running application into an Olares-compatible package and upload it for testing.
|
||||
* **[Add app assets](./tutorial/assets.md)**: Configure icons, screenshots, and descriptions to make your application store-ready.
|
||||
|
||||
## Step 2: Package your application
|
||||
To publish your application to the Olares Market, you must structure it according to the Olares Application Chart (OAC) specification. This format extends Helm Charts to support Olares-specific features like permission management and sandboxing.
|
||||
|
||||
* **[Understand the Olares Application Chart](./package/chart.md)**: Understand the file structure and requirements of an application package.
|
||||
* **[Understand `OlaresManifest.yaml`](./package/manifest.md)**: A comprehensive guide to the `OlaresManifest.yaml` file, which defines your app's metadata, permissions, and system integration points.
|
||||
* **[Understand Helm extensions](./package/extension.md)**: Learn about the custom fields and capabilities Olares adds to standard Helm deployments.
|
||||
|
||||
## Step 3: Submit your application
|
||||
Once your application is built and packaged, the final step is to share it with the Olares community.
|
||||
|
||||
* **[Submit to Market](./submit/index.md)**: Learn how to submit your application to the Olares Market for review and distribution.
|
||||
@@ -17,8 +17,8 @@ outline: [2, 3]
|
||||
### 1. Develop and test your application
|
||||
|
||||
Before submitting an application, please ensure that it has been thoroughly tested on your Olares.
|
||||
- Use DevBox's dev-container to test and debug your application in a real online environment. [Learn more about DevBox](../tutorial/studio).
|
||||
- Use the [custom installation](/manual/olares/market.md#install-custom-applications) in the Market app for user testing.
|
||||
- Use Studio's dev-container to test and debug your application in a real online environment. [Learn more about Studio](../tutorial/).
|
||||
- Use the [custom installation](../tutorial/package-upload.md) in the Market app for user testing.
|
||||
|
||||
### 2. Submit an application
|
||||
The submission of the application needs to be completed through a **Pull Request**. Here's how:
|
||||
|
||||
@@ -6,7 +6,7 @@ description: Deploy a single-container Docker app to Olares using Studio.
|
||||
This guide explains how to deploy a single-container Docker app to Olares using Studio.
|
||||
|
||||
:::info For single-container apps
|
||||
This method supports apps that run from a single container image. For multi-container apps (for example, a web service plus a separate database), use the workflow in the [developer documentation](../../../developer/develop/tutorial/index.md) instead.
|
||||
This method supports apps that run from a single container image.
|
||||
:::
|
||||
:::tip Recommended for testing
|
||||
Studio-created deployments are best suited for development, testing, or temporary use. Upgrades and long-term data persistence can be limited compared to installing a packaged app from the Market. For production use, consider [packaging and uploading the app](package-upload.md) and installing it via the Market.
|
||||
@@ -44,7 +44,6 @@ services:
|
||||
- "8282:80/tcp"
|
||||
environment:
|
||||
TZ: 'America/Toronto'
|
||||
# Volumes store your data between container upgrades
|
||||
volumes:
|
||||
- './db:/var/www/html/db'
|
||||
- './logos:/var/www/html/images/uploads/logos'
|
||||
@@ -67,7 +66,7 @@ These fields define the app's core components. You can find this information as
|
||||
:::
|
||||
3. For **Instance Specifications**, enter the minimum CPU and memory requirements. For example:
|
||||
- **CPU**: 2 core
|
||||
- **Memory**: 1 G
|
||||
- **Memory**: 1 Gi
|
||||

|
||||
|
||||
### Add environment variables
|
||||
@@ -83,7 +82,7 @@ Environment variables are used to pass configuration settings to your app. In th
|
||||
Volumes connect storage on your Olares device to a path inside the app's container, which is essential for saving data permanently. These are defined using the `-v` flag or in the `volumes:` section.
|
||||
|
||||
:::info Host path options
|
||||
The host path is where Olares stores the data, and the mount path is the path inside the container. Olares provides three managed host path prefixes:
|
||||
The host path is where Olares stores the data, and the mount path is the path inside the container. Studio provides three managed host path prefixes:
|
||||
|
||||
- `/app/data`: App data directory. Data can be accessed across nodes and is not deleted when the app is uninstalled. Appears under `/Data/studio` in Files.
|
||||
- `/app/cache`: App cache directory. Data is stored in the node's local disk and is deleted when the app is uninstalled. Appears under `/Cache/<device-name>/studio` in Files.
|
||||
@@ -96,15 +95,23 @@ The host path is where Olares stores the data, and the mount path is the path in
|
||||
|
||||
This app requires two volumes. You will add them one by one.
|
||||
1. Add the database volume. This data is for high-frequency I/O and does not need to be saved permanently. Map it to `/app/cache` so it will be automatically deleted when the app is uninstalled.
|
||||
1. Click **Add** next to **Storage Volume**.
|
||||
2. For **Host path**, select `/app/cache`, then enter `/db`.
|
||||
3. For **Mount path**, enter `/var/www/html/db`.
|
||||
4. Click **Submit**.
|
||||
2. Add the logo volume. This is user-uploaded data that should be persistent and reusable, even if the app is reinstalled. Map it to `/app/data`.
|
||||
1. Click **Add** next to **Storage Volume**.
|
||||
2. For **Host path**, select `/app/data`, then enter `/logos`.
|
||||
3. For **Mount path**, enter `/var/www/html/images/uploads/logos`
|
||||
4. Click **Submit**.
|
||||
|
||||
a. Click **Add** next to **Storage Volume**.
|
||||
|
||||
b. For **Host path**, select `/app/cache`, then enter `/db`.
|
||||
|
||||
c. For **Mount path**, enter `/var/www/html/db`.
|
||||
|
||||
d. Click **Submit**.
|
||||
2. Add the logo volume. This is user-uploaded data that should be persistent and reusable, even if the app is reinstalled. Map it to `/app/data`.
|
||||
|
||||
a. Click **Add** next to **Storage Volume**.
|
||||
|
||||
b. For **Host path**, select `/app/data`, then enter `/logos`.
|
||||
|
||||
c. For **Mount path**, enter `/var/www/html/images/uploads/logos`.
|
||||
|
||||
d. Click **Submit**.
|
||||

|
||||
|
||||
You can check Files later to verify the mounted paths.
|
||||
@@ -118,37 +125,36 @@ If your app needs Postgres or Redis, enable it under **Instance Specifications**
|
||||

|
||||
|
||||
When enabled, Studio provides dynamic variables. You must use these variables in the **Environment Variables** section for your app to connect to the database.
|
||||
- **Postgres variables:**
|
||||
- **Postgres variables**
|
||||
|
||||
| Variables | Description |
|
||||
|--------------|-----------------------|
|
||||
| $(PG_USER) | PostgreSQL username |
|
||||
| $(PG_DBNAME) | Database name |
|
||||
| $(PG_PASS) | Postgres Password |
|
||||
| $(PG_HOST) | Postgres service host |
|
||||
| $(PG_PORT) | Postgres service port |
|
||||
| Variables | Description |
|
||||
|----------------|-----------------------|
|
||||
| `$(PG_USER)` | PostgreSQL username |
|
||||
| `$(PG_DBNAME)` | Database name |
|
||||
| `$(PG_PASS)` | Postgres Password |
|
||||
| `$(PG_HOST)` | Postgres service host |
|
||||
| `$(PG_PORT)` | Postgres service port |
|
||||
|
||||
- **Redis variables:**
|
||||
- **Redis variables**
|
||||
|
||||
| Variables | Description |
|
||||
|---------------|--------------------|
|
||||
| $(REDIS_HOST) | Redis service host |
|
||||
| $(REDIS_PORT) | Redis service port |
|
||||
| $(REDIS_USER) | Redis username |
|
||||
| $(REDIS_PASS) | Redis password |
|
||||
| Variables | Description |
|
||||
|-----------------|--------------------|
|
||||
| `$(REDIS_HOST)` | Redis service host |
|
||||
| `$(REDIS_PORT)` | Redis service port |
|
||||
| `$(REDIS_USER)` | Redis username |
|
||||
| `$(REDIS_PASS)` | Redis password |
|
||||
|
||||
### Generate the app project
|
||||
1. Once all your configurations are set, click **Create**. This generates the app's project files.
|
||||
2. After creation, Studio generates the package files for your app, and then automatically deploys the app. You can check the status in the bottom bar.
|
||||
3. When the app is successfully deployed, click **Preview** in the top-right corner to launch it.
|
||||

|
||||
|
||||

|
||||
|
||||
## Review the package files and test the app
|
||||
Apps deployed from Studio include a `-dev` suffix in the title to distinguish them from Market installations.
|
||||

|
||||
|
||||
You can click on files like `OlaresManifest.yaml` to review and make changes. For example, to change the app's display name and logo.
|
||||
You can click on files like `OlaresManifest.yaml` to review and make changes. For example, to change the app's display name and logo:
|
||||
|
||||
1. Click **<span class="material-symbols-outlined">box_edit</span>Edit** in the top-right to open the editor.
|
||||
2. Click `OlaresManifest.yaml` to view the content.
|
||||
@@ -164,7 +170,6 @@ You can click on files like `OlaresManifest.yaml` to review and make changes. Fo
|
||||
:::
|
||||

|
||||
|
||||
|
||||
## Uninstall or delete the app
|
||||
If you no longer need the app, you can remove it.
|
||||
1. Click <span class="material-symbols-outlined">more_vert</span> in the top-right corner.
|
||||
@@ -175,12 +180,11 @@ If you no longer need the app, you can remove it.
|
||||
## Troubleshoot a deployment
|
||||
|
||||
### Cannot install the app
|
||||
If installation fails, review the error at the bottom of the page and click **View** to expand details.
|
||||

|
||||
If installation fails, review the error at the bottom of the page and click **View** to check details.
|
||||
|
||||
### Run into issues when the app is running
|
||||
Once running, you can manage the app from its deployment details page in Studio. The interface of this page is similar to Control Hub. If details don't appear, refresh the page.
|
||||
You can:
|
||||
- Use the **Stop** and **Restart** controls to retry. This action can often resolve runtime issues like a frozen process.
|
||||
- Check events or logs to investigate runtime errors. See [Export container logs for troubleshooting](../controlhub/manage-container.md#export-container-logs-for-troubleshooting) for details.
|
||||
- Use the **Stop** or **Restart** controls to retry. This action can often resolve runtime issues like a frozen process.
|
||||
- Check events or logs to investigate runtime errors. See [Export container logs for troubleshooting](../../../manual/olares/controlhub/manage-container.md#export-container-logs-for-troubleshooting) for details.
|
||||

|
||||
@@ -5,10 +5,7 @@ description: Learn how to use Studio to set up a dev container, access it via VS
|
||||
# Develop in a dev container
|
||||
Olares Studio allows you to spin up a pre-configured dev container to write and debug code (such as Node.js scripts or CUDA programs) without managing local infrastructure. This provides an isolated environment identical to the production runtime.
|
||||
|
||||
The following guide shows the setup workflow using a Node.js project as an example.
|
||||
:::info
|
||||
This workflow is optimized for iterative coding and testing. If you intend to publish the application to the Olares Market, you must create your own image and follow the [developer documentation](../../../developer/develop/submit/index.md) for final configuration.
|
||||
:::
|
||||
The following guide shows the development and setup workflow using a Node.js project as an example.
|
||||
|
||||
## Prerequisite
|
||||
- Olares version 1.12.2 or later.
|
||||
@@ -56,7 +53,7 @@ If you prefer your local settings and extensions, you can tunnel into the contai
|
||||
code tunnel
|
||||
```
|
||||
5. Follow the terminal prompts to authenticate using a Microsoft or GitHub account via the provided URL.
|
||||
6. Assign a name to the tunnel when prompted (e.g., `myapp-demo`). This will output a vscode.dev URL tied to this remote workspace.
|
||||
6. Assign a name to the tunnel when prompted (e.g., `myapp-demo`). This will output a `vscode.dev` URL tied to this remote workspace.
|
||||

|
||||
|
||||
7. Open VS Code on your local machine, click the **><** icon in the bottom-left, and select **Tunnel**.
|
||||
@@ -183,6 +180,9 @@ You can follow the same steps to modify `OlaresManifest.yaml` and `deployment.ya
|
||||
- name: "80"
|
||||
port: 80
|
||||
targetPort: 80
|
||||
- name: myweb-dev-8080
|
||||
port: 8080
|
||||
targetPort: 8080
|
||||
# Add the following
|
||||
- name: myweb-dev-8081 # Must match entrance name
|
||||
port: 8081
|
||||
@@ -195,10 +195,10 @@ You can follow the same steps to modify `OlaresManifest.yaml` and `deployment.ya
|
||||
|
||||
4. Click **Apply** to redeploy the container.
|
||||
|
||||
You can verify the active ports in **Services** > **Ports**.
|
||||
Once deployed, go to **Services** > **Ports**. You can see your new port listed here.
|
||||

|
||||
|
||||
### Verify the new port
|
||||
### Test the connection
|
||||
1. Update `index.js` to listen on the new port:
|
||||
```js
|
||||
const express = require('express');
|
||||
@@ -1,15 +1,26 @@
|
||||
# Tutorial
|
||||
---
|
||||
description: Get started with Studio to deploy Docker-based apps, develop new apps, package and upload locally, and manage assets on your Olares device.
|
||||
---
|
||||
# Deploy and develop apps in Olares
|
||||
|
||||
Welcome to the Olares developer guides. These detailed tutorials offer a step-by-step guide on building an Olares Application from scratch.
|
||||
Studio provides a real Olares environment for building, porting, and testing apps when cloud features and the sandbox system are hard to simulate locally. With Studio you can:
|
||||
- Create a new Olares app in an online development container.
|
||||
- Port an existing app, adjust its configurations, and test the installation flow.
|
||||
- Package your app into a chart and download it when your app is ready.
|
||||
|
||||
To get started, you can learn some basic concepts of Olares, such as:
|
||||
- [Olares architectural components](../../concepts/architecture.md)
|
||||
- [Olares Application Chart](../../develop/package/chart.md)
|
||||
- [Olares Extension on Helm](../package/extension.md)
|
||||
## Access Studio
|
||||
You must manually install Studio:
|
||||
1. Open **Market**, and search for "Studio".
|
||||

|
||||
|
||||
These fundamentals will help you grasp our development process more effectively.
|
||||
2. Click **Get**, then **Install**, and wait for installation to complete.
|
||||
|
||||
You can also [learn about DevBox](studio.md), a built-in app that Olares provides for developers to build Olares applications.
|
||||
After installation, launch Studio from Market or from Launchpad.
|
||||
|
||||
If you're brand new to Olares development and want to jump straight into coding, start with the [**Create your first Olares app**](./note/index.md). This tutorial will step you through the process of building a small note application.
|
||||
## Understand the Studio UI
|
||||
The sidebar and **Home** page organize your main tasks in Studio:
|
||||
- **Home**: A welcome page with shortcuts to common actions and documentation.
|
||||
- **Applications**: A list of apps you have created and deployed with Studio.
|
||||
- **Start**: You can start deploying or developing apps, or uploading an app from a local chart file.
|
||||
|
||||

|
||||
@@ -8,7 +8,7 @@ Apps created in Studio are ideal for development and testing. For stable, long-t
|
||||
|
||||
## Download the App package from Studio
|
||||
|
||||
After confirming that your app works as expected, you can download its complete installation package.
|
||||
After confirming that your app works as expected, you can download its complete installation package:
|
||||
|
||||
1. Open your app project in **Studio**.
|
||||
2. Click <span class="material-symbols-outlined">more_vert</span> in the top-right corner.
|
||||
@@ -24,6 +24,4 @@ After confirming that your app works as expected, you can download its complete
|
||||
|
||||
Once finished, you can click **Open** to launch it.
|
||||
|
||||
All custom-installed apps will appear under the **My Olares** > **Upload** tab.
|
||||
|
||||
|
||||
All custom-installed apps will appear under the **My Olares** > **Upload** tab.
|
||||
@@ -1,13 +0,0 @@
|
||||
# Learn about Studio
|
||||
|
||||
At Olares, we provide a development tool called Studio. It helps developers create applications for **Olares**.
|
||||
|
||||
- Why is Studio necessary for developers?
|
||||
|
||||
Olares has many cloud-based features that are difficult to simulate in a standalone development environment. Furthermore, the unique sandbox system of **Olares** requires a real system environment for end-to-end testing. To simplify app simulation for developers and minimize system integration efforts during development, we provide the **Studio**. **Studio** is a quick, automatic toolset for creating app sandboxes.
|
||||
|
||||
- What features does Studio have?
|
||||
|
||||
- In Studio, you can build an app and generate a corresponding Olares Application Configuration* This deployment files can be modified, allowing you to port an existing app and deploy it to the Olares. During the modification process, you can continually attempt installation and resolve any issues that arise. Once the app passes your tests, you can download your Application Chart and submit it to the [Olares Market Repository](https://github.com/beclab/apps).
|
||||
|
||||
- In addition to porting existing apps, you can also create a native Olares application in Studio. Studio provides an online development container where coders can work in a real environment, utilize other system interfaces, database clusters, and more.
|
||||
@@ -1,49 +0,0 @@
|
||||
---
|
||||
description: Get started with Studio to deploy Docker-based apps, develop new apps, package and upload locally, and manage assets on your Olares device.
|
||||
---
|
||||
# Deploy and develop apps in Olares
|
||||
|
||||
Studio provides a real Olares environment for building, porting, and testing apps when cloud features and the sandbox system are hard to simulate locally. With Studio you can:
|
||||
- Create a new Olares app in an online development container.
|
||||
- Port an existing app, adjust its configurations, and test the installation flow.
|
||||
-Package your app into a chart and download it when your app is ready.
|
||||
|
||||
## Access Studio
|
||||
Studio is available in Olares Market and must be installed manually.
|
||||
1. Open **Market**, and search for "Studio".
|
||||

|
||||
|
||||
2. Click **Get**, then **Install**, and wait for installation to complete.
|
||||
|
||||
After installation, launch Studio from Market or from Launchpad.
|
||||
|
||||
## Understand the Studio UI
|
||||
The sidebar and **Home** page organize your main tasks in Studio:
|
||||
- **Home**: A welcome page with shortcuts to common actions and documentation.
|
||||
- **Applications**: A list of apps you have created and deployed with Studio.
|
||||
- **Start**: You can start deploying or developing apps, or uploading an app from a local chart file.
|
||||
|
||||

|
||||
|
||||
|
||||
---
|
||||
<div>
|
||||
<h4><a href="./deploy">Deploy an app from Docker image</a></h4>
|
||||
Deploy an app from an existing Docker image, configure it, and test it in Studio.
|
||||
</div>
|
||||
|
||||
|
||||
<div>
|
||||
<h4><a href="./develop">Develop in a dev container</a></h4>
|
||||
Build and debug a new app using the Studio development environment.
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4><a href="./package-upload">Package and upload the app to Market</a></h4>
|
||||
Download an installable package and upload it to Market for local use.
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4><a href="./assets">Add app assets</a></h4>
|
||||
Use Olares image hosting to add and manage creative assets for your app.
|
||||
</div>
|
||||
|
After Width: | Height: | Size: 91 KiB |
|
After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 165 KiB |
|
After Width: | Height: | Size: 942 KiB |
BIN
docs/public/images/zh/manual/olares/studio-change-app-icon1.png
Normal file
|
After Width: | Height: | Size: 959 KiB |
|
After Width: | Height: | Size: 388 KiB |
BIN
docs/public/images/zh/manual/olares/studio-coding-on-olares.png
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
docs/public/images/zh/manual/olares/studio-configure-dev-env.png
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
docs/public/images/zh/manual/olares/studio-custom-install.png
Normal file
|
After Width: | Height: | Size: 435 KiB |
BIN
docs/public/images/zh/manual/olares/studio-deploy-wallos.png
Normal file
|
After Width: | Height: | Size: 92 KiB |
|
After Width: | Height: | Size: 209 KiB |
BIN
docs/public/images/zh/manual/olares/studio-enable-GPU.png
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
docs/public/images/zh/manual/olares/studio-enable-databases.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 76 KiB |
BIN
docs/public/images/zh/manual/olares/studio-ui.png
Normal file
|
After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 92 KiB |
BIN
docs/public/images/zh/manual/olares/studio.png
Normal file
|
After Width: | Height: | Size: 150 KiB |
@@ -1,15 +1,30 @@
|
||||
# 简介
|
||||
# 开发 Olares 应用
|
||||
|
||||
在 Olares 上开发应用与当下主流的网站开发方法并没有太多区别,只需要额外了解一些 Olares 的基本概念,即可在 Olares 上开发应用。
|
||||
Olares 应用开发依托于通用的 Web 技术与容器化方案。如果你熟悉 Web 应用构建或 Docker 容器技术,即可直接上手开发 Olares 应用,无需额外的技能储备。
|
||||
|
||||
- [Olares 的核心理念](../concepts/index.md)
|
||||
- [了解 Olares 应用 Chart 的格式](./package/chart.md)
|
||||
- [Olares 应用 Chart 包的结构](./package/chart.md)
|
||||
- [OlaresManifest.yaml 的配置和字段说明](./package/manifest.md)
|
||||
- [Olares 对 Helm 进行的字段扩展](./package/extension.md)
|
||||
本指南涵盖了 Olares 应用开发的全生命周期,从在 Studio 中编写第一行代码开始,一直到在 Market 上完成发布。
|
||||
|
||||
- [探索我们的教程](./tutorial/)
|
||||
- [了解 Olares 的开发工具 Studio](./tutorial/studio)
|
||||
- [创建首个应用](./tutorial/note/)
|
||||
- [了解一些进阶的技巧](./advanced/)
|
||||
- [提交应用到应用市场](./submit/)
|
||||
## 准备工作
|
||||
正式开始前,建议先了解以下核心概念:
|
||||
- [Application](../concepts/application.md)
|
||||
- [Network](../concepts/network.md)
|
||||
|
||||
## 第一步:使用 Studio 开发
|
||||
Olares Studio 是专为加速应用开发周期而设计的开发平台。它提供了预配置的工作区,支持直接在平台上构建、调试和测试应用。
|
||||
|
||||
* **[部署应用](./tutorial/deploy.md)**: 学习如何基于现有 Docker 镜像快速部署应用,并在 Studio 中完成配置与测试。
|
||||
* **[使用开发容器](./tutorial/develop.md)**: 创建远程开发环境 (Dev Container) 并连接至 VS Code,实现流畅的编码体验。
|
||||
* **[打包与上传](./tutorial/package-upload.md)**: 将运行中的应用转换为 Olares 兼容的安装包,并上传进行测试。
|
||||
* **[添加应用素材](./tutorial/assets.md)**: 配置图标、截图和应用描述,完善应用上架准备工作。
|
||||
|
||||
## 第二步:打包应用
|
||||
发布应用到 Olares Market 之前,需要按照 Olares Application Chart (OAC) 规范来组织应用结构。该格式在 Helm Charts 的基础上进行了扩展,增加了权限管理和沙箱机制等 Olares 专属特性。
|
||||
|
||||
* **[了解 Olares Application Chart](./package/chart.md)**: 了解应用包的文件结构与具体规范。
|
||||
* **[了解 `OlaresManifest.yaml`](./package/manifest.md)**: 全面介绍 `OlaresManifest.yaml` 文件,该文件用于定义应用的元数据、权限及与 Olares 系统对接的各项配置。
|
||||
* **[了解 Helm 扩展](./package/extension.md)**: 了解 Olares 在标准 Helm 部署之上增加的自定义字段与功能。
|
||||
|
||||
## 第三步:提交应用
|
||||
应用构建并打包完毕后,即可将其分享给 Olares 社区。
|
||||
|
||||
* **[提交至 Market](./submit/index.md)**: 了解如何将应用提交至 Olares Market 以进行审核与分发。
|
||||
@@ -17,8 +17,8 @@ outline: [2, 3]
|
||||
### 1. 创建并测试 Olares 应用
|
||||
|
||||
在提交应用程序之前,请确保它已在你的 Olares 上经过完整测试。
|
||||
- 使用 DevBox 的开发容器在真实的在线环境中测试和调试你的应用。 [了解有关 DevBox 的更多信息](../tutorial/studio)。
|
||||
- 使用 Market 应用程序中的[自定义安装](../../../manual/olares/market#install-custom-applications) 进行用户测试。
|
||||
- 使用 Studio 的开发容器在真实的在线环境中测试和调试你的应用。[了解有关 Studio 的更多信息](../tutorial/)。
|
||||
- 使用 Market 应用程序中的[自定义安装](../tutorial/package-upload.md)进行用户测试。
|
||||
|
||||
### 2. 提交应用
|
||||
应用提交需要通过 **Pull Request** 完成。具体步骤如下:
|
||||
|
||||
26
docs/zh/developer/develop/tutorial/assets.md
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
description: 了解如何为 Olares 应用准备和上传图标、功能图像以及宣传图。
|
||||
---
|
||||
# 添加图标、功能图像和宣传图
|
||||
|
||||
要打造视觉效果出色的应用,高质量的素材必不可少。本文档介绍应用图标、功能图像和截图的规格,以及如何将其上传至 Olares。
|
||||
|
||||
## 资源规格
|
||||
上传前,确保图片格式正确。
|
||||
|
||||
| 类型 | 格式 | 文件大小上限 | 尺寸(像素) | 描述 |
|
||||
|:---------|:--------------|:--------|:---------|:-------------------------------------|
|
||||
| **应用图标** | PNG,WEBP | 512 KB | 256x256 | 应用最常见的视觉符号,用于 Olares 桌面和整个系统。 |
|
||||
| **功能图像** | JPEG,PNG,WEBP | 8 MB | 1440x900 | 显示在**应用市场** > **我的 Olares** 中的应用页面上。 |
|
||||
| **宣传图** | JPEG,PNG,WEBP | 每张 8 MB | 1440x900 | 如果计划将应用提交至公开应用市场,必须上传至少两张。最多可上传八张。 |
|
||||
|
||||
## 上传并链接资源
|
||||
|
||||
1. 导航至 [Olares 应用市场图片托管](https://imghost.joinolares.cn/)。
|
||||
2. 选择要上传的资源类型,例如应用图标。
|
||||
3. 将准备好的文件拖放至上传区域,或点击选择文件。
|
||||
4. 如有必要,点击图片缩略图进行简单编辑。
|
||||
5. 准备就绪后,点击**上传**。
|
||||
6. 上传后,该服务将提供图片的直接 URL。点击 <span class="material-symbols-outlined">content_copy</span> 将 URL 复制到剪贴板。
|
||||
7. 在 **Studio** 中打开应用项目。
|
||||
8. 将 URL 粘贴到 `OlaresManifest.yaml` 文件中的对应字段。
|
||||
190
docs/zh/developer/develop/tutorial/deploy.md
Normal file
@@ -0,0 +1,190 @@
|
||||
---
|
||||
outline: [2, 3]
|
||||
description: 如何使用 Studio 将单容器 Docker 应用快速部署到 Olares。
|
||||
---
|
||||
# 基于 Docker 镜像部署应用
|
||||
本文档介绍如何使用 Studio 将单容器 Docker 应用部署到 Olares 系统。
|
||||
|
||||
:::info 仅限单容器应用
|
||||
此方法仅适用于通过单个容器镜像运行的应用。
|
||||
:::
|
||||
:::tip 推荐用于测试场景
|
||||
通过 Studio 部署的应用主要面向开发与测试场景。相比市场安装的正式应用,它在版本维护和数据持久化方面存在局限。如需长期稳定使用,建议先[打包并上传应用](package-upload.md),然后通过应用市场安装。
|
||||
:::
|
||||
|
||||
## 前提条件
|
||||
- Olares 1.12.2 及以上版本。
|
||||
- 应用的容器镜像已存在,且 Olares 主机可以访问。
|
||||
- 具备应用的 `docker run` 命令或 `docker-compose.yaml` 文件,用于参考端口、环境变量和挂载卷等配置信息。
|
||||
|
||||
## 创建并配置应用
|
||||
本节以个人订阅和开支追踪应用 [Wallos](https://hub.docker.com/r/bellamy/wallos) 为例,演示如何将常见的 Docker 配置(镜像、端口、环境变量、卷)映射到 Studio 中。
|
||||
|
||||
**Docker 配置参考示例**
|
||||
::: code-group
|
||||
```docker{3-6,8} [docker run 命令]
|
||||
docker run -d \
|
||||
--name wallos \
|
||||
-v /path/to/config/wallos/db:/var/www/html/db \
|
||||
-v /path/to/config/wallos/logos:/var/www/html/images/uploads/logos \
|
||||
-e TZ=America/Toronto \
|
||||
-p 8282:80 \
|
||||
--restart unless-stopped \
|
||||
bellamy/wallos:latest
|
||||
```
|
||||
|
||||
```yaml{5-6,7-10,12-14} [docker compose 文件]
|
||||
version: '3.0'
|
||||
|
||||
services:
|
||||
wallos:
|
||||
container_name: wallos
|
||||
image: bellamy/wallos:latest
|
||||
ports:
|
||||
- "8282:80/tcp"
|
||||
environment:
|
||||
TZ: 'America/Toronto'
|
||||
volumes:
|
||||
- './db:/var/www/html/db'
|
||||
- './logos:/var/www/html/images/uploads/logos'
|
||||
restart: unless-stopped
|
||||
```
|
||||
:::
|
||||
### 创建应用
|
||||
|
||||
1. 打开 Studio,选择**创建新应用**。
|
||||
2. 输入**应用名称**,例如 `wallos`,然后点击**确认**。
|
||||
3. 选择**将自己的容器部署到 Olares 上**。
|
||||

|
||||
|
||||
### 配置镜像、端口和实例规格
|
||||
这些字段定义了应用的核心组件。参考 `docker run` 命令中的镜像名和 `-p` 参数,或 `docker-compose.yaml` 文件中的 `image:` 和 `ports:` 字段进行填写。
|
||||
1. 在**容器镜像**字段中,粘贴镜像名称,例如 `bellamy/wallos:latest`。
|
||||
2. 在**容器端口**字段中,参考 `主机端口:容器端口` 格式的映射(如 `8282:80`),填写冒号后的 `80`。
|
||||
:::tip 仅需填写容器端口
|
||||
端口映射的标准格式为 `主机端口:容器端口`。冒号后的是应用在内部监听的“容器端口”,冒号前的是供外部访问的“主机端口”。由于 Studio 会自动管理外部路由,你只需填写容器端口即可。
|
||||
:::
|
||||
3. 在**实例规格**区域,设置应用所需的最低 CPU 和内存要求。例如:
|
||||
* **CPU**: 2 core
|
||||
* **Memory**: 1 Gi
|
||||

|
||||
|
||||
### 添加环境变量
|
||||
环境变量主要用于向应用传递配置信息,对应 Docker 示例中的 `-e` 参数或 `environment` 字段。
|
||||
1. 向下滚动至**环境变量**区域,点击**添加**。
|
||||
2. 参照下图示例,填写时区配置:
|
||||
- **键**: `TZ`
|
||||
- **值**:`America/Toronto`
|
||||
3. 点击**提交**。如需添加更多变量,重复此过程。
|
||||

|
||||
|
||||
### 添加存储卷
|
||||
存储卷用于将 Olares 设备的物理存储映射到容器内部,这是确保数据持久化的关键步骤,对应 Docker 示例中的 `-v` 参数或 `volumes` 字段。
|
||||
|
||||
:::info 理解主机路径
|
||||
主机路径是指数据在 Olares 系统中的实际存储位置,Studio 提供了三种预设的前缀路径:
|
||||
|
||||
- `/app/data`:应用数据目录。数据可跨节点访问,且卸载应用时**不会**删除。在文件管理器中显示为 `/Data/studio`。
|
||||
- `/app/cache`:应用缓存目录。数据存在节点本地磁盘,卸载应用时会自动删除。在文件管理器中显示为 `/Cache/<device-name>/studio`。
|
||||
- `/app/Home`:用户数据目录。主要用于读取外部文件,数据不会被删除。
|
||||
:::
|
||||
:::info 主机路径规则
|
||||
- 输入的主机路径必须以 `/` 开头。
|
||||
- Studio 会自动补全路径前缀。例如,应用名为 `test`,当设置主机路径为 `/app/data/folder1` 时,在文件管理器中的实际路径为 `/Data/studio/test/folder1`。
|
||||
:::
|
||||
|
||||
本应用需要依次挂载两个存储卷:
|
||||
1. 添加数据库卷。此类数据涉及高频 I/O 读写且无需永久保存。将其映射至 `/app/cache` 以便在应用卸载时自动清理。
|
||||
|
||||
a. 点击**存储卷**旁的**添加**。
|
||||
|
||||
b. **主机路径**选择 `/app/cache`,并输入 `/db`。
|
||||
|
||||
c. **容器路径**输入 `/var/www/html/db`。
|
||||
|
||||
d. 点击**提交**。
|
||||
2. 添加 Logo 卷。此类数据为用户上传内容,需持久化保存,即使重装应用也不应丢失。将其映射至 `/app/data`。
|
||||
|
||||
a. 点击**存储卷**旁的**添加**。
|
||||
|
||||
b. **主机路径**选择 `/app/data`,并输入 `/logos`。
|
||||
|
||||
c. **容器路径**输入 `/var/www/html/images/uploads/logos`。
|
||||
|
||||
d. 点击**提交**。
|
||||

|
||||
|
||||
添加完成后,可在文件管理器中确认挂载路径。
|
||||

|
||||
|
||||
### 可选:配置 GPU 或数据库中间件
|
||||
如果应用依赖 GPU,需要在**实例规格**下启用 **GPU** 选项并选择 GPU 厂商。
|
||||

|
||||
|
||||
如果应用需要 Postgres 或 Redis 数据库,在**实例规格**下启用相应选项。
|
||||

|
||||
|
||||
启用数据库后,Studio 会提供一组动态变量。你必须在应用的**环境变量**中添加这些变量,应用才能连接到数据库。
|
||||
- **Postgres 变量**
|
||||
|
||||
| 变量名 | 说明 |
|
||||
|----------------|----------------|
|
||||
| `$(PG_USER)` | PostgreSQL 用户名 |
|
||||
| `$(PG_DBNAME)` | 数据库名称 |
|
||||
| `$(PG_PASS)` | Postgres 密码 |
|
||||
| `$(PG_HOST)` | Postgres 服务主机名 |
|
||||
| `$(PG_PORT)` | Postgres 服务端口 |
|
||||
|
||||
- **Redis 变量**
|
||||
|
||||
| 变量名 | 说明 |
|
||||
|-----------------|-------------|
|
||||
| `$(REDIS_HOST)` | Redis 服务主机名 |
|
||||
| `$(REDIS_PORT)` | Redis 服务端口 |
|
||||
| `$(REDIS_USER)` | Redis 用户名 |
|
||||
| `$(REDIS_PASS)` | Redis 密码 |
|
||||
|
||||
### 生成应用项目
|
||||
1. 完成所有配置后点击**创建**,系统将生成应用的项目文件。
|
||||
2. 创建完成后,Studio 会自动打包并部署应用。你可以在页面底部栏查看进度状态。
|
||||
3. 部署成功后,在右上角点击**预览**即可打开应用。
|
||||

|
||||
|
||||
## 检查包文件与测试应用
|
||||
通过 Studio 部署的应用标题会自动添加 `-dev` 后缀,以便与从应用市场安装的正式版区分。
|
||||

|
||||
|
||||
你可以查看或编辑 `OlaresManifest.yaml` 等配置文件。例如,修改应用的显示名称和图标:
|
||||
|
||||
1. 在右上角点击 **<span class="material-symbols-outlined">box_edit</span> 编辑**打开编辑器。
|
||||
2. 点击 `OlaresManifest.yaml` 查看内容。
|
||||
3. 修改 `entrance` 和 `metadata` 部分的 `title` 字段。例如,将 `wallos` 改为 `Wallos`。
|
||||
4. 替换 `entrance` 和 `metadata` 部分的图标地址。
|
||||

|
||||
|
||||
5. 在右上角点击 <span class="material-symbols-outlined">save</span> 保存更改。
|
||||
6. 点击**应用**,系统将使用更新后的配置重新安装应用。
|
||||
|
||||
:::info
|
||||
如果自上次部署后未检测到任何更改,点击**应用**将直接返回应用状态页,不会触发重装。
|
||||
:::
|
||||

|
||||
|
||||
## 卸载或删除应用
|
||||
如果不再需要该应用,可执行以下操作:
|
||||
1. 在右上角点击 <span class="material-symbols-outlined">more_vert</span>。
|
||||
2. 选择相应操作:
|
||||
- **卸载**:仅从 Olares 系统中移除运行的实例,但在 Studio 中保留项目文件,方便继续编辑。
|
||||
- **删除**:卸载应用并从 Studio 中彻底删除项目文件。此操作不可撤销。
|
||||
|
||||
## 部署故障排除
|
||||
|
||||
### 无法安装应用
|
||||
如果安装失败,请查看页面底部的错误提示。点击**查看**可打开详细日志。
|
||||
|
||||
### 运行时遇到问题
|
||||
应用启动后,你可以在 Studio 的部署详情页进行管理(界面类似于控制面板)。如果详情未显示,刷新页面即可。
|
||||
常见操作包括:
|
||||
- 点击**停止**按钮或**重启**按钮后重试。这通常能解决进程卡死等临时性故障。
|
||||
- 查看事件或日志以排查错误。具体方法请参考[导出问题容器日志](../../../manual/olares/controlhub/manage-container.md#导出问题容器日志)。
|
||||

|
||||
238
docs/zh/developer/develop/tutorial/develop.md
Normal file
@@ -0,0 +1,238 @@
|
||||
---
|
||||
outline: [2, 3]
|
||||
description: 了解如何使用 Studio 设置开发容器,通过 VS Code 访问,并配置端口转发。
|
||||
---
|
||||
# 使用开发容器开发应用
|
||||
Olares Studio 允许你启动预配置的开发容器来编写和调试代码(如 Node.js 脚本或 CUDA 程序),无需管理本地基础设施。它提供了一个与生产运行时一致的、完全隔离的环境。
|
||||
|
||||
本文档以 Node.js 项目为例介绍开发和配置流程。
|
||||
|
||||
## 前提条件
|
||||
- Olares 1.12.2 及以上版本。
|
||||
|
||||
## 1. 初始化容器
|
||||
开始编码前,需要配置容器资源并选择运行时环境。
|
||||
1. 打开 Studio 并选择**创建新应用**。
|
||||
2. 输入**应用名称**(例如 `My Web`),然后点击**确认**。
|
||||
3. 选择**在 Olares 上写程序**作为创建方式。
|
||||

|
||||
|
||||
4. 配置**开发环境**:
|
||||
|
||||
a. 从下拉列表中选择 `beclab/node20-ts-dev:1.0.0`。
|
||||
|
||||
b. 为容器分配资源,例如:
|
||||
- **CPU**:`2 core`
|
||||
- **内存**:`4 Gi`
|
||||
- **卷大小**:`500 Mi`
|
||||
5. 在**暴露端口**字段中,输入用于调试的端口,例如 `8080`。
|
||||
:::tip 暴露多个端口
|
||||
端口 `80` 默认为暴露状态。如需暴露多个额外端口,请用逗号分隔。
|
||||
:::
|
||||

|
||||
|
||||
6. 点击**创建**。等待左下角的状态变为`运行中`。
|
||||
|
||||
## 2. 访问工作区
|
||||
你可以通过浏览器或本地 IDE 访问开发容器。
|
||||
|
||||
### 选项 A:基于浏览器的 VS Code
|
||||
点击 Studio 中的**在线编辑器**,在浏览器中启动一个功能齐全的 VS Code 实例。
|
||||
|
||||

|
||||
### 选项 B:本地 VS Code 远程隧道
|
||||
如果更习惯使用本地设置和插件,可以通过隧道连接到容器。
|
||||
1. 点击 Studio 中的**在线编辑器**以打开基于浏览器的 VS Code。
|
||||
2. 点击左上角的 <span class="material-symbols-outlined">menu</span>,选择 **Terminal** > **New Terminal** 打开终端。
|
||||
3. 安装 VS Code Tunnel CLI:
|
||||
```bash
|
||||
curl -SsfL https://vscode.download.prss.microsoft.com/dbazure/download/stable/17baf841131aa23349f217ca7c570c76ee87b957/vscode_cli_alpine_x64_cli.tar.gz | tar zxv -C /usr/local/bin
|
||||
```
|
||||
4. 创建安全隧道:
|
||||
```bash
|
||||
code tunnel
|
||||
```
|
||||
5. 按照终端提示,通过提供的 URL 使用 Microsoft 或 GitHub 帐户进行身份验证。
|
||||
6. 出现提示时为隧道命名,例如 `myapp-demo`。终端将输出绑定到此远程工作区的 `vscode.dev` URL。
|
||||

|
||||
|
||||
7. 在本地机器上打开 VS Code,点击左下角的 **><** 图标,选择 **Tunnel**。
|
||||
{width=30%}
|
||||

|
||||
|
||||
8. 使用上一步中的同一帐户登录。
|
||||
9. 选择刚才定义的隧道名称 `myapp-demo`。VS Code 可能需要几分钟建立连接。连接成功后,左下角的远程指示器将显示隧道名称。
|
||||

|
||||
{width=30%}
|
||||
|
||||
连接成功后,你将拥有对容器文件系统和终端的完全远程访问权限,体验与本地开发一致。
|
||||
## 3. 编写和运行代码
|
||||
进入工作区后,无论是通过浏览器还是本地隧道,工作流与标准本地开发无异。
|
||||
你可通过以下方式向工作区添加内容:
|
||||
- 上传文件
|
||||
- 克隆 Git 仓库
|
||||
- 手动创建文件
|
||||
|
||||
本例演示如何手动创建一个基础网页。
|
||||
|
||||
1. 打开 Explorer 侧边栏并导航到 `/root/`。
|
||||
:::info
|
||||
Studio 将项目文件持久化在 `数据/studio/<app_name>/` 路径下。
|
||||
:::
|
||||
|
||||

|
||||
2. 在左上角点击 <span class="material-symbols-outlined">menu</span>,选择 **Terminal** > **New Terminal** 打开终端。
|
||||
3. 运行以下命令初始化项目:
|
||||
```bash
|
||||
npm init -y
|
||||
```
|
||||
4. 安装 Express 框架:
|
||||
```bash
|
||||
npm install express --save
|
||||
```
|
||||
5. 在 `/root/` 中创建文件 `index.js`,内容如下:
|
||||
```js
|
||||
// 确保端口与定义的一致
|
||||
const express = require('express');
|
||||
const app = express();
|
||||
app.use(express.static('public/'));
|
||||
app.listen(8080), function() {
|
||||
console.log('Server is running on port 8080');
|
||||
};
|
||||
```
|
||||
6. 在 `/root/` 中创建 `public` 目录并添加 `index.html` 文件:
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>My Web Page</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World</h1>
|
||||
<h1>Hello Olares</h1>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
7. 启动服务器:
|
||||
```bash
|
||||
node index.js
|
||||
```
|
||||
8. 打开 VS Code 中的 **Ports** 标签页,点击转发地址查看结果。
|
||||

|
||||
|
||||
## 4. 配置端口转发
|
||||
如果在创建容器后需要暴露更多端口,例如添加端口 `8081`,需要手动编辑容器配置清单。
|
||||
:::tip
|
||||
如果需要更改端口号,可参照相同步骤修改 `OlaresManifest.yaml` 和 `deployment.yaml` 文件。
|
||||
:::
|
||||
### 修改配置
|
||||
1. 在 Studio 中,点击右上角的 **<span class="material-symbols-outlined">box_edit</span>编辑**打开编辑器。
|
||||
2. 编辑 `OlaresManifest.yaml`。
|
||||
|
||||
a. 将新端口追加到 `entrances` 列表:
|
||||
```yaml
|
||||
entrances:
|
||||
- authLevel: private
|
||||
host: myweb
|
||||
icon: https://app.cdn.olares.com/appstore/default/defaulticon.webp
|
||||
invisible: true
|
||||
name: myweb-dev-8080
|
||||
openMethod: ""
|
||||
port: 8080
|
||||
skip: true
|
||||
title: myweb-dev-8080
|
||||
# 添加以下内容
|
||||
- authLevel: private
|
||||
host: myweb # 必须匹配 Service metadata name
|
||||
icon: https://app.cdn.olares.com/appstore/default/defaulticon.webp
|
||||
invisible: true
|
||||
name: myweb-dev-8081 # 唯一标识符
|
||||
openMethod: ""
|
||||
port: 8081 # 新端口号
|
||||
skip: true
|
||||
title: myweb-dev-8081
|
||||
```
|
||||
b. 在右上角点击 <span class="material-symbols-outlined">save</span> 保存更改。
|
||||
3. 编辑 `deployment.yaml`。
|
||||
|
||||
a. 在 `Deployment` > `metadata` 下,将端口映射添加到 `default-thirdlevel-domains`:
|
||||
```yaml
|
||||
annotations:
|
||||
applications.app.bytetrade.io/default-thirdlevel-domains:
|
||||
'[{"appName":"myweb","entranceName":"myweb-dev-8080"},{"appName":"myweb","entranceName":"myweb-dev-8081"}]'
|
||||
# # entranceName 必须匹配 OlaresManifest.yaml 中的名称
|
||||
```
|
||||
b. 更新 `spec` > `template` > `metadata` 下的 `studio-expose-ports` 注解:
|
||||
```yaml
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
applications.app.bytetrade.io/studio-expose-ports: "8080,8081"
|
||||
```
|
||||
|
||||
c. 在 `Service` > `spec` > `ports` 下添加端口定义:
|
||||
```yaml
|
||||
kind: Service
|
||||
spec:
|
||||
ports:
|
||||
- name: "80"
|
||||
port: 80
|
||||
targetPort: 80
|
||||
- name: myweb-dev-8080
|
||||
port: 8080
|
||||
targetPort: 8080
|
||||
# 添加以下内容
|
||||
- name: myweb-dev-8081 # 必须匹配 entrance name
|
||||
port: 8081
|
||||
targetPort: 8081
|
||||
selector:
|
||||
io.kompose.service: myweb
|
||||
```
|
||||
|
||||
d. 在右上角点击 <span class="material-symbols-outlined">save</span> 保存更改。
|
||||
|
||||
4. 点击**应用**重新部署容器。
|
||||
|
||||
部署成功后,你可以在**服务** > **端口**中看到列出的新端口。
|
||||

|
||||
|
||||
### 测试连接
|
||||
1. 更新 `index.js` 以监听新端口:
|
||||
```js
|
||||
const express = require('express');
|
||||
const app = express();
|
||||
app.use(express.static('public/'));
|
||||
app.listen(8080), function() {
|
||||
console.log('Server is running on port 8080');
|
||||
};
|
||||
// 添加以下内容
|
||||
const app_new = express();
|
||||
app_new.use(express.static('new/'));
|
||||
app_new.listen(8081), function() {
|
||||
console.log('Server is running on port 8081');
|
||||
};
|
||||
```
|
||||
2. 在 `/root/` 中创建 `new` 目录并添加 `index.html` 文件:
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>My Web Page</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>This is a new page</h1>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
3. 重启服务器:
|
||||
```bash
|
||||
node index.js
|
||||
```
|
||||
4. 检查 **Ports** 标签页确认端口 `8081` 处于活动状态且可访问。
|
||||

|
||||
|
||||
5. 点击转发地址查看结果。
|
||||

|
||||
@@ -1,15 +1,26 @@
|
||||
# 教程
|
||||
---
|
||||
description: 学习如何使用 Studio 在 Olares 设备上部署 Docker 应用、开发新应用、进行本地打包上传以及管理应用素材。
|
||||
---
|
||||
# 在 Olares 上部署与开发应用
|
||||
|
||||
欢迎阅读 Olares 应用开发指南。这些详细的教程将逐步指导你从零开始构建 Olares 应用。
|
||||
由于本地环境难以模拟云功能和沙箱系统,Studio 提供了一个真实的 Olares 环境,用于构建、移植和测试应用。通过 Studio,你可以:
|
||||
- 在在线开发容器中创建全新的 Olares 应用。
|
||||
- 移植现有应用,调整配置并测试安装流程。
|
||||
- 待应用准备就绪后,将其打包为 Chart 并下载。
|
||||
|
||||
在开始前,你可以先了解一些 Olares 的基本概念,如:
|
||||
- [Olares 的组成](../../concepts/architecture.md)
|
||||
- [Olares 应用 Chart](../../develop/package/chart.md)
|
||||
- [Olares 在 Helm 上的扩展](../package/extension.md)。
|
||||
## 获取 Studio
|
||||
你需要手动安装 Studio:
|
||||
1. 打开**应用市场**,搜索 "Studio"。
|
||||

|
||||
|
||||
这些基础知识将帮助你更有效地掌握的开发流程。
|
||||
2. 点击**获取**,随后点击**安装**,等待安装完成。
|
||||
|
||||
你还可以先了解下 [DevBox](studio.md),这是 Olares 为开发人员构建 Olares 应用程序提供的内置应用程序。
|
||||
安装完成后,可从应用市场或启动台启动 Studio。
|
||||
|
||||
如果你是 Olares 开发的新手,想直接开始编码,可以从[创建首个应用](./note/index.md)开始。本教程将指导你构建一个小型笔记应用程序。
|
||||
## 熟悉 Studio 界面
|
||||
Studio 的核心功能都集中在侧边栏和**主页**:
|
||||
- **主页**:欢迎页,包含常用操作入口和文档链接。
|
||||
- **应用**:展示你用 Studio 创建和部署的应用列表。
|
||||
- **开始**:在此开始部署或开发应用,也可上传本地 Chart 文件。
|
||||
|
||||

|
||||
27
docs/zh/developer/develop/tutorial/package-upload.md
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
description: 从 Studio 下载应用包并在 Olares 应用市场中安装,以实现稳定且长期的使用。
|
||||
---
|
||||
|
||||
# 打包应用并上传至应用市场
|
||||
|
||||
Studio 创建的应用非常适合开发和测试。如需长期稳定使用,建议通过 Olares 应用市场进行安装。
|
||||
|
||||
## 从 Studio 下载应用包
|
||||
|
||||
确认应用运行符合预期后,即可下载完整的安装包:
|
||||
|
||||
1. 在 **Studio** 中打开应用项目。
|
||||
2. 在右上角点击 <span class="material-symbols-outlined">more_vert</span>。
|
||||
3. 从下拉菜单中选择**下载**,将应用包保存至本地。
|
||||
|
||||
## 通过应用市场安装应用
|
||||
|
||||
1. 打开**应用市场**。
|
||||
2. 导航至**我的 Olares**,并选择**上传自定义 Chart**。
|
||||
3. 选择从 Studio 下载的 `.tgz` 应用包文件。等待上传完成。
|
||||
4. 系统将弹出提示,确认应用已成功添加。点击**立即安装**。
|
||||

|
||||
|
||||
完成后,可以点击**打开**启动应用。
|
||||
|
||||
所有自定义安装的应用都将显示在**我的 Olares** > **Upload** 标签页下。
|
||||
@@ -1,13 +0,0 @@
|
||||
# 了解 Studio
|
||||
|
||||
在 Olares 中,我们为每个开发者提供了一个为 Olares 开发应用的开发工具,这就是 Studio 。
|
||||
|
||||
- 开发者为什么需要 Studio 呢?
|
||||
|
||||
Olares 作为一个具有诸多云原生特性的系统,有大量的系统上下文环境在开发者的单机开发环境很难模拟。同时,Olares 独有的沙盒体系也需要在真实的系统环境中才能完成 End to End 的测试。所以,为了方便开发者能够最便捷的获得真实的应用仿真体验,减少开发中的系统联调尝试,我们提供 Studio 为开发者提供自动快速构建应用沙盒的开发工具集。
|
||||
|
||||
- Studio 提供了哪些功能?
|
||||
|
||||
- 在 Studio 中,你可以创建一个应用,生成 Olares 应用的 Chart 包。接着你可以修改这个应用 Chart 的部署脚本,移植一个现有的应用,以 Olares 的方式部署到系统中。在修改过程中,你可以尝试安装,检查错误。测试通过后,可下载对应的应用 Chart,提交给 Olares 的 [Market 仓库](https://github.com/beclab/apps)。
|
||||
|
||||
- 除了移植现有应用,你还可以创建一个全新的应用,在 Studio 完成整个应用的开发到上线的工作。Studio 中提供了在线的开发容器,开发者可以在真实的环境中完成代码开发,在程序中调用系统的其他接口或者数据库集群等等。
|
||||
@@ -170,7 +170,7 @@ spec:
|
||||
priorityClassName: "system-cluster-critical"
|
||||
containers:
|
||||
- name: app-service
|
||||
image: beclab/app-service:0.4.61
|
||||
image: beclab/app-service:0.4.62
|
||||
imagePullPolicy: IfNotPresent
|
||||
securityContext:
|
||||
runAsUser: 0
|
||||
|
||||
@@ -199,13 +199,13 @@ func (h *HelmOps) AddApplicationLabelsToDeployment() error {
|
||||
patch = string(patchByte)
|
||||
|
||||
// TODO: add ownerReferences of user
|
||||
deployment, err := k8s.AppsV1().Deployments(h.app.Namespace).Get(h.ctx, h.app.RawAppName, metav1.GetOptions{})
|
||||
deployment, err := k8s.AppsV1().Deployments(h.app.Namespace).Get(h.ctx, h.app.AppName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
return h.tryToAddApplicationLabelsToStatefulSet(k8s, patch)
|
||||
}
|
||||
|
||||
klog.Errorf("Failed to get deployment %s in namespace %s: %v", h.app.RawAppName, h.app.Namespace, err)
|
||||
klog.Errorf("Failed to get deployment %s in namespace %s: %v", h.app.AppName, h.app.Namespace, err)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -216,7 +216,7 @@ func (h *HelmOps) AddApplicationLabelsToDeployment() error {
|
||||
metav1.PatchOptions{})
|
||||
|
||||
if err != nil {
|
||||
klog.Errorf("Failed to patch deployment %s in namespace %s: %v", h.app.RawAppName, h.app.Namespace, err)
|
||||
klog.Errorf("Failed to patch deployment %s in namespace %s: %v", h.app.AppName, h.app.Namespace, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -278,13 +278,13 @@ func (h *HelmOps) tryToAddApplicationLabelsToCluster() error {
|
||||
}
|
||||
|
||||
func (h *HelmOps) tryToAddApplicationLabelsToStatefulSet(k8s *kubernetes.Clientset, patch string) error {
|
||||
statefulSet, err := k8s.AppsV1().StatefulSets(h.app.Namespace).Get(h.ctx, h.app.RawAppName, metav1.GetOptions{})
|
||||
statefulSet, err := k8s.AppsV1().StatefulSets(h.app.Namespace).Get(h.ctx, h.app.AppName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
klog.Errorf("Failed to get statefulset %s in namespace %s: %v", h.app.RawAppName, h.app.Namespace, err)
|
||||
klog.Errorf("Failed to get statefulset %s in namespace %s: %v", h.app.AppName, h.app.Namespace, err)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -585,7 +585,7 @@ func (h *HelmOps) isStartUp() (bool, error) {
|
||||
func (h *HelmOps) findAppSelectedPods() (*corev1.PodList, error) {
|
||||
var labelSelector string
|
||||
deployment, err := h.client.KubeClient.Kubernetes().AppsV1().Deployments(h.app.Namespace).
|
||||
Get(h.ctx, h.app.RawAppName, metav1.GetOptions{})
|
||||
Get(h.ctx, h.app.AppName, metav1.GetOptions{})
|
||||
|
||||
if err == nil {
|
||||
labelSelector = metav1.FormatLabelSelector(deployment.Spec.Selector)
|
||||
@@ -593,7 +593,7 @@ func (h *HelmOps) findAppSelectedPods() (*corev1.PodList, error) {
|
||||
|
||||
if apierrors.IsNotFound(err) {
|
||||
sts, err := h.client.KubeClient.Kubernetes().AppsV1().StatefulSets(h.app.Namespace).
|
||||
Get(h.ctx, h.app.RawAppName, metav1.GetOptions{})
|
||||
Get(h.ctx, h.app.AppName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -603,7 +603,7 @@ func (h *HelmOps) findAppSelectedPods() (*corev1.PodList, error) {
|
||||
List(h.ctx, metav1.ListOptions{LabelSelector: labelSelector})
|
||||
|
||||
if err != nil {
|
||||
klog.Errorf("app %s get pods err %v", h.app.RawAppName, err)
|
||||
klog.Errorf("app %s get pods err %v", h.app.AppName, err)
|
||||
return nil, err
|
||||
}
|
||||
return pods, nil
|
||||
|
||||
@@ -78,6 +78,11 @@ func (p *SuspendingApp) Exec(ctx context.Context) (StatefulInProgressApp, error)
|
||||
}
|
||||
|
||||
func (p *SuspendingApp) exec(ctx context.Context) error {
|
||||
err := suspendOrResumeApp(ctx, p.client, p.manager, int32(0))
|
||||
if err != nil {
|
||||
klog.Errorf("suspend %s %s failed %v", p.manager.Spec.Type, p.manager.Spec.AppName, err)
|
||||
return fmt.Errorf("suspend app %s failed %w", p.manager.Spec.AppName, err)
|
||||
}
|
||||
// If stop-all is requested, also stop v2 server-side shared charts by scaling them down
|
||||
if p.manager.Annotations[api.AppStopAllKey] == "true" {
|
||||
var appCfg *appcfg.ApplicationConfig
|
||||
@@ -104,12 +109,6 @@ func (p *SuspendingApp) exec(ctx context.Context) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err := suspendOrResumeApp(ctx, p.client, p.manager, int32(0))
|
||||
if err != nil {
|
||||
klog.Errorf("suspend %s %s failed %v", p.manager.Spec.Type, p.manager.Spec.AppName, err)
|
||||
return fmt.Errorf("suspend app %s failed %w", p.manager.Spec.AppName, err)
|
||||
}
|
||||
}
|
||||
|
||||
if p.manager.Spec.Type == appsv1.Middleware && userspace.IsKbMiddlewares(p.manager.Spec.AppName) {
|
||||
|
||||
@@ -148,7 +148,7 @@ func suspendOrResumeApp(ctx context.Context, cli client.Client, am *appv1alpha1.
|
||||
workloadName := ""
|
||||
switch workload := w.(type) {
|
||||
case *appsv1.Deployment:
|
||||
if check(am.Spec.RawAppName, workload.Name) {
|
||||
if check(am.Spec.AppName, workload.Name) {
|
||||
if workload.Annotations == nil {
|
||||
workload.Annotations = make(map[string]string)
|
||||
}
|
||||
@@ -158,7 +158,7 @@ func suspendOrResumeApp(ctx context.Context, cli client.Client, am *appv1alpha1.
|
||||
workloadName = workload.Namespace + "/" + workload.Name
|
||||
}
|
||||
case *appsv1.StatefulSet:
|
||||
if check(am.Spec.RawAppName, workload.Name) {
|
||||
if check(am.Spec.AppName, workload.Name) {
|
||||
if workload.Annotations == nil {
|
||||
workload.Annotations = make(map[string]string)
|
||||
}
|
||||
@@ -201,7 +201,7 @@ func isStartUp(am *appv1alpha1.ApplicationManager, cli client.Client) (bool, err
|
||||
var labelSelector string
|
||||
var deployment appsv1.Deployment
|
||||
|
||||
err := cli.Get(context.TODO(), types.NamespacedName{Name: am.Spec.RawAppName, Namespace: am.Spec.AppNamespace}, &deployment)
|
||||
err := cli.Get(context.TODO(), types.NamespacedName{Name: am.Spec.AppName, Namespace: am.Spec.AppNamespace}, &deployment)
|
||||
|
||||
if err == nil {
|
||||
labelSelector = metav1.FormatLabelSelector(deployment.Spec.Selector)
|
||||
@@ -209,7 +209,7 @@ func isStartUp(am *appv1alpha1.ApplicationManager, cli client.Client) (bool, err
|
||||
|
||||
if apierrors.IsNotFound(err) {
|
||||
var sts appsv1.StatefulSet
|
||||
err = cli.Get(context.TODO(), types.NamespacedName{Name: am.Spec.RawAppName, Namespace: am.Spec.AppNamespace}, &sts)
|
||||
err = cli.Get(context.TODO(), types.NamespacedName{Name: am.Spec.AppName, Namespace: am.Spec.AppNamespace}, &sts)
|
||||
if err != nil {
|
||||
return false, err
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@ spec:
|
||||
value: os_framework_notifications
|
||||
containers:
|
||||
- name: notifications-api
|
||||
image: beclab/notifications-api:v1.12.39
|
||||
image: beclab/notifications-api:v1.12.40
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 3010
|
||||
|
||||
@@ -25,10 +25,7 @@ metadata:
|
||||
provider-service-ref: search3-provider-svc.{{ .Release.Namespace }}:28080
|
||||
rules:
|
||||
- nonResourceURLs:
|
||||
- "/document/get_by_resource_uri"
|
||||
- "/document/add"
|
||||
- "/document/delete/*"
|
||||
- "/document/update/*"
|
||||
- "/document/*"
|
||||
verbs: ["*"]
|
||||
|
||||
---
|
||||
|
||||
@@ -240,7 +240,7 @@ spec:
|
||||
value: os_framework_search3
|
||||
containers:
|
||||
- name: search3
|
||||
image: beclab/search3:v0.0.90
|
||||
image: beclab/search3:v0.0.93
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
@@ -301,7 +301,7 @@ spec:
|
||||
priorityClassName: "system-cluster-critical"
|
||||
containers:
|
||||
- name: search3monitor
|
||||
image: beclab/search3monitor:v0.0.90
|
||||
image: beclab/search3monitor:v0.0.93
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 8081
|
||||
|
||||
@@ -64,7 +64,7 @@ spec:
|
||||
operator: Exists
|
||||
containers:
|
||||
- name: search3-validation
|
||||
image: beclab/search3validation:v0.0.90
|
||||
image: beclab/search3validation:v0.0.92
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 8443
|
||||
|
||||
@@ -101,7 +101,7 @@ spec:
|
||||
value: os_framework_vault
|
||||
containers:
|
||||
- name: vault-server
|
||||
image: beclab/vault-server:v1.6.1
|
||||
image: beclab/vault-server:v1.6.23
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
@@ -148,7 +148,7 @@ spec:
|
||||
- name: vault-attach
|
||||
mountPath: /padloc/packages/server/attachments
|
||||
- name: vault-admin
|
||||
image: beclab/vault-admin:v1.4.29
|
||||
image: beclab/vault-admin:v1.6.23
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 3010
|
||||
|
||||
157
infrastructure/kubesphere/Makefile
Normal file
@@ -0,0 +1,157 @@
|
||||
# Copyright 2018 The KubeSphere Authors. All rights reserved.
|
||||
# Use of this source code is governed by a Apache license
|
||||
# that can be found in the LICENSE file.
|
||||
|
||||
|
||||
# Produce CRDs that work back to Kubernetes 1.11 (no version conversion)
|
||||
CRD_OPTIONS ?= "crd:trivialVersions=true"
|
||||
|
||||
GV="iam:v1alpha2"
|
||||
MANIFESTS="iam/*"
|
||||
|
||||
# App Version
|
||||
APP_VERSION = v3.2.0
|
||||
|
||||
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
|
||||
ifeq (,$(shell go env GOBIN))
|
||||
GOBIN=$(shell go env GOPATH)/bin
|
||||
else
|
||||
GOBIN=$(shell go env GOBIN)
|
||||
endif
|
||||
|
||||
OUTPUT_DIR=bin
|
||||
#ifeq (${GOFLAGS},)
|
||||
# # go build with vendor by default.
|
||||
# export GOFLAGS=-mod=vendor
|
||||
#endif
|
||||
define ALL_HELP_INFO
|
||||
# Build code.
|
||||
#
|
||||
# Args:
|
||||
# WHAT: Directory names to build. If any of these directories has a 'main'
|
||||
# package, the build will produce executable files under $(OUT_DIR).
|
||||
# If not specified, "everything" will be built.
|
||||
# GOFLAGS: Extra flags to pass to 'go' when building.
|
||||
# GOLDFLAGS: Extra linking flags passed to 'go' when building.
|
||||
# GOGCFLAGS: Additional go compile flags passed to 'go' when building.
|
||||
#
|
||||
# Example:
|
||||
# make
|
||||
# make all
|
||||
# make all WHAT=cmd/ks-apiserver
|
||||
# Note: Use the -N -l options to disable compiler optimizations an inlining.
|
||||
# Using these build options allows you to subsequently use source
|
||||
# debugging tools like delve.
|
||||
endef
|
||||
.PHONY: all
|
||||
all: test ks-apiserver;$(info $(M)...Begin to test and build all of binary.) @ ## Test and build all of binary.
|
||||
|
||||
help:
|
||||
@grep -hE '^[ a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
|
||||
awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-17s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
.PHONY: binary
|
||||
# Build all of binary
|
||||
binary: | ks-apiserver ; $(info $(M)...Build all of binary.) @ ## Build all of binary.
|
||||
|
||||
# Build ks-apiserver binary
|
||||
ks-apiserver: ; $(info $(M)...Begin to build ks-apiserver binary.) @ ## Build ks-apiserver.
|
||||
hack/gobuild.sh cmd/ks-apiserver;
|
||||
|
||||
# Run all verify scripts hack/verify-*.sh
|
||||
verify-all: ; $(info $(M)...Begin to run all verify scripts hack/verify-*.sh.) @ ## Run all verify scripts hack/verify-*.sh.
|
||||
hack/verify-all.sh
|
||||
|
||||
# Build e2e binary
|
||||
e2e: ;$(info $(M)...Begin to build e2e binary.) @ ## Build e2e binary.
|
||||
hack/build_e2e.sh test/e2e
|
||||
|
||||
kind-e2e: ;$(info $(M)...Run e2e test.) @ ## Run e2e test in kind.
|
||||
hack/kind_e2e.sh
|
||||
|
||||
# Run go fmt against code
|
||||
fmt: ;$(info $(M)...Begin to run go fmt against code.) @ ## Run go fmt against code.
|
||||
gofmt -w ./pkg ./cmd ./tools ./api
|
||||
|
||||
# Format all import, `goimports` is required.
|
||||
goimports: ;$(info $(M)...Begin to Format all import.) @ ## Format all import, `goimports` is required.
|
||||
@hack/update-goimports.sh
|
||||
|
||||
# Run go vet against code
|
||||
vet: ;$(info $(M)...Begin to run go vet against code.) @ ## Run go vet against code.
|
||||
go vet ./pkg/... ./cmd/...
|
||||
|
||||
# Generate manifests e.g. CRD, RBAC etc.
|
||||
manifests: ;$(info $(M)...Begin to generate manifests e.g. CRD, RBAC etc..) @ ## Generate manifests e.g. CRD, RBAC etc.
|
||||
hack/generate_manifests.sh ${CRD_OPTIONS} ${MANIFESTS}
|
||||
|
||||
deploy: manifests ;$(info $(M)...Begin to deploy.) @ ## Deploy.
|
||||
kubectl apply -f config/crds
|
||||
kustomize build config/default | kubectl apply -f -
|
||||
|
||||
mockgen: ;$(info $(M)...Begin to mockgen.) @ ## Mockgen.
|
||||
mockgen -package=openpitrix -source=pkg/simple/client/openpitrix/openpitrix.go -destination=pkg/simple/client/openpitrix/mock.go
|
||||
|
||||
deepcopy: ;$(info $(M)...Begin to deepcopy.) @ ## Deepcopy.
|
||||
hack/generate_group.sh "deepcopy" kubesphere.io/api kubesphere.io/api ${GV} --output-base=staging/src/ -h "hack/boilerplate.go.txt"
|
||||
|
||||
openapi: ;$(info $(M)...Begin to openapi.) @ ## Openapi.
|
||||
go run ./vendor/k8s.io/kube-openapi/cmd/openapi-gen/openapi-gen.go -O openapi_generated -i ./vendor/k8s.io/apimachinery/pkg/apis/meta/v1,./vendor/kubesphere.io/api/tenant/v1alpha1 -p kubesphere.io/api/tenant/v1alpha1 -h ./hack/boilerplate.go.txt --report-filename ./api/api-rules/violation_exceptions.list --output-base=staging/src/
|
||||
go run ./vendor/k8s.io/kube-openapi/cmd/openapi-gen/openapi-gen.go -O openapi_generated -i ./vendor/k8s.io/apimachinery/pkg/apis/meta/v1,./vendor/kubesphere.io/api/network/v1alpha1 -p kubesphere.io/api/network/v1alpha1 -h ./hack/boilerplate.go.txt --report-filename ./api/api-rules/violation_exceptions.list --output-base=staging/src/
|
||||
go run ./vendor/k8s.io/kube-openapi/cmd/openapi-gen/openapi-gen.go -O openapi_generated -i ./vendor/k8s.io/apimachinery/pkg/apis/meta/v1,./vendor/kubesphere.io/api/servicemesh/v1alpha2 -p kubesphere.io/api/servicemesh/v1alpha2 -h ./hack/boilerplate.go.txt --report-filename ./api/api-rules/violation_exceptions.list --output-base=staging/src/
|
||||
go run ./vendor/k8s.io/kube-openapi/cmd/openapi-gen/openapi-gen.go -O openapi_generated -i ./vendor/k8s.io/api/networking/v1,./vendor/k8s.io/apimachinery/pkg/apis/meta/v1,./vendor/k8s.io/apimachinery/pkg/util/intstr,./vendor/kubesphere.io/api/network/v1alpha1 -p kubesphere.io/api/network/v1alpha1 -h ./hack/boilerplate.go.txt --report-filename ./api/api-rules/violation_exceptions.list --output-base=staging/src/
|
||||
go run ./vendor/k8s.io/kube-openapi/cmd/openapi-gen/openapi-gen.go -O openapi_generated -i ./vendor/k8s.io/apimachinery/pkg/apis/meta/v1,./vendor/kubesphere.io/api/devops/v1alpha1,./vendor/k8s.io/apimachinery/pkg/runtime,./vendor/k8s.io/api/core/v1 -p kubesphere.io/api/devops/v1alpha1 -h ./hack/boilerplate.go.txt --report-filename ./api/api-rules/violation_exceptions.list --output-base=staging/src/
|
||||
go run ./vendor/k8s.io/kube-openapi/cmd/openapi-gen/openapi-gen.go -O openapi_generated -i ./vendor/k8s.io/apimachinery/pkg/apis/meta/v1,./vendor/kubesphere.io/api/cluster/v1alpha1,./vendor/k8s.io/apimachinery/pkg/runtime,./vendor/k8s.io/api/core/v1 -p kubesphere.io/api/cluster/v1alpha1 -h ./hack/boilerplate.go.txt --report-filename ./api/api-rules/violation_exceptions.list --output-base=staging/src/
|
||||
go run ./vendor/k8s.io/kube-openapi/cmd/openapi-gen/openapi-gen.go -O openapi_generated -i ./vendor/k8s.io/apimachinery/pkg/apis/meta/v1,./vendor/kubesphere.io/api/devops/v1alpha3,./vendor/k8s.io/apimachinery/pkg/runtime -p kubesphere.io/api/devops/v1alpha3 -h ./hack/boilerplate.go.txt --report-filename ./api/api-rules/violation_exceptions.list --output-base=staging/src/
|
||||
go run ./tools/cmd/crd-doc-gen/main.go
|
||||
go run ./tools/cmd/doc-gen/main.go
|
||||
|
||||
container: ;$(info $(M)...Begin to build the docker image.) @ ## Build the docker image.
|
||||
DRY_RUN=true hack/docker_build.sh
|
||||
|
||||
container-push: ;$(info $(M)...Begin to build and push.) @ ## Build and Push.
|
||||
hack/docker_build.sh
|
||||
|
||||
container-cross: ; $(info $(M)...Begin to build container images for multiple platforms.) @ ## Build container images for multiple platforms. Currently, only linux/amd64,linux/arm64 are supported.
|
||||
DRY_RUN=true hack/docker_build_multiarch.sh
|
||||
|
||||
container-cross-push: ; $(info $(M)...Begin to build and push.) @ ## Build and Push.
|
||||
hack/docker_build_multiarch.sh
|
||||
|
||||
helm-package: ; $(info $(M)...Begin to helm-package.) @ ## Helm-package.
|
||||
ls config/crds/ | xargs -i cp -r config/crds/{} config/ks-core/crds/
|
||||
helm package config/ks-core --app-version=${APP_VERSION} --version=0.1.0 -d ./bin
|
||||
|
||||
helm-deploy: ; $(info $(M)...Begin to helm-deploy.) @ ## Helm-deploy.
|
||||
ls config/crds/ | xargs -i cp -r config/crds/{} config/ks-core/crds/
|
||||
- kubectl create ns kubesphere-controls-system
|
||||
helm upgrade --install ks-core ./config/ks-core -n kubesphere-system --create-namespace
|
||||
kubectl apply -f https://raw.githubusercontent.com/kubesphere/ks-installer/master/roles/ks-core/prepare/files/ks-init/role-templates.yaml
|
||||
|
||||
helm-uninstall: ; $(info $(M)...Begin to helm-uninstall.) @ ## Helm-uninstall.
|
||||
- kubectl delete ns kubesphere-controls-system
|
||||
helm uninstall ks-core -n kubesphere-system
|
||||
kubectl delete -f https://raw.githubusercontent.com/kubesphere/ks-installer/master/roles/ks-core/prepare/files/ks-init/role-templates.yaml
|
||||
|
||||
# Run tests
|
||||
ENVTEST_ASSETS_DIR=$(shell pwd)/testbin
|
||||
test: vet test-env ;$(info $(M)...Begin to run tests.) @ ## Run tests.
|
||||
export KUBEBUILDER_ASSETS=$(shell pwd)/testbin/bin; go test ./pkg/... ./cmd/... -covermode=atomic -coverprofile=coverage.txt
|
||||
cd staging/src/kubesphere.io/api ; GOFLAGS="" go test ./...
|
||||
cd staging/src/kubesphere.io/client-go ; GOFLAGS="" go test ./...
|
||||
|
||||
.PHONY: test-env
|
||||
test-env: ;$(info $(M)...Begin to setup test env) @ ## Download unit test libraries e.g. kube-apiserver etcd.
|
||||
@hack/setup-kubebuilder-env.sh
|
||||
|
||||
.PHONY: clean
|
||||
clean: ;$(info $(M)...Begin to clean.) @ ## Clean.
|
||||
-make -C ./pkg/version clean
|
||||
@echo "ok"
|
||||
|
||||
clientset: ;$(info $(M)...Begin to find or download controller-gen.) @ ## Find or download controller-gen,download controller-gen if necessary.
|
||||
./hack/generate_client.sh ${GV}
|
||||
|
||||
# Fix invalid file's license.
|
||||
update-licenses: ;$(info $(M)...Begin to update licenses.)
|
||||
@hack/update-licenses.sh
|
||||
@@ -0,0 +1,95 @@
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,APIGroup,ServerAddressByClientCIDRs
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,APIGroup,Versions
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,APIGroupList,Groups
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,APIResource,Categories
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,APIResource,ShortNames
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,APIResourceList,APIResources
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,APIVersions,ServerAddressByClientCIDRs
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,APIVersions,Versions
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,ApplyOptions,DryRun
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,CreateOptions,DryRun
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,DeleteOptions,DryRun
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,FieldsV1,Raw
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,LabelSelector,MatchExpressions
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,LabelSelectorRequirement,Values
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,ObjectMeta,Finalizers
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,ObjectMeta,ManagedFields
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,ObjectMeta,OwnerReferences
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,PatchOptions,DryRun
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,RootPaths,Paths
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,StatusDetails,Causes
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,Table,ColumnDefinitions
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,Table,Rows
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,TableRow,Cells
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,TableRow,Conditions
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,UpdateOptions,DryRun
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/runtime,RawExtension,Raw
|
||||
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/runtime,Unknown,Raw
|
||||
API rule violation: list_type_missing,kubesphere.io/api/devops/v1alpha3,NoScmPipeline,Parameters
|
||||
API rule violation: names_match,k8s.io/apimachinery/pkg/apis/meta/v1,APIResourceList,APIResources
|
||||
API rule violation: names_match,k8s.io/apimachinery/pkg/apis/meta/v1,Duration,Duration
|
||||
API rule violation: names_match,k8s.io/apimachinery/pkg/apis/meta/v1,InternalEvent,Object
|
||||
API rule violation: names_match,k8s.io/apimachinery/pkg/apis/meta/v1,InternalEvent,Type
|
||||
API rule violation: names_match,k8s.io/apimachinery/pkg/apis/meta/v1,MicroTime,Time
|
||||
API rule violation: names_match,k8s.io/apimachinery/pkg/apis/meta/v1,StatusCause,Type
|
||||
API rule violation: names_match,k8s.io/apimachinery/pkg/apis/meta/v1,Time,Time
|
||||
API rule violation: names_match,k8s.io/apimachinery/pkg/runtime,Unknown,ContentEncoding
|
||||
API rule violation: names_match,k8s.io/apimachinery/pkg/runtime,Unknown,ContentType
|
||||
API rule violation: names_match,k8s.io/apimachinery/pkg/runtime,Unknown,Raw
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,BitbucketServerSource,ApiUri
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,BitbucketServerSource,CloneOption
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,BitbucketServerSource,CredentialId
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,BitbucketServerSource,DiscoverBranches
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,BitbucketServerSource,DiscoverPRFromForks
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,BitbucketServerSource,DiscoverPRFromOrigin
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,BitbucketServerSource,DiscoverTags
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,BitbucketServerSource,RegexFilter
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,BitbucketServerSource,ScmId
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,DiscarderProperty,DaysToKeep
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,DiscarderProperty,NumToKeep
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,GitSource,CloneOption
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,GitSource,CredentialId
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,GitSource,DiscoverBranches
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,GitSource,DiscoverTags
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,GitSource,RegexFilter
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,GitSource,ScmId
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,GithubSource,ApiUri
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,GithubSource,CloneOption
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,GithubSource,CredentialId
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,GithubSource,DiscoverBranches
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,GithubSource,DiscoverPRFromForks
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,GithubSource,DiscoverPRFromOrigin
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,GithubSource,DiscoverTags
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,GithubSource,RegexFilter
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,GithubSource,ScmId
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,GitlabSource,ApiUri
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,GitlabSource,CloneOption
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,GitlabSource,CredentialId
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,GitlabSource,DiscoverBranches
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,GitlabSource,DiscoverPRFromForks
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,GitlabSource,DiscoverPRFromOrigin
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,GitlabSource,DiscoverTags
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,GitlabSource,RegexFilter
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,GitlabSource,ScmId
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,GitlabSource,ServerName
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,MultiBranchJobTrigger,CreateActionJobsToTrigger
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,MultiBranchJobTrigger,DeleteActionJobsToTrigger
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,MultiBranchPipeline,BitbucketServerSource
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,MultiBranchPipeline,GitHubSource
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,MultiBranchPipeline,GitSource
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,MultiBranchPipeline,GitlabSource
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,MultiBranchPipeline,MultiBranchJobTrigger
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,MultiBranchPipeline,ScriptPath
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,MultiBranchPipeline,SingleSvnSource
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,MultiBranchPipeline,SourceType
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,MultiBranchPipeline,SvnSource
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,MultiBranchPipeline,TimerTrigger
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,NoScmPipeline,DisableConcurrent
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,NoScmPipeline,RemoteTrigger
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,NoScmPipeline,TimerTrigger
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,Parameter,DefaultValue
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,PipelineSpec,MultiBranchPipeline
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,SingleSvnSource,CredentialId
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,SingleSvnSource,ScmId
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,SvnSource,CredentialId
|
||||
API rule violation: names_match,kubesphere.io/api/devops/v1alpha3,SvnSource,ScmId
|
||||
49
infrastructure/kubesphere/build/ks-apiserver/Dockerfile
Normal file
@@ -0,0 +1,49 @@
|
||||
# Copyright 2020 The KubeSphere Authors. All rights reserved.
|
||||
# Use of this source code is governed by an Apache license
|
||||
# that can be found in the LICENSE file.
|
||||
|
||||
# Download dependencies
|
||||
FROM alpine:3.11 as base_os_context
|
||||
|
||||
ARG TARGETARCH
|
||||
ARG TARGETOS
|
||||
ARG HELM_VERSION=v3.5.2
|
||||
|
||||
ENV OUTDIR=/out
|
||||
RUN mkdir -p ${OUTDIR}/usr/local/bin/
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
RUN apk add --no-cache ca-certificates
|
||||
|
||||
# install helm
|
||||
ADD https://get.helm.sh/helm-${HELM_VERSION}-${TARGETOS}-${TARGETARCH}.tar.gz /tmp
|
||||
RUN tar xvzf /tmp/helm-${HELM_VERSION}-${TARGETOS}-${TARGETARCH}.tar.gz -C /tmp
|
||||
RUN mv /tmp/${TARGETOS}-${TARGETARCH}/helm ${OUTDIR}/usr/local/bin/
|
||||
|
||||
# Build
|
||||
FROM golang:1.24.0 as build_context
|
||||
|
||||
ENV OUTDIR=/out
|
||||
RUN mkdir -p ${OUTDIR}/usr/local/bin/
|
||||
|
||||
WORKDIR /workspace
|
||||
ADD . /workspace/
|
||||
|
||||
RUN make ks-apiserver
|
||||
RUN mv /workspace/bin/cmd/ks-apiserver ${OUTDIR}/usr/local/bin/
|
||||
|
||||
##############
|
||||
# Final image
|
||||
#############
|
||||
|
||||
FROM alpine:3.11
|
||||
|
||||
COPY --from=base_os_context /out/ /
|
||||
COPY --from=build_context /out/ /
|
||||
RUN apk update && apk add bash
|
||||
|
||||
WORKDIR /
|
||||
|
||||
EXPOSE 9090
|
||||
CMD ["sh"]
|
||||
32
infrastructure/kubesphere/cmd/ks-apiserver/apiserver.go
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Copyright 2019 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 main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"kubesphere.io/kubesphere/cmd/ks-apiserver/app"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
cmd := app.NewAPIServerCommand()
|
||||
|
||||
if err := cmd.Execute(); err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
Copyright 2020 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 options
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
cliflag "k8s.io/component-base/cli/flag"
|
||||
"k8s.io/klog"
|
||||
runtimecache "sigs.k8s.io/controller-runtime/pkg/cache"
|
||||
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
extv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
"kubesphere.io/kubesphere/pkg/apis"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver"
|
||||
apiserverconfig "kubesphere.io/kubesphere/pkg/apiserver/config"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
genericoptions "kubesphere.io/kubesphere/pkg/server/options"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/alerting"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/cache"
|
||||
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/monitoring/metricsserver"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/monitoring/prometheus"
|
||||
)
|
||||
|
||||
type ServerRunOptions struct {
|
||||
ConfigFile string
|
||||
GenericServerRunOptions *genericoptions.ServerRunOptions
|
||||
*apiserverconfig.Config
|
||||
|
||||
//
|
||||
DebugMode bool
|
||||
}
|
||||
|
||||
func NewServerRunOptions() *ServerRunOptions {
|
||||
s := &ServerRunOptions{
|
||||
GenericServerRunOptions: genericoptions.NewServerRunOptions(),
|
||||
Config: apiserverconfig.New(),
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *ServerRunOptions) Flags() (fss cliflag.NamedFlagSets) {
|
||||
fs := fss.FlagSet("generic")
|
||||
fs.BoolVar(&s.DebugMode, "debug", false, "Don't enable this if you don't know what it means.")
|
||||
s.GenericServerRunOptions.AddFlags(fs, s.GenericServerRunOptions)
|
||||
s.KubernetesOptions.AddFlags(fss.FlagSet("kubernetes"), s.KubernetesOptions)
|
||||
s.AuthorizationOptions.AddFlags(fss.FlagSet("authorization"), s.AuthorizationOptions)
|
||||
s.MonitoringOptions.AddFlags(fss.FlagSet("monitoring"), s.MonitoringOptions)
|
||||
s.LoggingOptions.AddFlags(fss.FlagSet("logging"), s.LoggingOptions)
|
||||
s.EventsOptions.AddFlags(fss.FlagSet("events"), s.EventsOptions)
|
||||
s.AlertingOptions.AddFlags(fss.FlagSet("alerting"), s.AlertingOptions)
|
||||
|
||||
fs = fss.FlagSet("klog")
|
||||
local := flag.NewFlagSet("klog", flag.ExitOnError)
|
||||
klog.InitFlags(local)
|
||||
local.VisitAll(func(fl *flag.Flag) {
|
||||
fl.Name = strings.Replace(fl.Name, "_", "-", -1)
|
||||
fs.AddGoFlag(fl)
|
||||
})
|
||||
|
||||
return fss
|
||||
}
|
||||
|
||||
const fakeInterface string = "FAKE"
|
||||
|
||||
// NewAPIServer creates an APIServer instance using given options
|
||||
func (s *ServerRunOptions) NewAPIServer(stopCh <-chan struct{}) (*apiserver.APIServer, error) {
|
||||
apiServer := &apiserver.APIServer{
|
||||
Config: s.Config,
|
||||
}
|
||||
|
||||
kubernetesClient, err := k8s.NewKubernetesClient(s.KubernetesOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
apiServer.KubernetesClient = kubernetesClient
|
||||
|
||||
informerFactory := informers.NewInformerFactories(kubernetesClient.Kubernetes(), kubernetesClient.KubeSphere(),
|
||||
kubernetesClient.Istio(), kubernetesClient.Snapshot(), kubernetesClient.ApiExtensions(), kubernetesClient.Prometheus())
|
||||
apiServer.InformerFactory = informerFactory
|
||||
|
||||
if s.MonitoringOptions == nil || len(s.MonitoringOptions.Endpoint) == 0 {
|
||||
return nil, fmt.Errorf("moinitoring service address in configuration MUST not be empty, please check configmap/kubesphere-config in kubesphere-system namespace")
|
||||
} else {
|
||||
monitoringClient, err := prometheus.NewPrometheus(s.MonitoringOptions)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to connect to prometheus, please check prometheus status, error: %v", err)
|
||||
}
|
||||
apiServer.MonitoringClient = monitoringClient
|
||||
}
|
||||
|
||||
apiServer.MetricsClient = metricsserver.NewMetricsClient(kubernetesClient.Kubernetes(), s.KubernetesOptions)
|
||||
|
||||
apiServer.CacheClient = cache.NewSimpleCache()
|
||||
|
||||
if s.AlertingOptions != nil && (s.AlertingOptions.PrometheusEndpoint != "" || s.AlertingOptions.ThanosRulerEndpoint != "") {
|
||||
alertingClient, err := alerting.NewRuleClient(s.AlertingOptions)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to init alerting client: %v", err)
|
||||
}
|
||||
apiServer.AlertingClient = alertingClient
|
||||
}
|
||||
|
||||
server := &http.Server{
|
||||
Addr: fmt.Sprintf(":%d", s.GenericServerRunOptions.InsecurePort),
|
||||
}
|
||||
|
||||
if s.GenericServerRunOptions.SecurePort != 0 {
|
||||
certificate, err := tls.LoadX509KeyPair(s.GenericServerRunOptions.TlsCertFile, s.GenericServerRunOptions.TlsPrivateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
server.TLSConfig = &tls.Config{
|
||||
Certificates: []tls.Certificate{certificate},
|
||||
}
|
||||
server.Addr = fmt.Sprintf(":%d", s.GenericServerRunOptions.SecurePort)
|
||||
}
|
||||
|
||||
sch := scheme.Scheme
|
||||
if err := apis.AddToScheme(sch); err != nil {
|
||||
klog.Fatalf("unable add APIs to scheme: %v", err)
|
||||
}
|
||||
if err := extv1.AddToScheme(sch); err != nil {
|
||||
klog.Fatalf("unable add apiextensions v1 APIs to scheme: %v", err)
|
||||
}
|
||||
|
||||
apiServer.RuntimeCache, err = runtimecache.New(apiServer.KubernetesClient.Config(), runtimecache.Options{Scheme: sch})
|
||||
if err != nil {
|
||||
klog.Fatalf("unable to create controller runtime cache: %v", err)
|
||||
}
|
||||
|
||||
apiServer.RuntimeClient, err = runtimeclient.New(apiServer.KubernetesClient.Config(), runtimeclient.Options{Scheme: sch})
|
||||
if err != nil {
|
||||
klog.Fatalf("unable to create controller runtime client: %v", err)
|
||||
}
|
||||
|
||||
apiServer.Server = server
|
||||
|
||||
return apiServer, nil
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Copyright 2020 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 options
|
||||
|
||||
// Validate validates server run options, to find
|
||||
// options' misconfiguration
|
||||
func (s *ServerRunOptions) Validate() []error {
|
||||
var errors []error
|
||||
|
||||
errors = append(errors, s.GenericServerRunOptions.Validate()...)
|
||||
errors = append(errors, s.KubernetesOptions.Validate()...)
|
||||
errors = append(errors, s.MonitoringOptions.Validate()...)
|
||||
errors = append(errors, s.LoggingOptions.Validate()...)
|
||||
errors = append(errors, s.AuthorizationOptions.Validate()...)
|
||||
errors = append(errors, s.EventsOptions.Validate()...)
|
||||
errors = append(errors, s.AlertingOptions.Validate()...)
|
||||
|
||||
return errors
|
||||
}
|
||||
143
infrastructure/kubesphere/cmd/ks-apiserver/app/server.go
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
Copyright 2019 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 app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
cliflag "k8s.io/component-base/cli/flag"
|
||||
"k8s.io/klog"
|
||||
|
||||
"sigs.k8s.io/controller-runtime/pkg/manager/signals"
|
||||
|
||||
"kubesphere.io/kubesphere/cmd/ks-apiserver/app/options"
|
||||
apiserverconfig "kubesphere.io/kubesphere/pkg/apiserver/config"
|
||||
"kubesphere.io/kubesphere/pkg/utils/term"
|
||||
"kubesphere.io/kubesphere/pkg/version"
|
||||
)
|
||||
|
||||
func NewAPIServerCommand() *cobra.Command {
|
||||
s := options.NewServerRunOptions()
|
||||
|
||||
// Load configuration from file
|
||||
conf, err := apiserverconfig.TryLoadFromDisk()
|
||||
if err == nil {
|
||||
s = &options.ServerRunOptions{
|
||||
GenericServerRunOptions: s.GenericServerRunOptions,
|
||||
Config: conf,
|
||||
}
|
||||
} else {
|
||||
klog.Fatal("Failed to load configuration from disk", err)
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "ks-apiserver",
|
||||
Long: `The KubeSphere API server validates and configures data for the API objects.
|
||||
The API Server services REST operations and provides the frontend to the
|
||||
cluster's shared state through which all other components interact.`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if errs := s.Validate(); len(errs) != 0 {
|
||||
return utilerrors.NewAggregate(errs)
|
||||
}
|
||||
|
||||
return Run(s, apiserverconfig.WatchConfigChange(), signals.SetupSignalHandler())
|
||||
},
|
||||
SilenceUsage: true,
|
||||
}
|
||||
|
||||
fs := cmd.Flags()
|
||||
namedFlagSets := s.Flags()
|
||||
for _, f := range namedFlagSets.FlagSets {
|
||||
fs.AddFlagSet(f)
|
||||
}
|
||||
|
||||
usageFmt := "Usage:\n %s\n"
|
||||
cols, _, _ := term.TerminalSize(cmd.OutOrStdout())
|
||||
cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) {
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "%s\n\n"+usageFmt, cmd.Long, cmd.UseLine())
|
||||
cliflag.PrintSections(cmd.OutOrStdout(), namedFlagSets, cols)
|
||||
})
|
||||
|
||||
versionCmd := &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Print the version of KubeSphere ks-apiserver",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cmd.Println(version.Get())
|
||||
},
|
||||
}
|
||||
|
||||
cmd.AddCommand(versionCmd)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func Run(s *options.ServerRunOptions, configCh <-chan apiserverconfig.Config, ctx context.Context) error {
|
||||
ictx, cancelFunc := context.WithCancel(context.TODO())
|
||||
errCh := make(chan error)
|
||||
defer close(errCh)
|
||||
go func() {
|
||||
if err := run(s, ictx); err != nil {
|
||||
errCh <- err
|
||||
}
|
||||
}()
|
||||
|
||||
// The ctx (signals.SetupSignalHandler()) is to control the entire program life cycle,
|
||||
// The ictx(internal context) is created here to control the life cycle of the ks-apiserver(http server, sharedInformer etc.)
|
||||
// when config change, stop server and renew context, start new server
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
cancelFunc()
|
||||
return nil
|
||||
case cfg := <-configCh:
|
||||
cancelFunc()
|
||||
s.Config = &cfg
|
||||
ictx, cancelFunc = context.WithCancel(context.TODO())
|
||||
go func() {
|
||||
if err := run(s, ictx); err != nil {
|
||||
errCh <- err
|
||||
}
|
||||
}()
|
||||
case err := <-errCh:
|
||||
cancelFunc()
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func run(s *options.ServerRunOptions, ctx context.Context) error {
|
||||
apiserver, err := s.NewAPIServer(ctx.Done())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = apiserver.PrepareRun(ctx.Done())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = apiserver.Run(ctx)
|
||||
if errors.Is(err, http.ErrServerClosed) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: (devel)
|
||||
creationTimestamp: null
|
||||
name: globalrolebindings.iam.kubesphere.io
|
||||
spec:
|
||||
group: iam.kubesphere.io
|
||||
names:
|
||||
categories:
|
||||
- iam
|
||||
kind: GlobalRoleBinding
|
||||
listKind: GlobalRoleBindingList
|
||||
plural: globalrolebindings
|
||||
singular: globalrolebinding
|
||||
scope: Cluster
|
||||
versions:
|
||||
- name: v1alpha2
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: GlobalRoleBinding is the Schema for the globalrolebindings API
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
roleRef:
|
||||
description: RoleRef can only reference a GlobalRole. If the RoleRef cannot
|
||||
be resolved, the Authorizer must return an error.
|
||||
properties:
|
||||
apiGroup:
|
||||
description: APIGroup is the group for the resource being referenced
|
||||
type: string
|
||||
kind:
|
||||
description: Kind is the type of resource being referenced
|
||||
type: string
|
||||
name:
|
||||
description: Name is the name of resource being referenced
|
||||
type: string
|
||||
required:
|
||||
- apiGroup
|
||||
- kind
|
||||
- name
|
||||
type: object
|
||||
subjects:
|
||||
description: Subjects holds references to the objects the role applies
|
||||
to.
|
||||
items:
|
||||
description: Subject contains a reference to the object or user identities
|
||||
a role binding applies to. This can either hold a direct API object
|
||||
reference, or a value for non-objects such as user and group names.
|
||||
properties:
|
||||
apiGroup:
|
||||
description: APIGroup holds the API group of the referenced subject.
|
||||
Defaults to "" for ServiceAccount subjects. Defaults to "rbac.authorization.k8s.io"
|
||||
for User and Group subjects.
|
||||
type: string
|
||||
kind:
|
||||
description: Kind of object being referenced. Values defined by
|
||||
this API group are "User", "Group", and "ServiceAccount". If the
|
||||
Authorizer does not recognized the kind value, the Authorizer
|
||||
should report an error.
|
||||
type: string
|
||||
name:
|
||||
description: Name of the object being referenced.
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace of the referenced object. If the object
|
||||
kind is non-namespace, such as "User" or "Group", and this value
|
||||
is not empty the Authorizer should report an error.
|
||||
type: string
|
||||
required:
|
||||
- kind
|
||||
- name
|
||||
type: object
|
||||
type: array
|
||||
required:
|
||||
- roleRef
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
@@ -0,0 +1,94 @@
|
||||
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: (devel)
|
||||
creationTimestamp: null
|
||||
name: globalroles.iam.kubesphere.io
|
||||
spec:
|
||||
group: iam.kubesphere.io
|
||||
names:
|
||||
categories:
|
||||
- iam
|
||||
kind: GlobalRole
|
||||
listKind: GlobalRoleList
|
||||
plural: globalroles
|
||||
singular: globalrole
|
||||
scope: Cluster
|
||||
versions:
|
||||
- name: v1alpha2
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
rules:
|
||||
description: Rules holds all the PolicyRules for this GlobalRole
|
||||
items:
|
||||
description: PolicyRule holds information that describes a policy rule,
|
||||
but does not contain information about who the rule applies to or
|
||||
which namespace the rule applies to.
|
||||
properties:
|
||||
apiGroups:
|
||||
description: APIGroups is the name of the APIGroup that contains
|
||||
the resources. If multiple API groups are specified, any action
|
||||
requested against one of the enumerated resources in any API group
|
||||
will be allowed.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
nonResourceURLs:
|
||||
description: NonResourceURLs is a set of partial urls that a user
|
||||
should have access to. *s are allowed, but only as the full,
|
||||
final step in the path Since non-resource URLs are not namespaced,
|
||||
this field is only applicable for ClusterRoles referenced from
|
||||
a ClusterRoleBinding. Rules can either apply to API resources
|
||||
(such as "pods" or "secrets") or non-resource URL paths (such
|
||||
as "/api"), but not both.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
resourceNames:
|
||||
description: ResourceNames is an optional white list of names that
|
||||
the rule applies to. An empty set means that everything is allowed.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
resources:
|
||||
description: Resources is a list of resources this rule applies
|
||||
to. ResourceAll represents all resources.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
verbs:
|
||||
description: Verbs is a list of Verbs that apply to ALL the ResourceKinds
|
||||
and AttributeRestrictions contained in this rule. VerbAll represents
|
||||
all kinds.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
required:
|
||||
- verbs
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
@@ -0,0 +1,51 @@
|
||||
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: (devel)
|
||||
creationTimestamp: null
|
||||
name: rolebases.iam.kubesphere.io
|
||||
spec:
|
||||
group: iam.kubesphere.io
|
||||
names:
|
||||
categories:
|
||||
- iam
|
||||
kind: RoleBase
|
||||
listKind: RoleBaseList
|
||||
plural: rolebases
|
||||
singular: rolebase
|
||||
scope: Cluster
|
||||
versions:
|
||||
- name: v1alpha2
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
role:
|
||||
type: object
|
||||
x-kubernetes-embedded-resource: true
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
required:
|
||||
- role
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
@@ -0,0 +1,98 @@
|
||||
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: (devel)
|
||||
creationTimestamp: null
|
||||
name: syncs.iam.kubesphere.io
|
||||
spec:
|
||||
group: iam.kubesphere.io
|
||||
names:
|
||||
categories:
|
||||
- all
|
||||
kind: Sync
|
||||
listKind: SyncList
|
||||
plural: syncs
|
||||
shortNames:
|
||||
- sync
|
||||
singular: sync
|
||||
scope: Cluster
|
||||
versions:
|
||||
- additionalPrinterColumns:
|
||||
- jsonPath: .spec.name
|
||||
name: sync name
|
||||
type: string
|
||||
- jsonPath: .spec.namespace
|
||||
name: namespace
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: age
|
||||
type: date
|
||||
name: v1alpha2
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: Sync is the Schema for the sync API
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: SyncSpec defines the desired state of Sync
|
||||
properties:
|
||||
lldap:
|
||||
properties:
|
||||
credentialsSecret:
|
||||
properties:
|
||||
kind:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
required:
|
||||
- kind
|
||||
- name
|
||||
- namespace
|
||||
type: object
|
||||
groupWhitelist:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
userBlacklist:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
required:
|
||||
- credentialsSecret
|
||||
- name
|
||||
- url
|
||||
type: object
|
||||
required:
|
||||
- lldap
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
@@ -0,0 +1,97 @@
|
||||
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: (devel)
|
||||
creationTimestamp: null
|
||||
name: users.iam.kubesphere.io
|
||||
spec:
|
||||
group: iam.kubesphere.io
|
||||
names:
|
||||
categories:
|
||||
- iam
|
||||
kind: User
|
||||
listKind: UserList
|
||||
plural: users
|
||||
singular: user
|
||||
scope: Cluster
|
||||
versions:
|
||||
- additionalPrinterColumns:
|
||||
- jsonPath: .spec.email
|
||||
name: Email
|
||||
type: string
|
||||
- jsonPath: .status.state
|
||||
name: Status
|
||||
type: string
|
||||
name: v1alpha2
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: User is the Schema for the users API
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: UserSpec defines the desired state of User
|
||||
properties:
|
||||
description:
|
||||
description: Description of the user.
|
||||
type: string
|
||||
displayName:
|
||||
type: string
|
||||
email:
|
||||
description: Unique email address(https://www.ietf.org/rfc/rfc5322.txt).
|
||||
type: string
|
||||
groups:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
initialPassword:
|
||||
description: InitialPassword only for the first user that need sync
|
||||
from here to lldap
|
||||
type: string
|
||||
lang:
|
||||
description: The preferred written or spoken language for the user.
|
||||
type: string
|
||||
required:
|
||||
- email
|
||||
type: object
|
||||
status:
|
||||
description: UserStatus defines the observed state of User
|
||||
properties:
|
||||
lastLoginTime:
|
||||
description: Last login attempt timestamp
|
||||
format: date-time
|
||||
type: string
|
||||
lastTransitionTime:
|
||||
format: date-time
|
||||
type: string
|
||||
reason:
|
||||
type: string
|
||||
state:
|
||||
description: The user status
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- spec
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
14
infrastructure/kubesphere/config/watches.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
# Use the 'create api' subcommand to add watches to this file.
|
||||
- group: gateway.kubesphere.io
|
||||
version: v1alpha1
|
||||
kind: Nginx
|
||||
chart: /var/helm-charts/ingress-nginx
|
||||
- group: gateway.kubesphere.io
|
||||
version: v1alpha1
|
||||
kind: Gateway
|
||||
chart: /var/helm-charts/gateway
|
||||
# uncomment the following 2 lines, if only allow to run global scope or namespaced scope.
|
||||
# Leave the option to CR, when allow to run global and namespaced together.
|
||||
# overrideValues:
|
||||
# controller.scope.enabled: $SCOPE_ENABLED
|
||||
#+kubebuilder:scaffold:watch
|
||||