diff --git a/builtin/core/playbooks/hook/post_install.yaml b/builtin/core/playbooks/hook/post_install.yaml index 2eed64bd..39de423f 100644 --- a/builtin/core/playbooks/hook/post_install.yaml +++ b/builtin/core/playbooks/hook/post_install.yaml @@ -20,8 +20,19 @@ mode: 0755 register: post_install_copy_result + - name: Post | Copy post-installation config scripts to remote hosts + copy: + src: >- + {{ .scripts_dir }}/{{ .item.script }} + dest: >- + /etc/kubekey/scripts/post_install_{{ .item.script }} + mode: 0755 + loop: "{{ .post_install | toJson }}" + when: "{{ getStringSlice .groups .item.group | default list | has .inventory_hostname }}" + register: post_install_config_copy_result + - name: Post | Execute post-installation scripts on remote hosts - when: .post_install_copy_result.error | empty + when: or (.post_install_copy_result.error | empty) (and .post_install_config_copy_result (.post_install_config_copy_result.error | empty)) command: | for file in /etc/kubekey/scripts/post_install_*.sh; do if [ -f "$file" ]; then @@ -29,4 +40,4 @@ chmod +x "$file" "$file" fi - done \ No newline at end of file + done diff --git a/builtin/core/playbooks/hook/pre_install.yaml b/builtin/core/playbooks/hook/pre_install.yaml index 25167316..02b4cf36 100644 --- a/builtin/core/playbooks/hook/pre_install.yaml +++ b/builtin/core/playbooks/hook/pre_install.yaml @@ -13,8 +13,19 @@ mode: 0755 register: pre_install_copy_result + - name: Pre | Copy pre-installation config scripts to remote hosts + copy: + src: >- + {{ .work_dir }}/scripts/{{ .item.script }} + dest: >- + /etc/kubekey/scripts/pre_install_{{ .item.script }} + mode: 0755 + loop: "{{ .pre_install | toJson }}" + when: "{{ getStringSlice .groups .item.group | default list | has .inventory_hostname }}" + register: pre_install_config_copy_result + - name: Pre | Execute pre-installation scripts on remote hosts - when: .pre_install_copy_result.error | empty + when: or (.pre_install_copy_result.error | empty) (and .pre_install_config_copy_result (.pre_install_config_copy_result.error | empty)) command: | for file in /etc/kubekey/scripts/pre_install_*.sh; do if [ -f "$file" ]; then diff --git a/builtin/core/roles/defaults/defaults/main/01-main.yaml b/builtin/core/roles/defaults/defaults/main/01-main.yaml index 7fe80fd3..1917f17f 100644 --- a/builtin/core/roles/defaults/defaults/main/01-main.yaml +++ b/builtin/core/roles/defaults/defaults/main/01-main.yaml @@ -2,7 +2,7 @@ work_dir: /root/kubekey binary_dir: >- {{ .work_dir }}/kubekey scripts_dir: >- - {{ .binary_dir }}/scripts + {{ .work_dir }}/scripts tmp_dir: /tmp/kubekey # Mapping of common machine architecture names to their standard forms diff --git a/pkg/converter/tmpl/functions.go b/pkg/converter/tmpl/functions.go index bcd6ebe7..ee61d6e6 100644 --- a/pkg/converter/tmpl/functions.go +++ b/pkg/converter/tmpl/functions.go @@ -30,6 +30,7 @@ func funcMap() template.FuncMap { f["subtractList"] = subtractList f["fileExist"] = fileExist f["unquote"] = unquote + f["getStringSlice"] = getStringSlice return f } @@ -131,3 +132,10 @@ func unquote(input any) string { } return output } + +func getStringSlice(d map[string][]string, key string) []string { + if val, ok := d[key]; ok { + return val + } + return nil +} diff --git a/pkg/converter/tmpl/template_test.go b/pkg/converter/tmpl/template_test.go index a7d0ff5c..70ca7712 100644 --- a/pkg/converter/tmpl/template_test.go +++ b/pkg/converter/tmpl/template_test.go @@ -252,6 +252,16 @@ func TestParseValue(t *testing.T) { }, excepted: []byte("bar"), }, + { + name: "get string slice from dictionary", + input: "{{ getStringSlice .foo \"foo\" }}", + variable: map[string]any{ + "foo": map[string][]string{ + "foo": {"bar1", "bar2"}, + }, + }, + excepted: []byte("[bar1 bar2]"), + }, { name: "multi level 2", input: "{{ index .foo \"foo\" }}", diff --git a/pkg/executor/task_executor.go b/pkg/executor/task_executor.go index ba853720..b8f3a8e7 100644 --- a/pkg/executor/task_executor.go +++ b/pkg/executor/task_executor.go @@ -166,21 +166,19 @@ func (e *taskExecutor) execTaskHost(i int, h string) func(ctx context.Context) { resErr = errors.Errorf("host: %s variable is not a map", h) return } - // check when condition - if skip, err := e.dealWhen(had); err != nil { - resErr = err - return - } else if skip { - stdout = modules.StdoutSkip - return - } // execute module in loop with loop item. // if loop is empty. execute once, and the item is null for _, item := range e.dealLoop(had) { - resErr = e.executeModule(ctx, e.task, item, h, &stdout, &stderr) - if resErr != nil { + resSkip, exeErr := e.executeModule(ctx, e.task, item, h, &stdout, &stderr) + if exeErr != nil { + resErr = exeErr break } + // loop execute once, skip task + if item == nil && resSkip { + stdout = modules.StdoutSkip + return + } } } } @@ -260,18 +258,18 @@ func (e *taskExecutor) execTaskHostLogs(ctx context.Context, h string, stdout, _ } // executeModule executes a single module task on a specific host. -func (e *taskExecutor) executeModule(ctx context.Context, task *kkcorev1alpha1.Task, item any, host string, stdout, stderr *string) (resErr error) { +func (e *taskExecutor) executeModule(ctx context.Context, task *kkcorev1alpha1.Task, item any, host string, stdout, stderr *string) (resSkip bool, resErr error) { // Set loop item variable if one was provided if item != nil { // Convert item to runtime variable node, err := converter.ConvertMap2Node(map[string]any{_const.VariableItem: item}) if err != nil { - return errors.Wrap(err, "failed to convert loop item") + return false, errors.Wrap(err, "failed to convert loop item") } // Merge item into host's runtime variables if err := e.variable.Merge(variable.MergeRuntimeVariable([]yaml.Node{node}, host)); err != nil { - return errors.Wrap(err, "failed to set loop item to variable") + return false, errors.Wrap(err, "failed to set loop item to variable") } // Clean up loop item variable after execution @@ -295,13 +293,20 @@ func (e *taskExecutor) executeModule(ctx context.Context, task *kkcorev1alpha1.T // Get all variables for this host, including any loop item ha, err := e.variable.Get(variable.GetAllVariable(host)) if err != nil { - return errors.Wrapf(err, "failed to get host %s variable", host) + return false, errors.Wrapf(err, "failed to get host %s variable", host) } // Convert host variables to map type had, ok := ha.(map[string]any) if !ok { - return errors.Wrapf(err, "host %s variable is not a map", host) + return false, errors.Wrapf(err, "host %s variable is not a map", host) + } + + // check when condition + if skip, err := e.dealWhen(had); err != nil { + return false, err + } else if skip { + return true, nil } // Execute the actual module with the prepared context @@ -313,7 +318,7 @@ func (e *taskExecutor) executeModule(ctx context.Context, task *kkcorev1alpha1.T Playbook: *e.playbook, LogOutput: e.logOutput, }) - return e.dealFailedWhen(had, resErr) + return false, e.dealFailedWhen(had, resErr) } // dealLoop parses the loop specification into a slice of items to iterate over.