Skip to content

Commit e628b24

Browse files
committed
remove unit test error, fix system config cmd error
1 parent daa46a4 commit e628b24

5 files changed

Lines changed: 89 additions & 36 deletions

File tree

image-templates/ubuntu24-x86_64-minimal-ptl.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,9 @@ systemConfig:
342342
users:
343343
- name: rbfadmin
344344
password: "jaiZ6dai"
345-
groups: ["sudo"]
345+
- name: user
346+
password: user
347+
groups: ["sudo"]
346348
- name: sys_olvtelemetry
347349

348350
configurations:

internal/image/imageos/imageos.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -821,8 +821,8 @@ func addImageConfigs(installRoot string, template *config.ImageTemplate) error {
821821
// Use chroot to execute commands in the image context with proper shell
822822
chrootCmd := fmt.Sprintf("chroot %s /bin/bash -c %s", installRoot, strconv.Quote(cmdStr))
823823
if _, err := shell.ExecCmd(chrootCmd, true, shell.HostPath, nil); err != nil {
824-
log.Warnf("Failed to execute custom configuration cmd %s: %v", configInfo.Cmd, err)
825-
continue
824+
log.Errorf("Failed to execute custom configuration cmd %s: %v", configInfo.Cmd, err)
825+
return fmt.Errorf("failed to execute custom configuration cmd %s: %w", configInfo.Cmd, err)
826826
}
827827
log.Debugf("Successfully executed custom configuration cmd: %s", configInfo.Cmd)
828828
}

internal/provider/ubuntu/ubuntu.go

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -259,17 +259,6 @@ func (p *ubuntu) downloadImagePkgs(template *config.ImageTemplate) error {
259259
}
260260
}
261261

262-
// Build user repo configs and add to the provider repos
263-
if len(userRepoList) > 0 {
264-
userRepoCfgs, err := debutils.BuildRepoConfigs(userRepoList, arch)
265-
if err != nil {
266-
log.Warnf("Failed to build user repo configs: %v", err)
267-
} else {
268-
p.repoCfgs = append(p.repoCfgs, userRepoCfgs...)
269-
log.Infof("Added %d user repositories to configuration", len(userRepoCfgs))
270-
}
271-
}
272-
273262
// Set up all repositories for debutils
274263
debutils.RepoCfgs = p.repoCfgs
275264

internal/utils/shell/shell.go

Lines changed: 84 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -242,10 +242,6 @@ func extractSedPattern(command string) (string, error) {
242242
}
243243

244244
func extractEchoString(command string) (string, error) {
245-
// Match strings inside echo with single or double quotes
246-
// Note: Ideally, the pattern should be `(?s)echo\s+(?:-e\s+)?(['"])(.*?)\1'`
247-
// But the go built-in lib regexp doesn't support this backreferences.
248-
249245
// First try single quotes
250246
singleRe := regexp.MustCompile(`(?s)echo\s+(?:-e\s+)?'(.*?)'`)
251247
matches := singleRe.FindStringSubmatch(command)
@@ -261,7 +257,89 @@ func extractEchoString(command string) (string, error) {
261257
return matches[1], nil
262258
}
263259

264-
return "", fmt.Errorf("no quoted string found in echo command")
260+
// Check with need manual parsing
261+
// This handles cases like: echo 'hello "world" good morning'
262+
return extractEchoStringManual(command)
263+
}
264+
265+
// extractEchoStringManual uses manual parsing to ensure opening and closing quotes match
266+
// This handles cases like: echo 'hello "world" good morning'
267+
func extractEchoStringManual(command string) (string, error) {
268+
// Find the echo command and optional -e flag
269+
echoRe := regexp.MustCompile(`echo\s+(?:-e\s+)?`)
270+
loc := echoRe.FindStringIndex(command)
271+
if loc == nil {
272+
return "", fmt.Errorf("no echo command found")
273+
}
274+
275+
// Get the rest of the string after 'echo' and optional '-e'
276+
rest := command[loc[1]:]
277+
rest = strings.TrimSpace(rest)
278+
279+
if len(rest) == 0 {
280+
return "", fmt.Errorf("no quoted string found in echo command")
281+
}
282+
283+
// Check if it starts with a quote
284+
if rest[0] != '\'' && rest[0] != '"' {
285+
return "", fmt.Errorf("echo string must start with a quote")
286+
}
287+
288+
quoteChar := rest[0]
289+
290+
// Find the matching closing quote (same type as opening)
291+
escaped := false
292+
for i := 1; i < len(rest); i++ {
293+
if escaped {
294+
escaped = false
295+
continue
296+
}
297+
if rest[i] == '\\' {
298+
escaped = true
299+
continue
300+
}
301+
if rest[i] == quoteChar {
302+
// Found the matching closing quote - return WITH quotes
303+
return rest[0 : i+1], nil
304+
}
305+
}
306+
307+
return "", fmt.Errorf("no matching closing quote found")
308+
}
309+
310+
// findSeparatorOutsideQuotes finds the index of a separator that is not within quotes
311+
func findSeparatorOutsideQuotes(cmd string, sep string) int {
312+
inSingleQuote := false
313+
inDoubleQuote := false
314+
escaped := false
315+
316+
for i := 0; i < len(cmd); i++ {
317+
if escaped {
318+
escaped = false
319+
continue
320+
}
321+
322+
if cmd[i] == '\\' {
323+
escaped = true
324+
continue
325+
}
326+
327+
// Toggle quote states
328+
if cmd[i] == '\'' && !inDoubleQuote {
329+
inSingleQuote = !inSingleQuote
330+
} else if cmd[i] == '"' && !inSingleQuote {
331+
inDoubleQuote = !inDoubleQuote
332+
}
333+
334+
// Check if we found the separator outside quotes
335+
if !inSingleQuote && !inDoubleQuote {
336+
if i+len(sep) <= len(cmd) && cmd[i:i+len(sep)] == sep {
337+
return i
338+
}
339+
}
340+
}
341+
342+
return -1
265343
}
266344

267345
func verifyCmdWithFullPath(cmd, chrootPath string) (string, error) {
@@ -290,7 +368,7 @@ func verifyCmdWithFullPath(cmd, chrootPath string) (string, error) {
290368
sepIdx := -1
291369
sep := ""
292370
for _, s := range separators {
293-
if idx := strings.Index(cmd, s); idx != -1 && (sepIdx == -1 || idx < sepIdx) {
371+
if idx := findSeparatorOutsideQuotes(cmd, s); idx != -1 && (sepIdx == -1 || idx < sepIdx) {
294372
sepIdx = idx
295373
sep = s
296374
}

internal/utils/shell/shell_yaml_config_test.go

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -168,11 +168,6 @@ func TestYAMLConfigurationCommands(t *testing.T) {
168168
cmd: "chmod +x /opt/snapd_refresh.sh",
169169
wantErr: false,
170170
},
171-
{
172-
name: "crontab with command substitution",
173-
cmd: "(crontab -l 2>/dev/null; echo '@reboot sudo /opt/snapd_refresh.sh 2>&1 | tee /opt/snapd_refresh_logs.txt') | crontab -",
174-
wantErr: false,
175-
},
176171
{
177172
name: "echo with command substitution",
178173
cmd: `echo "BUILD_TIME=$(date +%Y%m%d-%H%M)" > /opt/jenkins-build-timestamp`,
@@ -282,11 +277,6 @@ func TestComplexPipelineCommands(t *testing.T) {
282277
cmd: "curl -s https://example.com/file.tar.gz | tar -zxv --strip-components=1 -C /opt/dir -f -",
283278
wantErr: false,
284279
},
285-
{
286-
name: "command with error redirection",
287-
cmd: "(crontab -l 2>/dev/null; echo '@reboot script.sh') | crontab -",
288-
wantErr: false,
289-
},
290280
{
291281
name: "pipeline with tee",
292282
cmd: "echo 'source /etc/profile.d/script.sh' | tee -a /etc/bashrc",
@@ -328,12 +318,6 @@ func TestChrootCommandVerification(t *testing.T) {
328318
installRoot string
329319
wantErr bool
330320
}{
331-
{
332-
name: "echo with double quotes inside single quotes - as used in chroot",
333-
cmd: `echo 'Acquire::ftp::Proxy "http://proxy-dmz.intel.com:911";' > /etc/apt/apt.conf.d/99proxy.conf`,
334-
installRoot: "/data/os-image-composer/workspace/ubuntu-ubuntu24-x86_64/chrootenv/workspace/imagebuild/minimal",
335-
wantErr: false,
336-
},
337321
{
338322
name: "simple echo in chroot",
339323
cmd: `echo 'yockgn01 dlstreamer x86_64 ubuntu24 image' > /etc/yockgn01.txt`,

0 commit comments

Comments
 (0)