diff --git a/pkg/asset/ignition/bootstrap/bootstrap.go b/pkg/asset/ignition/bootstrap/bootstrap.go index cf5c040a7d5..24a80cf66a5 100644 --- a/pkg/asset/ignition/bootstrap/bootstrap.go +++ b/pkg/asset/ignition/bootstrap/bootstrap.go @@ -173,6 +173,14 @@ func (a *Bootstrap) Generate(dependencies asset.Parents) error { if err != nil { return errors.Wrap(err, "failed to Marshal Ignition config") } + + if installConfig.Config.Spec3 == true { + data, err = ignition.ConvertSpec2ToSpec3(data) + if err != nil { + return err + } + } + a.File = &asset.File{ Filename: bootstrapIgnFilename, Data: data, diff --git a/pkg/asset/ignition/machine/master.go b/pkg/asset/ignition/machine/master.go index bf7e860ef36..3751147a3eb 100644 --- a/pkg/asset/ignition/machine/master.go +++ b/pkg/asset/ignition/machine/master.go @@ -8,6 +8,7 @@ import ( "github.com/pkg/errors" "github.com/openshift/installer/pkg/asset" + "github.com/openshift/installer/pkg/asset/ignition" "github.com/openshift/installer/pkg/asset/installconfig" "github.com/openshift/installer/pkg/asset/tls" ) @@ -44,6 +45,14 @@ func (a *Master) Generate(dependencies asset.Parents) error { if err != nil { return errors.Wrap(err, "failed to marshal Ignition config") } + + if installConfig.Config.Spec3 == true { + data, err = ignition.ConvertSpec2ToSpec3(data) + if err != nil { + return err + } + } + a.File = &asset.File{ Filename: masterIgnFilename, Data: data, diff --git a/pkg/asset/ignition/machine/worker.go b/pkg/asset/ignition/machine/worker.go index e47f28fdcc5..15440fdf41c 100644 --- a/pkg/asset/ignition/machine/worker.go +++ b/pkg/asset/ignition/machine/worker.go @@ -8,6 +8,7 @@ import ( "github.com/pkg/errors" "github.com/openshift/installer/pkg/asset" + "github.com/openshift/installer/pkg/asset/ignition" "github.com/openshift/installer/pkg/asset/installconfig" "github.com/openshift/installer/pkg/asset/tls" ) @@ -44,6 +45,14 @@ func (a *Worker) Generate(dependencies asset.Parents) error { if err != nil { return errors.Wrap(err, "failed to marshal Ignition config") } + + if installConfig.Config.Spec3 == true { + data, err = ignition.ConvertSpec2ToSpec3(data) + if err != nil { + return err + } + } + a.File = &asset.File{ Filename: workerIgnFilename, Data: data, diff --git a/pkg/asset/ignition/spec2to3.go b/pkg/asset/ignition/spec2to3.go new file mode 100644 index 00000000000..6295904e0a2 --- /dev/null +++ b/pkg/asset/ignition/spec2to3.go @@ -0,0 +1,74 @@ +package ignition + +import ( + "encoding/json" + + "github.com/pkg/errors" +) + +// ConvertSpec2ToSpec3 converts Ignition spec2 to ignition spec3 +func ConvertSpec2ToSpec3(spec2data []byte) ([]byte, error) { + // Unmarshal + jsonMap := make(map[string]interface{}) + err := json.Unmarshal(spec2data, &jsonMap) + if err != nil { + return nil, errors.Wrap(err, "failed to Marshal Ignition config") + } + + // Replace ignition.version + ign := jsonMap["ignition"].(map[string]interface{}) + ign["version"] = "3.0.0" + + // ignition.config.append -> ignition.config.merge + config := ign["config"].(map[string]interface{}) + if val, ok := config["append"]; ok { + config["merge"] = val + delete(config, "append") + } + ign["config"] = config + jsonMap["ignition"] = ign + + // Delete networkd section + if _, ok := jsonMap["networkd"]; ok { + delete(jsonMap, "networkd") + } + + // Modify storage.files + if sval, ok := jsonMap["storage"]; ok { + storage := sval.(map[string]interface{}) + + if fval, ok := storage["files"]; ok { + files := fval.([]interface{}) + + updatedFiles := make([]interface{}, 0) + + for i := range files { + file := files[i].(map[string]interface{}) + // Remove filesystem + if _, ok := file["filesystem"]; ok { + delete(file, "filesystem") + } + // append is no longer a flag + if val, ok := file["append"]; ok { + if val == "true" { + if contentsval, ok := file["contents"]; ok { + file["append"] = contentsval + delete(file, "contents") + } + } + } + + updatedFiles = append(updatedFiles, file) + } + storage["files"] = updatedFiles + } + jsonMap["storage"] = storage + } + + // Convert to bytes + spec3data, err := json.Marshal(jsonMap) + if err != nil { + return nil, errors.Wrap(err, "failed to Marshal Ignition config") + } + return spec3data, nil +} diff --git a/pkg/types/installconfig.go b/pkg/types/installconfig.go index 7b2c0ee41ca..a3d77c34244 100644 --- a/pkg/types/installconfig.go +++ b/pkg/types/installconfig.go @@ -87,6 +87,10 @@ type InstallConfig struct { // ImageContentSources lists sources/repositories for the release-image content. ImageContentSources []ImageContentSource `json:"imageContentSources,omitempty"` + + // Spec3 is a flag to convert Ignition in spec3 + // +optional + Spec3 bool `json:"spec3,omitempty"` } // ClusterDomain returns the DNS domain that all records for a cluster must belong to.