Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion Gopkg.lock

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

37 changes: 37 additions & 0 deletions pkg/asset/machines/machineconfig/authorizedkeys.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package machineconfig

import (
"fmt"

ignv2_2types "github.com/coreos/ignition/config/v2_2/types"
mcfgv1 "github.com/openshift/machine-config-operator/pkg/apis/machineconfiguration.openshift.io/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// ForAuthorizedKeys creates the MachineConfig to set the authorized key for `core` user.
func ForAuthorizedKeys(key string, role string) *mcfgv1.MachineConfig {
return &mcfgv1.MachineConfig{
TypeMeta: metav1.TypeMeta{
APIVersion: mcfgv1.SchemeGroupVersion.String(),
Kind: "MachineConfig",
},
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("99-%s-ssh", role),
Labels: map[string]string{
"machineconfiguration.openshift.io/role": role,
},
},
Spec: mcfgv1.MachineConfigSpec{
Config: ignv2_2types.Config{
Ignition: ignv2_2types.Ignition{
Version: ignv2_2types.MaxVersion.String(),
},
Passwd: ignv2_2types.Passwd{
Users: []ignv2_2types.PasswdUser{{
Name: "core", SSHAuthorizedKeys: []ignv2_2types.SSHAuthorizedKey{ignv2_2types.SSHAuthorizedKey(key)},
}},
},
},
},
}
}
63 changes: 63 additions & 0 deletions pkg/asset/machines/machineconfig/manifest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package machineconfig

import (
"fmt"
"os"
"path/filepath"

"github.com/ghodss/yaml"

mcfgv1 "github.com/openshift/machine-config-operator/pkg/apis/machineconfiguration.openshift.io/v1"

"github.com/openshift/installer/pkg/asset"
)

const (
machineConfigFileName = "99_openshift-machineconfig_%s.yaml"
)

var (
machineConfigFileNamePattern = fmt.Sprintf(machineConfigFileName, "*")
)

// Manifests creates manifest files containing the MachineConfigs.
func Manifests(configs []*mcfgv1.MachineConfig, role, directory string) ([]*asset.File, error) {
data := []byte{}
for _, c := range configs {
if c == nil {
continue
}
configData, err := yaml.Marshal(c)
if err != nil {
return nil, err
}
data = append(data, []byte("---\n")...)
data = append(data, configData...)
}
if len(data) == 0 {
return nil, nil
}
return []*asset.File{
{
Filename: filepath.Join(directory, fmt.Sprintf(machineConfigFileName, role)),
Data: data,
},
}, nil
}

// IsManifest tests whether the specified filename is a MachineConfig manifest.
func IsManifest(role, filename string) bool {
return fmt.Sprintf(machineConfigFileName, role) == filename
}

// Load loads the MachineConfig manifests.
func Load(f asset.FileFetcher, role, directory string) ([]*asset.File, error) {
file, err := f.FetchByName(filepath.Join(directory, fmt.Sprintf(machineConfigFileName, role)))
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, err
}
return []*asset.File{file}, nil
}
106 changes: 73 additions & 33 deletions pkg/asset/machines/master.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand All @@ -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)
)
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -138,71 +146,83 @@ 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{}
if ic.SSHKey != "" {
machineConfigs = append(machineConfigs, machineconfig.ForAuthorizedKeys(ic.SSHKey, "master"))
}
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 {
return errors.Wrapf(err, "marshal master %d", i)
}

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
}

// 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

m.MachineConfigFiles, err = machineconfig.Load(f, "master", directory)
if err != nil {
return true, err
}

fileList, err := f.FetchByPattern(filepath.Join(directory, fmt.Sprintf(MasterMachineFileName, "*")))
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
}
Expand All @@ -220,9 +240,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)
}
Expand All @@ -238,3 +258,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
}
}
Loading