Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MGMT-10209: Pass in icsp file to be used for 'oc adm release extract' #4115

Merged
merged 11 commits into from
Jul 15, 2022
77 changes: 76 additions & 1 deletion internal/ignition/ignition.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ import (
"github.com/coreos/vcontext/report"
"github.com/go-openapi/swag"
bmh_v1alpha1 "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
operatorv1alpha1 "github.com/openshift/api/operator/v1alpha1"
clusterPkg "github.com/openshift/assisted-service/internal/cluster"
"github.com/openshift/assisted-service/internal/common"
"github.com/openshift/assisted-service/internal/constants"
"github.com/openshift/assisted-service/internal/host/hostutil"
"github.com/openshift/assisted-service/internal/installcfg"
"github.com/openshift/assisted-service/internal/installercache"
"github.com/openshift/assisted-service/internal/manifests"
"github.com/openshift/assisted-service/internal/network"
Expand Down Expand Up @@ -288,15 +290,24 @@ func (g *installerGenerator) UploadToS3(ctx context.Context) error {

// Generate generates ignition files and applies modifications.
func (g *installerGenerator) Generate(ctx context.Context, installConfig []byte, platformType models.PlatformType) error {
var icspFile string
log := logutil.FromContext(ctx, g.log)

// In case we don't want to override image for extracting installer use release one
if g.installerReleaseImageOverride == "" {
g.installerReleaseImageOverride = g.releaseImage
}

// If ImageContentSources are defined, store in a file for the 'oc' command
defer removeIcspFile(icspFile)
zaneb marked this conversation as resolved.
Show resolved Hide resolved

icspFile, err := getIcspFileFromInstallConfig(installConfig)
if err != nil {
return errors.Wrap(err, "failed to create file with ImageContentSources")
}

installerPath, err := installercache.Get(g.installerReleaseImageOverride, g.releaseImageMirror, g.installerDir,
g.cluster.PullSecret, platformType, log)
g.cluster.PullSecret, platformType, icspFile, log)
if err != nil {
return errors.Wrap(err, "failed to get installer path")
}
Expand Down Expand Up @@ -1513,3 +1524,67 @@ func proxySettingsForIgnition(httpProxy, httpsProxy, noProxy string) (string, er
}
return buf.String(), nil
}

func getIcspFileFromInstallConfig(cfg []byte) (string, error) {
contents, err := getIcsp(cfg)
if err != nil {
return "", err
}
if contents == nil {
return "", nil
}

icspFile, err := ioutil.TempFile("", "icsp-file")
if err != nil {
return "", err
}
if _, err := icspFile.Write(contents); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add logging of the ICSP content.
It should allow us to debug issues in case something goes wrong

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, added.

os.Remove(icspFile.Name())
zaneb marked this conversation as resolved.
Show resolved Hide resolved
return "", err
}
icspFile.Close()
zaneb marked this conversation as resolved.
Show resolved Hide resolved

return icspFile.Name(), nil
}

func getIcsp(cfg []byte) ([]byte, error) {

var installCfg installcfg.InstallerConfigBaremetal
if err := yaml.Unmarshal(cfg, &installCfg); err != nil {
return nil, err
}

if len(installCfg.ImageContentSources) == 0 {
// No ImageContentSources were defined
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider logging here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added logging.

return nil, nil
}

icsp := operatorv1alpha1.ImageContentSourcePolicy{
TypeMeta: metav1.TypeMeta{
APIVersion: operatorv1alpha1.SchemeGroupVersion.String(),
Kind: "ImageContentSourcePolicy",
},
ObjectMeta: metav1.ObjectMeta{
Name: "image-policy",
// not namespaced
},
}

icsp.Spec.RepositoryDigestMirrors = make([]operatorv1alpha1.RepositoryDigestMirrors, len(installCfg.ImageContentSources))
for i, imageSource := range installCfg.ImageContentSources {
icsp.Spec.RepositoryDigestMirrors[i] = operatorv1alpha1.RepositoryDigestMirrors{Source: imageSource.Source, Mirrors: imageSource.Mirrors}

}

contents, err := yaml.Marshal(icsp)
if err != nil {
return nil, err
}
return contents, nil
}

func removeIcspFile(filename string) {
if filename != "" {
os.Remove(filename)
}
}
4 changes: 2 additions & 2 deletions internal/installercache/installercache.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func (i *installers) Get(releaseID string) *release {
// Get returns the path to an openshift-baremetal-install binary extracted from
// the referenced release image. Tries the mirror release image first if it's set. It is safe for concurrent use. A cache of
// binaries is maintained to reduce re-downloading of the same release.
func Get(releaseID, releaseIDMirror, cacheDir, pullSecret string, platformType models.PlatformType, log logrus.FieldLogger) (string, error) {
func Get(releaseID, releaseIDMirror, cacheDir, pullSecret string, platformType models.PlatformType, icspFile string, log logrus.FieldLogger) (string, error) {
r := cache.Get(releaseID)
r.Lock()
defer r.Unlock()
Expand All @@ -49,7 +49,7 @@ func Get(releaseID, releaseIDMirror, cacheDir, pullSecret string, platformType m
//cache miss
if r.path == "" {
path, err = oc.NewRelease(&executer.CommonExecuter{}, oc.Config{
MaxTries: oc.DefaultTries, RetryDelay: oc.DefaltRetryDelay}).Extract(log, releaseID, releaseIDMirror, cacheDir, pullSecret, platformType)
MaxTries: oc.DefaultTries, RetryDelay: oc.DefaltRetryDelay}).Extract(log, releaseID, releaseIDMirror, cacheDir, pullSecret, platformType, icspFile)
if err != nil {
return "", err
}
Expand Down
8 changes: 4 additions & 4 deletions internal/oc/mock_release.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 17 additions & 10 deletions internal/oc/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type Release interface {
GetOpenshiftVersion(log logrus.FieldLogger, releaseImage string, releaseImageMirror string, pullSecret string) (string, error)
GetMajorMinorVersion(log logrus.FieldLogger, releaseImage string, releaseImageMirror string, pullSecret string) (string, error)
GetReleaseArchitecture(log logrus.FieldLogger, releaseImage string, releaseImageMirror string, pullSecret string) (string, error)
Extract(log logrus.FieldLogger, releaseImage string, releaseImageMirror string, cacheDir string, pullSecret string, platformType models.PlatformType) (string, error)
Extract(log logrus.FieldLogger, releaseImage string, releaseImageMirror string, cacheDir string, pullSecret string, platformType models.PlatformType, icspFile string) (string, error)
}

type imageValue struct {
Expand All @@ -61,10 +61,11 @@ func NewRelease(executer executer.Executer, config Config) Release {
}

const (
templateGetImage = "oc adm release info --image-for=%s --insecure=%t %s"
templateGetVersion = "oc adm release info -o template --template '{{.metadata.version}}' --insecure=%t %s"
templateExtract = "oc adm release extract --command=%s --to=%s --insecure=%t %s"
templateImageInfo = "oc image info --output json %s"
templateGetImage = "oc adm release info --image-for=%s --insecure=%t %s"
templateGetVersion = "oc adm release info -o template --template '{{.metadata.version}}' --insecure=%t %s"
templateExtract = "oc adm release extract --command=%s --to=%s --insecure=%t %s"
templateExtractWithIcsp = "oc adm release extract --command=%s --to=%s --insecure=%t --icsp-file=%s %s"
templateImageInfo = "oc image info --output json %s"
)

// GetMCOImage gets mcoImage url from the releaseImageMirror if provided.
Expand Down Expand Up @@ -228,21 +229,21 @@ func (r *release) getOpenshiftVersionFromRelease(log logrus.FieldLogger, release

// Extract openshift-baremetal-install binary from releaseImageMirror if provided.
// Else extract from the source releaseImage
func (r *release) Extract(log logrus.FieldLogger, releaseImage string, releaseImageMirror string, cacheDir string, pullSecret string, platformType models.PlatformType) (string, error) {
func (r *release) Extract(log logrus.FieldLogger, releaseImage string, releaseImageMirror string, cacheDir string, pullSecret string, platformType models.PlatformType, icspFile string) (string, error) {
var path string
var err error
if releaseImage == "" && releaseImageMirror == "" {
return "", errors.New("no releaseImage or releaseImageMirror provided")
}
if releaseImageMirror != "" {
//TODO: Get mirror registry certificate from install-config
path, err = r.extractFromRelease(log, releaseImageMirror, cacheDir, pullSecret, true, platformType)
path, err = r.extractFromRelease(log, releaseImageMirror, cacheDir, pullSecret, true, platformType, icspFile)
if err != nil {
log.WithError(err).Errorf("failed to extract openshift-baremetal-install from mirror release image %s", releaseImageMirror)
return "", err
}
} else {
path, err = r.extractFromRelease(log, releaseImage, cacheDir, pullSecret, false, platformType)
path, err = r.extractFromRelease(log, releaseImage, cacheDir, pullSecret, false, platformType, icspFile)
if err != nil {
log.WithError(err).Errorf("failed to extract openshift-baremetal-install from release image %s", releaseImage)
return "", err
Expand All @@ -253,7 +254,7 @@ func (r *release) Extract(log logrus.FieldLogger, releaseImage string, releaseIm

// extractFromRelease returns the path to an openshift-baremetal-install binary extracted from
// the referenced release image.
func (r *release) extractFromRelease(log logrus.FieldLogger, releaseImage, cacheDir, pullSecret string, insecure bool, platformType models.PlatformType) (string, error) {
func (r *release) extractFromRelease(log logrus.FieldLogger, releaseImage, cacheDir, pullSecret string, insecure bool, platformType models.PlatformType, icspFile string) (string, error) {
// Using platform type as an indication for which openshift install binary to use
// (e.g. as non-x86_64 clusters should use the openshift-install binary).
var binary string
Expand All @@ -270,7 +271,13 @@ func (r *release) extractFromRelease(log logrus.FieldLogger, releaseImage, cache
return "", err
}

cmd := fmt.Sprintf(templateExtract, binary, workdir, insecure, releaseImage)
var cmd string
if icspFile == "" {
cmd = fmt.Sprintf(templateExtract, binary, workdir, insecure, releaseImage)
} else {
cmd = fmt.Sprintf(templateExtractWithIcsp, binary, workdir, insecure, icspFile, releaseImage)
}

_, err = retry.Do(r.config.MaxTries, r.config.RetryDelay, execute, log, r.executer, pullSecret, cmd)
if err != nil {
return "", err
Expand Down
12 changes: 6 additions & 6 deletions internal/oc/release_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ var _ = Describe("oc", func() {
args := splitStringToInterfacesArray(command)
mockExecuter.EXPECT().Execute(args[0], args[1:]...).Return("", "", 0).Times(1)

path, err := oc.Extract(log, releaseImage, "", cacheDir, pullSecret, models.PlatformTypeBaremetal)
path, err := oc.Extract(log, releaseImage, "", cacheDir, pullSecret, models.PlatformTypeBaremetal, "")
filePath := filepath.Join(cacheDir+"/"+releaseImage, baremetalInstallBinary)
Expect(path).To(Equal(filePath))
Expect(err).ShouldNot(HaveOccurred())
Expand All @@ -296,14 +296,14 @@ var _ = Describe("oc", func() {
args := splitStringToInterfacesArray(command)
mockExecuter.EXPECT().Execute(args[0], args[1:]...).Return("", "", 0).Times(1)

path, err := oc.Extract(log, releaseImage, releaseImageMirror, cacheDir, pullSecret, models.PlatformTypeBaremetal)
path, err := oc.Extract(log, releaseImage, releaseImageMirror, cacheDir, pullSecret, models.PlatformTypeBaremetal, "")
filePath := filepath.Join(cacheDir+"/"+releaseImageMirror, baremetalInstallBinary)
Expect(path).To(Equal(filePath))
Expect(err).ShouldNot(HaveOccurred())
})

It("extract baremetal-install with no release image or mirror", func() {
path, err := oc.Extract(log, "", "", cacheDir, pullSecret, models.PlatformTypeBaremetal)
path, err := oc.Extract(log, "", "", cacheDir, pullSecret, models.PlatformTypeBaremetal, "")
Expect(path).Should(BeEmpty())
Expect(err).Should(HaveOccurred())
})
Expand All @@ -314,7 +314,7 @@ var _ = Describe("oc", func() {
mockExecuter.EXPECT().Execute(args[0], args[1:]...).Return("", "Failed to extract the installer", 1).Times(1)
mockExecuter.EXPECT().Execute(args[0], args[1:]...).Return("", "", 0).Times(1)

path, err := oc.Extract(log, releaseImage, "", cacheDir, pullSecret, models.PlatformTypeBaremetal)
path, err := oc.Extract(log, releaseImage, "", cacheDir, pullSecret, models.PlatformTypeBaremetal, "")
filePath := filepath.Join(cacheDir+"/"+releaseImage, baremetalInstallBinary)
Expect(path).To(Equal(filePath))
Expect(err).ShouldNot(HaveOccurred())
Expand All @@ -326,7 +326,7 @@ var _ = Describe("oc", func() {
args := splitStringToInterfacesArray(command)
mockExecuter.EXPECT().Execute(args[0], args[1:]...).Return("", "Failed to extract the installer", 1).Times(5)

path, err := oc.Extract(log, releaseImage, "", cacheDir, pullSecret, models.PlatformTypeBaremetal)
path, err := oc.Extract(log, releaseImage, "", cacheDir, pullSecret, models.PlatformTypeBaremetal, "")
Expect(path).To(Equal(""))
Expect(err).Should(HaveOccurred())
})
Expand All @@ -337,7 +337,7 @@ var _ = Describe("oc", func() {
args := splitStringToInterfacesArray(command)
mockExecuter.EXPECT().Execute(args[0], args[1:]...).Return("", "", 0).Times(1)

path, err := oc.Extract(log, releaseImage, "", cacheDir, pullSecret, models.PlatformTypeNone)
path, err := oc.Extract(log, releaseImage, "", cacheDir, pullSecret, models.PlatformTypeNone, "")
filePath := filepath.Join(cacheDir+"/"+releaseImage, installBinary)
Expect(path).To(Equal(filePath))
Expect(err).ShouldNot(HaveOccurred())
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions vendor/github.com/openshift/api/operator/v1alpha1/doc.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.