mirror of
https://github.com/kubesphere/kubekey.git
synced 2025-12-25 17:12:50 +00:00
feature: support task include vars (#2717)
feature: support task include vars feature: support task include vars feature: support task include vars feature: support task include vars feature: support task include vars feature: support task include vars feature: support task include vars feature: support task include vars feature: support task include vars feature: support task include vars feature: support task include vars feature: support task include vars Signed-off-by: xuesongzuo@yunify.com <xuesongzuo@yunify.com>
This commit is contained in:
parent
aaae2f6634
commit
a8e533e608
|
|
@ -0,0 +1,18 @@
|
|||
# include_vars 模块
|
||||
|
||||
include_vars模块允许用户将变量设置到指定的主机中生效。
|
||||
|
||||
## 参数
|
||||
|
||||
| 参数 | 说明 | 类型 | 必填 | 默认值 |
|
||||
|------|------|------|------|-------|
|
||||
| include_vars | 引用的文件地址,类型必须是yaml/yml | 字符串 | 是 | - |
|
||||
|
||||
## 使用示例
|
||||
|
||||
1. 设置字符串参数
|
||||
```yaml
|
||||
- name: set other var file
|
||||
include_vars: "{{ .os.architecture }}/var.yaml"
|
||||
```
|
||||
|
||||
|
|
@ -138,3 +138,6 @@ const RuntimePlaybookVariableDir = "variable"
|
|||
|
||||
// KubernetesDir represents the remote host directory for each Kubernetes connection created during playbook execution.
|
||||
const KubernetesDir = "kubernetes"
|
||||
|
||||
// VarsDir is a directory name for vars
|
||||
const VarsDir = "vars"
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ func (ca copyArgs) handleAbsolutePath(ctx context.Context, conn connector.Connec
|
|||
func (ca copyArgs) handleRelativePath(ctx context.Context, options ExecOptions, conn connector.Connector) (string, string, error) {
|
||||
pj, err := project.New(ctx, options.Playbook, false)
|
||||
if err != nil {
|
||||
return StdoutFailed, "failed to get playbook", err
|
||||
return StdoutFailed, StderrGetPlaybook, err
|
||||
}
|
||||
|
||||
relPath := filepath.Join(options.Task.Annotations[kkcorev1alpha1.TaskAnnotationRelativePath], _const.ProjectRolesFilesDir, ca.src)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,96 @@
|
|||
package modules
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/cockroachdb/errors"
|
||||
kkcorev1alpha1 "github.com/kubesphere/kubekey/api/core/v1alpha1"
|
||||
"gopkg.in/yaml.v3"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
|
||||
_const "github.com/kubesphere/kubekey/v4/pkg/const"
|
||||
"github.com/kubesphere/kubekey/v4/pkg/project"
|
||||
"github.com/kubesphere/kubekey/v4/pkg/utils"
|
||||
"github.com/kubesphere/kubekey/v4/pkg/variable"
|
||||
)
|
||||
|
||||
/*
|
||||
Module: include_vars
|
||||
|
||||
Description:
|
||||
- Adds or updates host variables for one or more hosts.
|
||||
|
||||
Example Usage in Playbook Task:
|
||||
- name: Add custom variables to hosts
|
||||
include_vars: path/file.yaml
|
||||
|
||||
Return Values:
|
||||
- On success: returns empty stdout and stderr.
|
||||
- On failure: returns error message in stderr.
|
||||
*/
|
||||
|
||||
type includeVarsArgs struct {
|
||||
includeVars string
|
||||
}
|
||||
|
||||
// ModuleIncludeVars handle the "include_vars" module ,add other var files into playbook
|
||||
func ModuleIncludeVars(ctx context.Context, options ExecOptions) (string, string, error) {
|
||||
// get host variable
|
||||
vd, err := options.getAllVariables()
|
||||
if err != nil {
|
||||
return StdoutFailed, StderrGetHostVariable, err
|
||||
}
|
||||
// check args
|
||||
includeVarsByte, err := variable.Extension2String(vd, options.Args)
|
||||
if err != nil {
|
||||
return StdoutFailed, StderrParseArgument, err
|
||||
}
|
||||
if len(includeVarsByte) == 0 {
|
||||
return StdoutFailed, "input file path wrong", errors.New("input value can not be empty")
|
||||
}
|
||||
arg := includeVarsArgs{
|
||||
includeVars: string(includeVarsByte),
|
||||
}
|
||||
if !filepath.IsLocal(arg.includeVars) {
|
||||
return StdoutFailed, "can not read remote file", errors.New("can not read remote file")
|
||||
}
|
||||
if !utils.HasSuffixIn(arg.includeVars, []string{"yaml", "yml"}) {
|
||||
return StdoutFailed, "input file type wrong", errors.New("input file type wrong")
|
||||
}
|
||||
|
||||
var includeVarsFileContent []byte
|
||||
if filepath.IsAbs(arg.includeVars) {
|
||||
includeVarsFileContent, err = os.ReadFile(arg.includeVars)
|
||||
if err != nil {
|
||||
return StdoutFailed, "failed to read var file", errors.Wrap(err, "failed to read include variables file")
|
||||
}
|
||||
} else {
|
||||
pj, err := project.New(ctx, options.Playbook, false)
|
||||
if err != nil {
|
||||
return StdoutFailed, StderrGetPlaybook, err
|
||||
}
|
||||
fileReadPath := filepath.Join(options.Task.Annotations[kkcorev1alpha1.TaskAnnotationRelativePath], _const.VarsDir, arg.includeVars)
|
||||
includeVarsFileContent, err = pj.ReadFile(fileReadPath)
|
||||
if err != nil {
|
||||
return StdoutFailed, "failed to read var file", err
|
||||
}
|
||||
}
|
||||
|
||||
var node yaml.Node
|
||||
// Unmarshal the YAML document into a root node.
|
||||
if err := yaml.Unmarshal(includeVarsFileContent, &node); err != nil {
|
||||
return StdoutFailed, StderrParseArgument, errors.Wrap(err, "failed to failed to unmarshal YAML")
|
||||
}
|
||||
|
||||
if err := options.Variable.Merge(variable.MergeRuntimeVariable([]yaml.Node{node}, options.Host)); err != nil {
|
||||
return StdoutFailed, StderrParseArgument, errors.Wrap(err, "failed to merge runtime variables")
|
||||
}
|
||||
|
||||
return StdoutSuccess, "", nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
utilruntime.Must(RegisterModule("include_vars", ModuleIncludeVars))
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
package modules
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
func TestModuleIncludeVars(t *testing.T) {
|
||||
testcases := []struct {
|
||||
name string
|
||||
opt ExecOptions
|
||||
exceptStdout string
|
||||
}{
|
||||
{
|
||||
name: "include remote path",
|
||||
opt: ExecOptions{
|
||||
Args: runtime.RawExtension{
|
||||
Raw: []byte(`{
|
||||
"include_vars": "http://127.0.0.1:8080/include_vars",
|
||||
}`),
|
||||
},
|
||||
Variable: newTestVariable(nil, nil),
|
||||
},
|
||||
exceptStdout: StdoutFailed,
|
||||
}, {
|
||||
name: "include empty path",
|
||||
opt: ExecOptions{
|
||||
Args: runtime.RawExtension{
|
||||
Raw: []byte(`{
|
||||
"include_vars": "",
|
||||
}`),
|
||||
},
|
||||
Variable: newTestVariable(nil, nil),
|
||||
},
|
||||
exceptStdout: StdoutFailed,
|
||||
}, {
|
||||
name: "include path not exist",
|
||||
opt: ExecOptions{
|
||||
Args: runtime.RawExtension{
|
||||
Raw: []byte(`{
|
||||
"include_vars": "/path/not/exist/not_exist.yaml",
|
||||
}`),
|
||||
},
|
||||
Variable: newTestVariable(nil, nil),
|
||||
},
|
||||
exceptStdout: StdoutFailed,
|
||||
}, {
|
||||
name: "include path not yaml",
|
||||
opt: ExecOptions{
|
||||
Args: runtime.RawExtension{
|
||||
Raw: []byte(`{
|
||||
"include_vars": "/path/some/exist/exist.yyy",
|
||||
}`),
|
||||
},
|
||||
Variable: newTestVariable(nil, nil),
|
||||
},
|
||||
exceptStdout: StdoutFailed,
|
||||
},
|
||||
}
|
||||
|
||||
for _, testcase := range testcases {
|
||||
t.Run(testcase.name, func(t *testing.T) {
|
||||
stdout, _, _ := ModuleIncludeVars(context.Background(), testcase.opt)
|
||||
assert.Equal(t, testcase.exceptStdout, stdout)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -46,6 +46,8 @@ const (
|
|||
StderrParseArgument = "failed to parse argument"
|
||||
// StderrUnsupportArgs is returned when the provided arguments are not supported.
|
||||
StderrUnsupportArgs = "unsupport args"
|
||||
// StderrGetPlaybook is returned when get playbook error
|
||||
StderrGetPlaybook = "failed to get playbook"
|
||||
)
|
||||
|
||||
// ModuleExecFunc defines the function signature for executing a module.
|
||||
|
|
|
|||
Loading…
Reference in New Issue