Skip to content

Commit 2f8d547

Browse files
committed
Refactor execute() function to not do arg splitting
1 parent e97ce22 commit 2f8d547

File tree

1 file changed

+43
-66
lines changed

1 file changed

+43
-66
lines changed
Lines changed: 43 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"sigs.k8s.io/yaml"
2525

2626
operatorv1alpha1 "github.com/openshift/api/operator/v1alpha1"
27+
"github.com/openshift/installer/pkg/asset/agent"
2728
"github.com/openshift/installer/pkg/asset/agent/mirror"
2829
"github.com/openshift/installer/pkg/rhcos"
2930
"github.com/openshift/installer/pkg/rhcos/cache"
@@ -34,19 +35,19 @@ const (
3435
coreOsFileName = "/coreos/coreos-%s.iso"
3536
coreOsSha256FileName = "/coreos/coreos-%s.iso.sha256"
3637
coreOsStreamFileName = "/coreos/coreos-stream.json"
37-
//OcDefaultTries is the number of times to execute the oc command on failues
38+
// OcDefaultTries is the number of times to execute the oc command on failures.
3839
OcDefaultTries = 5
39-
// OcDefaultRetryDelay is the time between retries
40+
// OcDefaultRetryDelay is the time between retries.
4041
OcDefaultRetryDelay = time.Second * 5
4142
)
4243

43-
// Config is used to set up the retries for extracting the base ISO
44+
// Config is used to set up the retries for extracting the base ISO.
4445
type Config struct {
4546
MaxTries uint
4647
RetryDelay time.Duration
4748
}
4849

49-
// Release is the interface to use the oc command to the get image info
50+
// Release is the interface to use the oc command to the get image info.
5051
type Release interface {
5152
GetBaseIso(architecture string) (string, error)
5253
GetBaseIsoVersion(architecture string) (string, error)
@@ -60,7 +61,7 @@ type release struct {
6061
mirrorConfig []mirror.RegistriesConfig
6162
}
6263

63-
// NewRelease is used to set up the executor to run oc commands
64+
// NewRelease is used to set up the executor to run oc commands.
6465
func NewRelease(config Config, releaseImage string, pullSecret string, mirrorConfig []mirror.RegistriesConfig) Release {
6566
return &release{
6667
config: config,
@@ -70,13 +71,6 @@ func NewRelease(config Config, releaseImage string, pullSecret string, mirrorCon
7071
}
7172
}
7273

73-
const (
74-
templateGetImage = "oc adm release info --image-for=%s --filter-by-os=linux/%s --insecure=%t %s"
75-
templateGetImageWithIcsp = "oc adm release info --image-for=%s --filter-by-os=linux/%s --insecure=%t --icsp-file=%s %s"
76-
templateImageExtract = "oc image extract --path %s:%s --filter-by-os=linux/%s --confirm %s"
77-
templateImageExtractWithIcsp = "oc image extract --path %s:%s --filter-by-os=linux/%s --confirm --icsp-file=%s %s"
78-
)
79-
8074
// ExtractFile extracts the specified file from the given image name, and store it in the cache dir.
8175
func (r *release) ExtractFile(image string, filename string, architecture string) ([]string, error) {
8276
imagePullSpec, err := r.getImageFromRelease(image, architecture)
@@ -171,7 +165,6 @@ func (r *release) GetBaseIsoVersion(architecture string) (string, error) {
171165
func (r *release) getImageFromRelease(imageName string, architecture string) (string, error) {
172166
// This requires the 'oc' command so make sure its available
173167
_, err := exec.LookPath("oc")
174-
var cmd string
175168
if err != nil {
176169
if len(r.mirrorConfig) > 0 {
177170
logrus.Warning("Unable to validate mirror config because \"oc\" command is not available")
@@ -182,21 +175,32 @@ func (r *release) getImageFromRelease(imageName string, architecture string) (st
182175
}
183176

184177
archName := arch.GoArch(architecture)
185-
178+
imagefor := "--image-for=" + imageName
179+
filterbyos := "--filter-by-os=linux/" + archName
180+
insecure := "--insecure=true"
181+
182+
var cmd = []string{
183+
"oc",
184+
"adm",
185+
"release",
186+
"info",
187+
imagefor,
188+
filterbyos,
189+
insecure,
190+
}
186191
if len(r.mirrorConfig) > 0 {
187192
logrus.Debugf("Using mirror configuration")
188193
icspFile, err := getIcspFileFromRegistriesConfig(r.mirrorConfig)
189194
if err != nil {
190195
return "", err
191196
}
192197
defer removeIcspFile(icspFile)
193-
cmd = fmt.Sprintf(templateGetImageWithIcsp, imageName, archName, true, icspFile, r.releaseImage)
194-
} else {
195-
cmd = fmt.Sprintf(templateGetImage, imageName, archName, true, r.releaseImage)
198+
icspfile := "--icsp-file=" + icspFile
199+
cmd = append(cmd, icspfile)
196200
}
197-
201+
cmd = append(cmd, r.releaseImage)
198202
logrus.Debugf("Fetching image from OCP release (%s)", cmd)
199-
image, err := execute(r.pullSecret, cmd)
203+
image, err := agent.ExecuteOC(r.pullSecret, cmd)
200204
if err != nil {
201205
if strings.Contains(err.Error(), "unknown flag: --icsp-file") {
202206
logrus.Warning("Using older version of \"oc\" that does not support mirroring")
@@ -208,26 +212,36 @@ func (r *release) getImageFromRelease(imageName string, architecture string) (st
208212
}
209213

210214
func (r *release) extractFileFromImage(image, file, cacheDir string, architecture string) ([]string, error) {
211-
var cmd string
212215
archName := arch.GoArch(architecture)
216+
extractpath := "--path=" + file + ":" + cacheDir
217+
filterbyos := "--filter-by-os=linux/" + archName
218+
219+
var cmd = []string{
220+
"oc",
221+
"image",
222+
"extract",
223+
extractpath,
224+
filterbyos,
225+
"--confirm",
226+
}
227+
213228
if len(r.mirrorConfig) > 0 {
214229
icspFile, err := getIcspFileFromRegistriesConfig(r.mirrorConfig)
215230
if err != nil {
216231
return nil, err
217232
}
218233
defer removeIcspFile(icspFile)
219-
cmd = fmt.Sprintf(templateImageExtractWithIcsp, file, cacheDir, archName, icspFile, image)
220-
} else {
221-
cmd = fmt.Sprintf(templateImageExtract, file, cacheDir, archName, image)
234+
icspfile := "--icsp-file=" + icspFile
235+
cmd = append(cmd, icspfile)
222236
}
223237
path := filepath.Join(cacheDir, path.Base(file))
224238
// Remove file if it exists
225239
if err := removeCacheFile(path); err != nil {
226240
return nil, err
227241
}
228-
242+
cmd = append(cmd, image)
229243
logrus.Debugf("extracting %s to %s, %s", file, cacheDir, cmd)
230-
_, err := retry.Do(r.config.MaxTries, r.config.RetryDelay, execute, r.pullSecret, cmd)
244+
_, err := retry.Do(r.config.MaxTries, r.config.RetryDelay, agent.ExecuteOC, r.pullSecret, cmd)
231245
if err != nil {
232246
return nil, err
233247
}
@@ -244,7 +258,7 @@ func (r *release) extractFileFromImage(image, file, cacheDir string, architectur
244258
return matches, nil
245259
}
246260

247-
// Get hash from rhcos.json
261+
// Get hash from rhcos.json.
248262
func getHashFromInstaller(architecture string) (bool, string) {
249263
// Get hash from metadata in the installer
250264
ctx, cancel := context.WithTimeout(context.TODO(), 30*time.Second)
@@ -277,7 +291,7 @@ func matchingHash(imageSha []byte, sha string) bool {
277291
return false
278292
}
279293

280-
// Check if there is a different base ISO in the release payload
294+
// Check if there is a different base ISO in the release payload.
281295
func (r *release) verifyCacheFile(image, file, architecture string) (bool, error) {
282296
// Get hash of cached file
283297
f, err := os.Open(file)
@@ -343,44 +357,7 @@ func removeCacheFile(path string) error {
343357
return nil
344358
}
345359

346-
func execute(pullSecret, command string) (string, error) {
347-
ps, err := os.CreateTemp("", "registry-config")
348-
if err != nil {
349-
return "", err
350-
}
351-
defer func() {
352-
ps.Close()
353-
os.Remove(ps.Name())
354-
}()
355-
_, err = ps.Write([]byte(pullSecret))
356-
if err != nil {
357-
return "", err
358-
}
359-
// flush the buffer to ensure the file can be read
360-
ps.Close()
361-
executeCommand := command[:] + " --registry-config=" + ps.Name()
362-
args := strings.Split(executeCommand, " ")
363-
364-
var stdoutBytes, stderrBytes bytes.Buffer
365-
cmd := exec.Command(args[0], args[1:]...) //nolint:gosec
366-
cmd.Stdout = &stdoutBytes
367-
cmd.Stderr = &stderrBytes
368-
369-
err = cmd.Run()
370-
if err == nil {
371-
return strings.TrimSpace(stdoutBytes.String()), nil
372-
}
373-
374-
var exitErr *exec.ExitError
375-
if errors.As(err, &exitErr) {
376-
err = fmt.Errorf("command '%s' exited with non-zero exit code %d: %s\n%s", executeCommand, exitErr.ExitCode(), stdoutBytes.String(), stderrBytes.String())
377-
} else {
378-
err = fmt.Errorf("command '%s' failed: %w", executeCommand, err)
379-
}
380-
return "", err
381-
}
382-
383-
// Create a temporary file containing the ImageContentPolicySources
360+
// Create a temporary file containing the ImageContentPolicySources.
384361
func getIcspFileFromRegistriesConfig(mirrorConfig []mirror.RegistriesConfig) (string, error) {
385362
contents, err := getIcspContents(mirrorConfig)
386363
if err != nil {
@@ -406,7 +383,7 @@ func getIcspFileFromRegistriesConfig(mirrorConfig []mirror.RegistriesConfig) (st
406383
return icspFile.Name(), nil
407384
}
408385

409-
// Convert the data in registries.conf into ICSP format
386+
// Convert the data in registries.conf into ICSP format.
410387
func getIcspContents(mirrorConfig []mirror.RegistriesConfig) ([]byte, error) {
411388
icsp := operatorv1alpha1.ImageContentSourcePolicy{
412389
TypeMeta: metav1.TypeMeta{

0 commit comments

Comments
 (0)