diff --git a/cmd/static-server/main.go b/cmd/static-server/main.go index 1f950284..a241797d 100644 --- a/cmd/static-server/main.go +++ b/cmd/static-server/main.go @@ -40,6 +40,11 @@ var ( ) func loadStaticNMState(env *env.EnvInputs, nmstateDir string, imageServer imagehandler.ImageHandler) error { + registries, err := env.RegistriesConf() + if err != nil { + return err + } + files, err := ioutil.ReadDir(nmstateDir) if err != nil { return errors.WithMessagef(err, "problem reading %s", nmstateDir) @@ -53,7 +58,7 @@ func loadStaticNMState(env *env.EnvInputs, nmstateDir string, imageServer imageh if err != nil { return errors.WithMessagef(err, "problem reading %s", path.Join(nmstateDir, f.Name())) } - igBuilder := ignition.New(b, + igBuilder := ignition.New(b, registries, env.IronicBaseURL, env.IronicAgentImage, env.IronicAgentPullSecret, diff --git a/pkg/env/env.go b/pkg/env/env.go index b27d5b38..ad4e74e5 100644 --- a/pkg/env/env.go +++ b/pkg/env/env.go @@ -1,6 +1,11 @@ package env -import "github.com/kelseyhightower/envconfig" +import ( + "os" + + "github.com/kelseyhightower/envconfig" + "github.com/pkg/errors" +) type EnvInputs struct { DeployISO string `envconfig:"DEPLOY_ISO" required:"true"` @@ -9,6 +14,7 @@ type EnvInputs struct { IronicAgentImage string `envconfig:"IRONIC_AGENT_IMAGE"` IronicAgentPullSecret string `envconfig:"IRONIC_AGENT_PULL_SECRET"` IronicRAMDiskSSHKey string `envconfig:"IRONIC_RAMDISK_SSH_KEY"` + RegistriesConfPath string `envconfig:"REGISTRIES_CONF_PATH"` } func New() (*EnvInputs, error) { @@ -16,3 +22,16 @@ func New() (*EnvInputs, error) { err := envconfig.Process("", env) return env, err } + +func (env *EnvInputs) RegistriesConf() (data []byte, err error) { + if env.RegistriesConfPath == "" { + return + } + + data, err = os.ReadFile(env.RegistriesConfPath) + if err != nil { + err = errors.Wrapf(err, "failed to read registries.conf file %s", + env.RegistriesConfPath) + } + return +} diff --git a/pkg/env/env_test.go b/pkg/env/env_test.go new file mode 100644 index 00000000..f45a405c --- /dev/null +++ b/pkg/env/env_test.go @@ -0,0 +1,29 @@ +package env + +import ( + "testing" +) + +func TestRegistriesConf(t *testing.T) { + inputs := EnvInputs{ + RegistriesConfPath: "../../test/registries.conf", + } + + registries := `[[registry]] + prefix = "" + location = "quay.io/openshift-release-dev/ocp-v4.0-art-dev" + mirror-by-digest-only = true + + [[registry.mirror]] + location = "virthost.ostest.test.metalkube.org:5000/localimages/local-release-image" +` + + data, err := inputs.RegistriesConf() + if err != nil { + t.Fatalf("Unexpected error %v", err) + } + + if string(data) != registries { + t.Fatalf("Registries data:\n%s\ndoes not match expected:\n%s", string(data), registries) + } +} diff --git a/pkg/ignition/builder.go b/pkg/ignition/builder.go index 164f5173..82c87ff3 100644 --- a/pkg/ignition/builder.go +++ b/pkg/ignition/builder.go @@ -20,13 +20,14 @@ const ( type ignitionBuilder struct { nmStateData []byte + registriesConf []byte ironicBaseURL string ironicAgentImage string ironicAgentPullSecret string ironicRAMDiskSSHKey string } -func New(nmStateData []byte, ironicBaseURL, ironicAgentImage, ironicAgentPullSecret, ironicRAMDiskSSHKey string) *ignitionBuilder { +func New(nmStateData, registriesConf []byte, ironicBaseURL, ironicAgentImage, ironicAgentPullSecret, ironicRAMDiskSSHKey string) *ignitionBuilder { if ironicAgentImage == "" { // https://github.com/openshift/ironic-image/blob/master/scripts/configure-coreos-ipa#L13 ironicAgentImage = "quay.io/dtantsur/ironic-agent" // TODO check @@ -34,6 +35,7 @@ func New(nmStateData []byte, ironicBaseURL, ironicAgentImage, ironicAgentPullSec return &ignitionBuilder{ nmStateData: nmStateData, + registriesConf: registriesConf, ironicBaseURL: ironicBaseURL, ironicAgentImage: ironicAgentImage, ironicAgentPullSecret: ironicAgentPullSecret, @@ -69,6 +71,14 @@ func (b *ignitionBuilder) Generate() ([]byte, error) { }) } + if len(b.registriesConf) > 0 { + registriesFile := ignitionFileEmbed("/etc/containers/registries.conf", + 0644, + b.registriesConf) + + config.Storage.Files = append(config.Storage.Files, registriesFile) + } + if len(b.nmStateData) > 0 { nmstatectl := exec.Command("nmstatectl", "gc", "-") nmstatectl.Stdin = strings.NewReader(string(b.nmStateData)) diff --git a/pkg/ignition/builder_test.go b/pkg/ignition/builder_test.go new file mode 100644 index 00000000..096206eb --- /dev/null +++ b/pkg/ignition/builder_test.go @@ -0,0 +1,32 @@ +package ignition + +import ( + "strings" + "testing" +) + +func TestGenerateRegistries(t *testing.T) { + registries := ` +[[registry]] + prefix = "" + location = "quay.io/openshift-release-dev/ocp-v4.0-art-dev" + mirror-by-digest-only = true + + [[registry.mirror]] + location = "virthost.ostest.test.metalkube.org:5000/localimages/local-release-image" +` + builder := New([]byte{}, []byte(registries), + "http://ironic.example.com", + "quay.io/openshift-release-dev/ironic-ipa-image", + "", "") + + ignition, err := builder.Generate() + if err != nil { + t.Fatalf("Unexpected error %v", err) + } + + registriesData := "\"data:text/plain,%0A%5B%5Bregistry%5D%5D%0A%20%20prefix%20%3D%20%22%22%0A%20%20location%20%3D%20%22quay.io%2Fopenshift-release-dev%2Focp-v4.0-art-dev%22%0A%20%20mirror-by-digest-only%20%3D%20true%0A%0A%20%20%5B%5Bregistry.mirror%5D%5D%0A%20%20%20%20location%20%3D%20%22virthost.ostest.test.metalkube.org%3A5000%2Flocalimages%2Flocal-release-image%22%0A\"" + if !strings.Contains(string(ignition), registriesData) { + t.Fatalf("Registries data not found in ignition:\n%s", string(ignition)) + } +} diff --git a/pkg/imageprovider/rhcos.go b/pkg/imageprovider/rhcos.go index d6637e44..68b3768d 100644 --- a/pkg/imageprovider/rhcos.go +++ b/pkg/imageprovider/rhcos.go @@ -13,14 +13,21 @@ import ( ) type rhcosImageProvider struct { - ImageHandler imagehandler.ImageHandler - EnvInputs *env.EnvInputs + ImageHandler imagehandler.ImageHandler + EnvInputs *env.EnvInputs + RegistriesConf []byte } func NewRHCOSImageProvider(imageServer imagehandler.ImageHandler, inputs *env.EnvInputs) imageprovider.ImageProvider { + registries, err := inputs.RegistriesConf() + if err != nil { + panic(err) + } + return &rhcosImageProvider{ - ImageHandler: imageServer, - EnvInputs: inputs, + ImageHandler: imageServer, + EnvInputs: inputs, + RegistriesConf: registries, } } @@ -40,7 +47,7 @@ func (ip *rhcosImageProvider) SupportsFormat(format metal3.ImageFormat) bool { func (ip *rhcosImageProvider) buildIgnitionConfig(networkData imageprovider.NetworkData) ([]byte, error) { nmstateData := networkData["nmstate"] - return ignition.New(nmstateData, + return ignition.New(nmstateData, ip.RegistriesConf, ip.EnvInputs.IronicBaseURL, ip.EnvInputs.IronicAgentImage, ip.EnvInputs.IronicAgentPullSecret, diff --git a/test/registries.conf b/test/registries.conf new file mode 100644 index 00000000..6cd8e392 --- /dev/null +++ b/test/registries.conf @@ -0,0 +1,7 @@ +[[registry]] + prefix = "" + location = "quay.io/openshift-release-dev/ocp-v4.0-art-dev" + mirror-by-digest-only = true + + [[registry.mirror]] + location = "virthost.ostest.test.metalkube.org:5000/localimages/local-release-image"