diff --git a/pkg/asset/machines/master.go b/pkg/asset/machines/master.go index a3147b8f73e..798cb2e9edd 100644 --- a/pkg/asset/machines/master.go +++ b/pkg/asset/machines/master.go @@ -14,6 +14,7 @@ import ( "github.com/openshift/installer/pkg/asset/installconfig" "github.com/openshift/installer/pkg/asset/machines/aws" "github.com/openshift/installer/pkg/asset/machines/libvirt" + "github.com/openshift/installer/pkg/asset/machines/machineconfig" "github.com/openshift/installer/pkg/asset/machines/openstack" "github.com/openshift/installer/pkg/asset/rhcos" awstypes "github.com/openshift/installer/pkg/types/aws" @@ -22,6 +23,7 @@ import ( nonetypes "github.com/openshift/installer/pkg/types/none" openstacktypes "github.com/openshift/installer/pkg/types/openstack" vspheretypes "github.com/openshift/installer/pkg/types/vsphere" + mcfgv1 "github.com/openshift/machine-config-operator/pkg/apis/machineconfiguration.openshift.io/v1" "github.com/pkg/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/serializer" @@ -33,17 +35,23 @@ import ( // Master generates the machines for the `master` machine pool. type Master struct { - FileList []*asset.File + UserDataFile *asset.File + MachineConfigFiles []*asset.File + MachineFiles []*asset.File } -var ( +const ( directory = "openshift" - // MasterMachineFileName is the format string for constucting the master Machine filenames. - MasterMachineFileName = "99_openshift-cluster-api_master-machines-%s.yaml" + // masterMachineFileName is the format string for constucting the master Machine filenames. + masterMachineFileName = "99_openshift-cluster-api_master-machines-%s.yaml" + + // masterUserDataFileName is the filename used for the master user-data secret. + masterUserDataFileName = "99_openshift-cluster-api_master-user-data-secret.yaml" +) - // MasterUserDataFileName is the filename used for the master user-data secret. - MasterUserDataFileName = "99_openshift-cluster-api_master-user-data-secret.yaml" +var ( + masterMachineFileNamePattern = fmt.Sprintf(masterMachineFileName, "*") _ asset.WritableAsset = (*Master)(nil) ) @@ -82,10 +90,10 @@ func (m *Master) Generate(dependencies asset.Parents) error { mign := &machine.Master{} dependencies.Get(clusterID, installconfig, rhcosImage, mign) - var err error - machines := []machineapi.Machine{} ic := installconfig.Config pool := ic.ControlPlane + var err error + machines := []machineapi.Machine{} switch ic.Platform.Name() { case awstypes.Name: mpool := defaultAWSMachinePoolPlatform() @@ -138,17 +146,19 @@ func (m *Master) Generate(dependencies asset.Parents) error { return errors.Wrap(err, "failed to create user-data secret for master machines") } - m.FileList = []*asset.File{{ - Filename: filepath.Join(directory, MasterUserDataFileName), + m.UserDataFile = &asset.File{ + Filename: filepath.Join(directory, masterUserDataFileName), Data: data, - }} + } - count := len(machines) - if count == 0 { - return errors.New("at least one master machine must be configured") + machineConfigs := []*mcfgv1.MachineConfig{} + m.MachineConfigFiles, err = machineconfig.Manifests(machineConfigs, "master", directory) + if err != nil { + return errors.Wrap(err, "failed to create MachineConfig manifests for master machines") } - padFormat := fmt.Sprintf("%%0%dd", len(fmt.Sprintf("%d", count))) + m.MachineFiles = make([]*asset.File, len(machines)) + padFormat := fmt.Sprintf("%%0%dd", len(fmt.Sprintf("%d", len(machines)))) for i, machine := range machines { data, err := yaml.Marshal(machine) if err != nil { @@ -156,10 +166,10 @@ func (m *Master) Generate(dependencies asset.Parents) error { } padded := fmt.Sprintf(padFormat, i) - m.FileList = append(m.FileList, &asset.File{ - Filename: filepath.Join(directory, fmt.Sprintf(MasterMachineFileName, padded)), + m.MachineFiles[i] = &asset.File{ + Filename: filepath.Join(directory, fmt.Sprintf(masterMachineFileName, padded)), Data: data, - }) + } } return nil @@ -167,42 +177,49 @@ func (m *Master) Generate(dependencies asset.Parents) error { // Files returns the files generated by the asset. func (m *Master) Files() []*asset.File { - return m.FileList + files := make([]*asset.File, 0, 1+len(m.MachineConfigFiles)+len(m.MachineFiles)) + if m.UserDataFile != nil { + files = append(files, m.UserDataFile) + } + files = append(files, m.MachineConfigFiles...) + files = append(files, m.MachineFiles...) + return files } // Load reads the asset files from disk. func (m *Master) Load(f asset.FileFetcher) (found bool, err error) { - file, err := f.FetchByName(filepath.Join(directory, MasterUserDataFileName)) + file, err := f.FetchByName(filepath.Join(directory, masterUserDataFileName)) if err != nil { if os.IsNotExist(err) { return false, nil } return false, err } - m.FileList = []*asset.File{file} + m.UserDataFile = file - fileList, err := f.FetchByPattern(filepath.Join(directory, fmt.Sprintf(MasterMachineFileName, "*"))) + m.MachineConfigFiles, err = machineconfig.Load(f, "master", directory) + if err != nil { + return true, err + } + + fileList, err := f.FetchByPattern(filepath.Join(directory, masterMachineFileNamePattern)) if err != nil { return true, err } if len(fileList) == 0 { - return true, errors.Errorf("master machine manifests are required if you also provide %s", file.Filename) + return true, errors.Errorf("master machine manifests are required if you also provide %s", m.UserDataFile.Filename) } - m.FileList = append(m.FileList, fileList...) + m.MachineFiles = fileList return true, nil } // Machines returns master Machine manifest YAML. func (m *Master) Machines() [][]byte { - machines := [][]byte{} - userData := filepath.Join(directory, MasterUserDataFileName) - for _, file := range m.FileList { - if file.Filename == userData { - continue - } - machines = append(machines, file.Data) + machines := make([][]byte, len(m.MachineFiles)) + for i, file := range m.MachineFiles { + machines[i] = file.Data } return machines } @@ -220,9 +237,9 @@ func (m *Master) StructuredMachines() ([]machineapi.Machine, error) { ) machines := []machineapi.Machine{} - for i, data := range m.Machines() { + for i, file := range m.MachineFiles { machine := &machineapi.Machine{} - err := yaml.Unmarshal(data, &machine) + err := yaml.Unmarshal(file.Data, &machine) if err != nil { return machines, errors.Wrapf(err, "unmarshal master %d", i) } @@ -238,3 +255,23 @@ func (m *Master) StructuredMachines() ([]machineapi.Machine, error) { return machines, nil } + +// IsMasterManifest tests whether a file is a manifest that belongs to the +// Master Machines asset. +func IsMasterManifest(file *asset.File) bool { + if filepath.Dir(file.Filename) != directory { + return false + } + filename := filepath.Base(file.Filename) + if filename == masterUserDataFileName { + return true + } + if machineconfig.IsManifest("master", filename) { + return true + } + if matched, err := filepath.Match(masterMachineFileNamePattern, filename); err != nil { + panic("bad format for master machine file name pattern") + } else { + return matched + } +} diff --git a/pkg/asset/manifests/openshift.go b/pkg/asset/manifests/openshift.go index 5e3db74e6e4..ee033052aee 100644 --- a/pkg/asset/manifests/openshift.go +++ b/pkg/asset/manifests/openshift.go @@ -2,7 +2,6 @@ package manifests import ( "encoding/base64" - "fmt" "path/filepath" "github.com/aws/aws-sdk-go/aws/session" @@ -154,18 +153,8 @@ func (o *Openshift) Load(f asset.FileFetcher) (bool, error) { return false, err } - masterMachinePattern := fmt.Sprintf(machines.MasterMachineFileName, "*") for _, file := range fileList { - filename := filepath.Base(file.Filename) - if filename == machines.MasterUserDataFileName { - continue - } - - matched, err := filepath.Match(masterMachinePattern, filename) - if err != nil { - return true, err - } - if matched { + if machines.IsMasterManifest(file) { continue }