@@ -27,6 +27,7 @@ import (
2727 "github.com/cockroachdb/errors"
2828 kkprojectv1 "github.com/kubesphere/kubekey/api/project/v1"
2929
30+ "github.com/kubesphere/kubekey/v4/pkg/converter/tmpl"
3031 "github.com/kubesphere/kubekey/v4/pkg/modules/internal"
3132 "github.com/kubesphere/kubekey/v4/pkg/variable"
3233)
@@ -39,8 +40,10 @@ Configuration:
3940Users can specify either a message or a variable path to debug.
4041
4142debug:
42- msg: "message" # optional: direct message to print
43- msg: "{{ .var }}" # optional: template syntax to print variable value
43+ msg: "message" # optional: direct message to print
44+ msg: "value is {{ .var }}" # optional: template syntax with filters
45+ var: "{{ .var }}" # optional: template syntax to get variable
46+ var: ".var" # optional: simple variable path
4447
4548Usage Examples in Playbook Tasks:
46491. Print direct message:
@@ -51,11 +54,27 @@ Usage Examples in Playbook Tasks:
5154 register: debug_result
5255 ```
5356
54- 2. Print variable value:
57+ 2. Print message with template:
58+ ```yaml
59+ - name: Debug with template
60+ debug:
61+ msg: "Version is {{ .config.version | default \"unknown\" }}"
62+ register: debug_result
63+ ```
64+
65+ 3. Print variable value:
5566 ```yaml
5667 - name: Debug variable
5768 debug:
58- msg: "{{ .config.version }}"
69+ var: "{{ .config.version }}"
70+ register: var_debug
71+ ```
72+
73+ 4. Print variable with simple path:
74+ ```yaml
75+ - name: Debug variable simple
76+ debug:
77+ var: ".config.version"
5978 register: var_debug
6079 ```
6180
@@ -72,40 +91,89 @@ func ModuleDebug(_ context.Context, opts internal.ExecOptions) (string, string,
7291 return internal .StdoutFailed , internal .StderrGetHostVariable , err
7392 }
7493 args := variable .Extension2Variables (opts .Args )
75- v := reflect .ValueOf (args ["msg" ])
76- switch v .Kind () {
77- case reflect .Invalid :
78- return internal .StdoutFailed , internal .StderrUnsupportArgs , errors .New ("\" msg\" is not found" )
94+
95+ // Handle "var" field - for getting variable values
96+ if v , ok := args ["var" ]; ok {
97+ return handleVarField (v , ha , opts .LogOutput )
98+ }
99+
100+ // Handle "msg" field - for printing messages with template support
101+ if v , ok := args ["msg" ]; ok {
102+ return handleMsgField (v , ha , opts .LogOutput )
103+ }
104+
105+ return internal .StdoutFailed , internal .StderrUnsupportArgs , errors .New ("either \" msg\" or \" var\" must be specified" )
106+ }
107+
108+ // handleVarField handles the "var" field for variable debugging
109+ // Supports both template syntax "{{ .var }}" and simple path ".var"
110+ func handleVarField (v any , ha map [string ]any , output io.Writer ) (string , string , error ) {
111+ rv := reflect .ValueOf (v )
112+ switch rv .Kind () {
79113 case reflect .String :
80- if ! kkprojectv1 .IsTmplSyntax (v .String ()) {
81- return formatOutput ([]byte (v .String ()), opts .LogOutput ), "" , nil
114+ val := rv .String ()
115+ // Check if it's template syntax
116+ if kkprojectv1 .IsTmplSyntax (val ) {
117+ val = kkprojectv1 .TrimTmplSyntax (val )
82118 }
83- val := kkprojectv1 . TrimTmplSyntax ( v . String ())
119+ // Ensure it starts with "."
84120 if ! strings .HasPrefix (val , "." ) {
85- return internal .StdoutFailed , internal .StderrUnsupportArgs , errors .New ("error tmpl value syntax " )
121+ return internal .StdoutFailed , internal .StderrUnsupportArgs , errors .New ("variable path must start with '.' " )
86122 }
87- data , err := variable .PrintVar (ha , strings .Split (val , "." )[1 :]... )
123+ // Remove leading "." and split path
124+ path := strings .TrimPrefix (val , "." )
125+ if path == "" {
126+ return internal .StdoutFailed , internal .StderrUnsupportArgs , errors .New ("variable path cannot be empty" )
127+ }
128+ data , err := variable .PrintVar (ha , strings .Split (path , "." )... )
88129 if err != nil {
89130 return internal .StdoutFailed , internal .StderrParseArgument , err
90131 }
91- return formatOutput (data , opts . LogOutput ), "" , nil
132+ return formatOutput (data , output ), "" , nil
92133 default :
93- // do not parse by ctx
94- data , err := json .Marshal (v .Interface ())
95- if err != nil {
96- return internal .StdoutFailed , "failed to marshal value to json" , err
134+ // For non-string types, pass directly to formatOutput for pretty printing
135+ return formatOutput (rv .Interface (), output ), "" , nil
136+ }
137+ }
138+
139+ // handleMsgField handles the "msg" field for message debugging
140+ // Supports template syntax with filters like "a is {{ .var | default 'b' }}"
141+ func handleMsgField (v any , ha map [string ]any , output io.Writer ) (string , string , error ) {
142+ rv := reflect .ValueOf (v )
143+ switch rv .Kind () {
144+ case reflect .String :
145+ msg := rv .String ()
146+ // If it contains template syntax, parse it
147+ if kkprojectv1 .IsTmplSyntax (msg ) {
148+ parsed , err := tmpl .Parse (ha , msg )
149+ if err != nil {
150+ return internal .StdoutFailed , internal .StderrParseArgument , err
151+ }
152+ return formatOutput (string (parsed ), output ), "" , nil
97153 }
98- return formatOutput (data , opts .LogOutput ), "" , nil
154+ // Direct message without template
155+ return formatOutput (msg , output ), "" , nil
156+ default :
157+ // For non-string types, pass directly to formatOutput for pretty printing
158+ return formatOutput (rv .Interface (), output ), "" , nil
99159 }
100160}
101161
102162// formatOutput formats data as pretty JSON and logs it with DEBUG prefix if output is provided
103163// Returns the formatted string
104164func formatOutput (data any , output io.Writer ) string {
105165 var msg string
106- prettyJSON , err := json .MarshalIndent (data , "" , " " )
107- if err == nil {
108- msg = string (prettyJSON )
166+ // Handle string data directly without JSON marshaling
167+ switch v := data .(type ) {
168+ case string :
169+ msg = v
170+ case []byte :
171+ msg = string (v )
172+ default :
173+ prettyJSON , err := json .MarshalIndent (v , "" , " " )
174+ if err == nil {
175+ msg = string (prettyJSON )
176+ }
109177 }
110178 if output != nil {
111179 _ , _ = fmt .Fprintln (output , "DEBUG: \n " + msg ) // Ignore error in test context
0 commit comments