20 Star 1 Fork 10

openEuler-RISC-V/eggo

forked from src-openEuler/eggo 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
0011-run-hook-with-envs-of-cluster-info.patch 14.94 KB
一键复制 编辑 原始数据 按行查看 历史
zhangxiaoyu 提交于 2021-11-26 09:39 . upgrade to v0.9.4-2
From f1d2766bda44a878777ea266573236271dcc65ed Mon Sep 17 00:00:00 2001
From: haozi007 <liuhao27@huawei.com>
Date: Thu, 11 Nov 2021 11:15:37 +0000
Subject: [PATCH 11/12] run hook with envs of cluster info
Signed-off-by: haozi007 <liuhao27@huawei.com>
---
docs/hooks_of_eggo.md | 2 +-
pkg/api/tools.go | 29 ++++++++
pkg/api/types.go | 42 ++++++++++++
.../binary/infrastructure/infrastructure.go | 10 +--
pkg/utils/dependency/dependency.go | 40 ++++++++---
pkg/utils/dependency/dependency_test.go | 52 +++++++++++++++
pkg/utils/dependency/install.go | 66 +++++++++++++++----
pkg/utils/runner/runner.go | 16 ++---
8 files changed, 216 insertions(+), 41 deletions(-)
create mode 100644 pkg/utils/dependency/dependency_test.go
diff --git a/docs/hooks_of_eggo.md b/docs/hooks_of_eggo.md
index 92b9a38..b1f09cb 100644
--- a/docs/hooks_of_eggo.md
+++ b/docs/hooks_of_eggo.md
@@ -22,6 +22,7 @@
- 脚本目录下的所有脚本都会被执行,而子目录中的脚本不会被执行;
- 每个脚本的超时时间为60s;
+- role可以为master,worker,etcd或者loadbalance;
### 配置文件参数方式
@@ -60,4 +61,3 @@ eggo会在hook执行时,通过环境变量传递部分信息,用于脚本执
| EGGO_NODE_ROLE | hook执行的节点角色 |
| EGGO_HOOK_TYPE | hook的类型,prehook或者posthook |
| EGGO_OPERATOR | 当前的操作,deploy,cleanup,join,delete。 |
-
diff --git a/pkg/api/tools.go b/pkg/api/tools.go
index 861d70a..4c65dc2 100644
--- a/pkg/api/tools.go
+++ b/pkg/api/tools.go
@@ -55,6 +55,10 @@ func (p PackageSrcConfig) GetPkgDstPath() string {
return p.DstPath
}
+func (ep APIEndpoint) GetUrl() string {
+ return fmt.Sprintf("%s/%v", ep.AdvertiseAddress, ep.BindPort)
+}
+
func GetClusterHomePath(cluster string) string {
return filepath.Join(EggoHomePath, cluster)
}
@@ -191,3 +195,28 @@ func ParseScheduleType(schedule string) (ScheduleType, error) {
return SchedulePreJoin, fmt.Errorf("invalid schedule type: %s", schedule)
}
}
+
+func GetRoleString(roles uint16) []string {
+ var roleStrs []string
+ if roles&Master != 0 {
+ roleStrs = append(roleStrs, "master")
+ }
+ if roles&Worker != 0 {
+ roleStrs = append(roleStrs, "worker")
+ }
+ if roles&ETCD != 0 {
+ roleStrs = append(roleStrs, "etcd")
+ }
+ if roles&LoadBalance != 0 {
+ roleStrs = append(roleStrs, "loadbalance")
+ }
+
+ return roleStrs
+}
+
+func GetUserTempDir(user string) string {
+ if user == "root" {
+ return constants.DefaultRootCopyTempDirHome
+ }
+ return fmt.Sprintf(constants.DefaultUserCopyTempHomeFormat, user)
+}
diff --git a/pkg/api/types.go b/pkg/api/types.go
index 6a1351e..fea3f26 100644
--- a/pkg/api/types.go
+++ b/pkg/api/types.go
@@ -35,6 +35,37 @@ const (
SchedulePostCleanup ScheduleType = "postcleanup"
)
+type HookOperator string
+
+const (
+ HookOpDeploy HookOperator = "deploy"
+ HookOpCleanup HookOperator = "cleanup"
+ HookOpJoin HookOperator = "join"
+ HookOpDelete HookOperator = "delete"
+)
+
+type HookType string
+
+const (
+ PreHookType HookType = "prehook"
+ PostHookType HookType = "posthook"
+)
+
+type HookRunConfig struct {
+ ClusterID string
+ ClusterApiEndpoint string
+ ClusterConfigDir string
+
+ HookType HookType
+ Operator HookOperator
+
+ Node *HostConfig
+ Scheduler ScheduleType
+
+ HookDir string
+ Hooks []*PackageConfig
+}
+
type RoleInfra struct {
OpenPorts []*OpenPorts `json:"open-ports"`
Softwares []*PackageConfig `json:"softwares"`
@@ -201,6 +232,14 @@ type AddonConfig struct {
Filename string `json:"filename"`
}
+type ClusterHookConf struct {
+ Type HookType
+ Operator HookOperator
+ Target uint16
+ HookDir string
+ HookFiles []string
+}
+
type ClusterConfig struct {
Name string `json:"name"`
DeployDriver string `json:"deploy-driver"` // default is binary
@@ -218,6 +257,9 @@ type ClusterConfig struct {
WorkerConfig WorkerConfig `json:"workerconfig"`
RoleInfra map[uint16]*RoleInfra `json:"role-infra"`
+ // do not encode hooks, just set before use it
+ HooksConf *ClusterHookConf `json:"-"`
+
// TODO: add other configurations at here
}
diff --git a/pkg/clusterdeployment/binary/infrastructure/infrastructure.go b/pkg/clusterdeployment/binary/infrastructure/infrastructure.go
index 634e338..68faf36 100644
--- a/pkg/clusterdeployment/binary/infrastructure/infrastructure.go
+++ b/pkg/clusterdeployment/binary/infrastructure/infrastructure.go
@@ -27,7 +27,6 @@ import (
"isula.org/eggo/pkg/api"
"isula.org/eggo/pkg/clusterdeployment/binary/cleanupcluster"
- "isula.org/eggo/pkg/constants"
"isula.org/eggo/pkg/utils"
"isula.org/eggo/pkg/utils/dependency"
"isula.org/eggo/pkg/utils/nodemanager"
@@ -321,13 +320,6 @@ func (it *DestroyInfraTask) Name() string {
return "DestroyInfraTask"
}
-func getCopyDefaultDir(user string) string {
- if user == "root" {
- return constants.DefaultRootCopyTempDirHome
- }
- return fmt.Sprintf(constants.DefaultUserCopyTempHomeFormat, user)
-}
-
func (it *DestroyInfraTask) Run(r runner.Runner, hcg *api.HostConfig) error {
if hcg == nil {
return fmt.Errorf("empty host config")
@@ -348,7 +340,7 @@ func (it *DestroyInfraTask) Run(r runner.Runner, hcg *api.HostConfig) error {
logrus.Errorf("path %s not in White List and cannot remove", dstDir)
return nil
}
- copyTempDir := getCopyDefaultDir(hcg.UserName)
+ copyTempDir := api.GetUserTempDir(hcg.UserName)
if _, err := r.RunCommand(fmt.Sprintf("sudo -E /bin/sh -c \"rm -rf %s %s %s\"", dstDir, copyTempDir, it.k8sConfigDir)); err != nil {
return fmt.Errorf("rm dependency failed: %v", err)
}
diff --git a/pkg/utils/dependency/dependency.go b/pkg/utils/dependency/dependency.go
index 9e6ac22..2c5dc26 100644
--- a/pkg/utils/dependency/dependency.go
+++ b/pkg/utils/dependency/dependency.go
@@ -293,6 +293,7 @@ func (dy *dependencyYaml) Remove(r runner.Runner) error {
}
type dependencyShell struct {
+ envs []string
srcPath string
shell []*api.PackageConfig
}
@@ -305,22 +306,45 @@ func NewDependencyShell(srcPath string, shell []*api.PackageConfig) *dependencyS
}
func (ds *dependencyShell) Install(r runner.Runner) error {
- var sb strings.Builder
+ shellTemplate := `
+#!/bin/bash
+{{- range $i, $v := .Envs }}
+export {{ $v }}
+{{- end }}
- sb.WriteString("sudo -E /bin/sh -c \"")
- for _, s := range ds.shell {
- sb.WriteString(fmt.Sprintf("chmod +x %s/%s && ", ds.srcPath, s.Name))
+{{- $tout := .Timeouts }}
+{{- range $i, $v := .Shells }}
+chmod +x {{ $v }} && timeout -s SIGKILL {{index $tout $i}} {{ $v }} > /dev/null
+if [ $? -ne 0 ]; then
+ echo "run {{ $v }} failed"
+ exit 1
+fi
+{{- end }}
+exit 0
+`
+ datastore := map[string]interface{}{}
+ datastore["Envs"] = ds.envs
+ var shells []string
+ var timeouts []string
+ for _, s := range ds.shell {
+ shells = append(shells, fmt.Sprintf("%s/%s", ds.srcPath, s.Name))
timeout := s.TimeOut
if timeout == "" {
timeout = "30s"
}
- sb.WriteString(fmt.Sprintf("timeout -s SIGKILL %s %s/%s > /dev/null ; ", timeout, ds.srcPath, s.Name))
+ timeouts = append(timeouts, timeout)
}
- sb.WriteString("\"")
+ datastore["Shells"] = shells
+ datastore["Timeouts"] = timeouts
- if _, err := r.RunCommand(sb.String()); err != nil {
- return fmt.Errorf("shell execute failed: %v", err)
+ parsedShell, err := template.TemplateRender(shellTemplate, datastore)
+ if err != nil {
+ return err
+ }
+
+ if _, err := r.RunShell(parsedShell, "exechook"); err != nil {
+ return fmt.Errorf("hook execute failed: %v", err)
}
return nil
diff --git a/pkg/utils/dependency/dependency_test.go b/pkg/utils/dependency/dependency_test.go
new file mode 100644
index 0000000..58ea756
--- /dev/null
+++ b/pkg/utils/dependency/dependency_test.go
@@ -0,0 +1,52 @@
+package dependency
+
+import (
+ "testing"
+
+ "github.com/sirupsen/logrus"
+ "isula.org/eggo/pkg/api"
+)
+
+type MockRunner struct {
+}
+
+func (m *MockRunner) Copy(src, dst string) error {
+ logrus.Infof("copy %s to %s", src, dst)
+ return nil
+}
+
+func (m *MockRunner) RunCommand(cmd string) (string, error) {
+ logrus.Infof("run command: %s", cmd)
+ return "", nil
+}
+
+func (m *MockRunner) RunShell(shell string, name string) (string, error) {
+ logrus.Infof("run shell: %s, name: %s", shell, name)
+ return "", nil
+}
+
+func (m *MockRunner) Reconnect() error {
+ logrus.Infof("reconnect")
+ return nil
+}
+
+func (m *MockRunner) Close() {
+ logrus.Infof("close")
+}
+
+func TestNewDependencyShell(t *testing.T) {
+ var mr MockRunner
+
+ shell := &api.PackageConfig{
+ Name: "test.sh",
+ Type: "shell",
+ Dst: "/root",
+ Schedule: api.SchedulePreJoin,
+ TimeOut: "30s",
+ }
+
+ dp := NewDependencyShell("/tmp", []*api.PackageConfig{shell})
+ if err := dp.Install(&mr); err != nil {
+ t.Fatalf("run test failed: %v", err)
+ }
+}
diff --git a/pkg/utils/dependency/install.go b/pkg/utils/dependency/install.go
index 8687602..8cb80f6 100644
--- a/pkg/utils/dependency/install.go
+++ b/pkg/utils/dependency/install.go
@@ -349,33 +349,77 @@ func getShell(roleInfra *api.RoleInfra, schedule api.ScheduleType) []*api.Packag
return shell
}
-func ExecuteShell(roleInfra *api.RoleInfra, packagePath string, hcf *api.HostConfig, schedule api.ScheduleType) error {
- shell := getShell(roleInfra, schedule)
- if len(shell) == 0 {
+func ExecuteHooks(hookConf *api.HookRunConfig) error {
+ if hookConf == nil || len(hookConf.Hooks) == 0 {
return nil
}
- logrus.Debugf("run %s shell %v on %v\n", string(schedule), shell, hcf.Address)
- dp := &dependencyShell{
- srcPath: path.Join(packagePath, constants.DefaultFilePath),
- shell: shell,
+ var hookStr []string
+ for _, h := range hookConf.Hooks {
+ hookStr = append(hookStr, h.Name)
}
+ logrus.Debugf("run %s shell %v on %v\n", string(hookConf.Scheduler), hookStr, hookConf.Node.Address)
+
+ dp := &dependencyShell{
+ srcPath: hookConf.HookDir,
+ shell: hookConf.Hooks,
+ }
+ envs := make([]string, 9)
+ envs[0] = fmt.Sprintf("EGGO_CLUSTER_ID=%s", hookConf.ClusterID)
+ envs[1] = fmt.Sprintf("EGGO_CLUSTER_API_ENDPOINT=%s", hookConf.ClusterApiEndpoint)
+ envs[2] = fmt.Sprintf("EGGO_CLUSTER_CONFIG_DIR=%s", hookConf.ClusterConfigDir)
+ envs[3] = fmt.Sprintf("EGGO_NODE_IP=%s", hookConf.Node.Address)
+ envs[4] = fmt.Sprintf("EGGO_NODE_NAME=%s", hookConf.Node.Name)
+ envs[5] = fmt.Sprintf("EGGO_NODE_ARCH=%s", hookConf.Node.Arch)
+ envs[6] = fmt.Sprintf("EGGO_NODE_ROLE=%s", strings.Join(api.GetRoleString(hookConf.Node.Type), ","))
+ envs[7] = fmt.Sprintf("EGGO_HOOK_TYPE=%s", hookConf.HookType)
+ envs[8] = fmt.Sprintf("EGGO_OPERATOR=%s", hookConf.Operator)
+ dp.envs = envs
dependencyTask := task.NewTaskInstance(&DependencyTask{
dp: dp,
})
- if api.IsCleanupSchedule(schedule) {
+ if api.IsCleanupSchedule(hookConf.Scheduler) {
task.SetIgnoreErrorFlag(dependencyTask)
}
- if err := nodemanager.RunTaskOnNodes(dependencyTask, []string{hcf.Address}); err != nil {
- logrus.Errorf("Hook %s failed for %s: %v", string(api.SchedulePreJoin), hcf.Address, err)
+ if err := nodemanager.RunTaskOnNodes(dependencyTask, []string{hookConf.Node.Address}); err != nil {
+ logrus.Errorf("Hook %s failed for %s: %v", string(api.SchedulePreJoin), hookConf.Node.Address, err)
return err
}
return nil
}
+func executeShell(ccfg *api.ClusterConfig, role uint16, hcf *api.HostConfig, schedule api.ScheduleType) error {
+ shell := getShell(ccfg.RoleInfra[role], schedule)
+ if len(shell) == 0 {
+ return nil
+ }
+
+ htype := api.PreHookType
+ if strings.HasPrefix(string(schedule), "post") {
+ htype = api.PostHookType
+ }
+ oper := api.HookOpJoin
+ if strings.HasSuffix(string(schedule), "cleanup") {
+ oper = api.HookOpCleanup
+ }
+
+ hookConf := &api.HookRunConfig{
+ ClusterID: ccfg.Name,
+ ClusterApiEndpoint: ccfg.APIEndpoint.GetUrl(),
+ ClusterConfigDir: ccfg.ConfigDir,
+ HookType: htype,
+ Operator: oper,
+ Node: hcf,
+ HookDir: path.Join(ccfg.PackageSrc.GetPkgDstPath(), constants.DefaultFilePath),
+ Hooks: shell,
+ }
+
+ return ExecuteHooks(hookConf)
+}
+
func HookSchedule(ccfg *api.ClusterConfig, nodes []*api.HostConfig, role []uint16, schedule api.ScheduleType) error {
for _, n := range nodes {
for _, r := range role {
@@ -383,7 +427,7 @@ func HookSchedule(ccfg *api.ClusterConfig, nodes []*api.HostConfig, role []uint1
continue
}
- if err := ExecuteShell(ccfg.RoleInfra[r], ccfg.PackageSrc.GetPkgDstPath(), n, schedule); err != nil {
+ if err := executeShell(ccfg, r, n, schedule); err != nil {
if api.IsCleanupSchedule(schedule) {
logrus.Errorf("execute shell failed for %s at %s: %v", n.Address, string(schedule), err)
} else {
diff --git a/pkg/utils/runner/runner.go b/pkg/utils/runner/runner.go
index c7088df..83a81e9 100644
--- a/pkg/utils/runner/runner.go
+++ b/pkg/utils/runner/runner.go
@@ -30,7 +30,6 @@ import (
"github.com/kubesphere/kubekey/pkg/util/ssh"
"github.com/sirupsen/logrus"
"isula.org/eggo/pkg/api"
- "isula.org/eggo/pkg/constants"
)
const (
@@ -164,7 +163,7 @@ func (ssh *SSHRunner) Reconnect() error {
func clearUserTempDir(conn ssh.Connection, host *kkv1alpha1.HostCfg) {
tmpShell := "/tmp/" + RunnerShellPrefix + "*"
// scp to tmp file
- dir := getCopyDefaultDir(host.User)
+ dir := api.GetUserTempDir(host.User)
_, err := conn.Exec(fmt.Sprintf("sudo -E /bin/sh -c \"rm -rf %s; rm -rf %s\"", dir, tmpShell), host)
if err != nil {
logrus.Warnf("[%s] remove temp dir: %s failed: %v", host.Name, dir, err)
@@ -175,7 +174,7 @@ func clearUserTempDir(conn ssh.Connection, host *kkv1alpha1.HostCfg) {
func prepareUserTempDir(conn ssh.Connection, host *kkv1alpha1.HostCfg) error {
// scp to tmp file
- dir := getCopyDefaultDir(host.User)
+ dir := api.GetUserTempDir(host.User)
var sb strings.Builder
sb.WriteString("sudo -E /bin/sh -c \"")
sb.WriteString(fmt.Sprintf("mkdir -p %s", dir))
@@ -191,18 +190,11 @@ func prepareUserTempDir(conn ssh.Connection, host *kkv1alpha1.HostCfg) error {
return nil
}
-func getCopyDefaultDir(user string) string {
- if user == "root" {
- return constants.DefaultRootCopyTempDirHome + "/temp"
- }
- return fmt.Sprintf(constants.DefaultUserCopyTempHomeFormat, user) + "/temp"
-}
-
func (ssh *SSHRunner) copyFile(src, dst string) error {
if ssh.Conn == nil {
return fmt.Errorf("[%s] SSH runner is not connected", ssh.Host.Name)
}
- tempDir := getCopyDefaultDir(ssh.Host.User)
+ tempDir := api.GetUserTempDir(ssh.Host.User)
// scp to tmp file
tempCpyFile := filepath.Join(tempDir, filepath.Base(src))
err := ssh.Conn.Scp(src, tempCpyFile)
@@ -248,7 +240,7 @@ func (ssh *SSHRunner) copyDir(srcDir, dstDir string) error {
logrus.Errorf("[%s] create cert tmp tar failed: %v", ssh.Host.Name, err)
return err
}
- tmpCpyDir := getCopyDefaultDir(ssh.Host.User)
+ tmpCpyDir := api.GetUserTempDir(ssh.Host.User)
tmpPkiFile := filepath.Join(tmpCpyDir, "pkg.tar")
// scp to user home directory
err = ssh.Copy(tmpPkgFile, tmpPkiFile)
--
2.25.1
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/openeuler-risc-v/eggo.git
git@gitee.com:openeuler-risc-v/eggo.git
openeuler-risc-v
eggo
eggo
master

搜索帮助