@@ -3,41 +3,85 @@ package machines
33import (
44 "context"
55 "fmt"
6+ "os"
7+ "path/filepath"
68 "strings"
79
810 "github.com/pkg/errors"
911 "github.com/sirupsen/logrus"
1012 v1 "k8s.io/api/core/v1"
1113 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
14+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
1215 "k8s.io/utils/ptr"
1316 capa "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2"
1417 capi "sigs.k8s.io/cluster-api/api/v1beta1"
18+ "sigs.k8s.io/controller-runtime/pkg/client"
19+ "sigs.k8s.io/yaml"
1520
1621 configv1 "github.com/openshift/api/config/v1"
1722 "github.com/openshift/installer/pkg/asset"
1823 "github.com/openshift/installer/pkg/asset/installconfig"
1924 "github.com/openshift/installer/pkg/asset/machines/aws"
2025 "github.com/openshift/installer/pkg/asset/manifests/capiutils"
2126 "github.com/openshift/installer/pkg/asset/rhcos"
27+ "github.com/openshift/installer/pkg/clusterapi"
2228 awstypes "github.com/openshift/installer/pkg/types/aws"
2329 awsdefaults "github.com/openshift/installer/pkg/types/aws/defaults"
2430 azuretypes "github.com/openshift/installer/pkg/types/azure"
2531)
2632
27- // GenerateClusterAPI generates manifests for target cluster.
28- func GenerateClusterAPI (ctx context.Context , installConfig * installconfig.InstallConfig , clusterID * installconfig.ClusterID , rhcosImage * rhcos.Image ) (* capiutils.GenerateMachinesOutput , error ) {
33+ var _ asset.WritableRuntimeAsset = (* ClusterAPI )(nil )
34+
35+ // ClusterAPI is the asset for CAPI control-plane manifests.
36+ type ClusterAPI struct {
37+ FileList []* asset.RuntimeFile
38+ }
39+
40+ // Name returns a human friendly name for the operator.
41+ func (c * ClusterAPI ) Name () string {
42+ return "Cluster API Machine Manifests"
43+ }
44+
45+ // Dependencies returns all of the dependencies directly needed by the
46+ // ClusterAPI machines asset.
47+ func (c * ClusterAPI ) Dependencies () []asset.Asset {
48+ return []asset.Asset {
49+ & installconfig.InstallConfig {},
50+ & installconfig.ClusterID {},
51+ new (rhcos.Image ),
52+ }
53+ }
54+
55+ // Generate generates Cluster API machine manifests.
56+ func (c * ClusterAPI ) Generate (dependencies asset.Parents ) error {
57+ installConfig := & installconfig.InstallConfig {}
58+ clusterID := & installconfig.ClusterID {}
59+ rhcosImage := new (rhcos.Image )
60+ dependencies .Get (installConfig , clusterID , rhcosImage )
61+
62+ // If the feature gate is not enabled, do not generate any manifests.
63+ if ! capiutils .IsEnabled (installConfig ) {
64+ return nil
65+ }
66+
67+ if err := os .MkdirAll (filepath .Dir (capiutils .ManifestDir ), 0755 ); err != nil {
68+ return err
69+ }
70+
71+ c .FileList = []* asset.RuntimeFile {}
72+
2973 var err error
30- result := & capiutils.GenerateMachinesOutput {}
3174 ic := installConfig .Config
3275 pool := * ic .ControlPlane
76+ ctx := context .TODO ()
3377
3478 switch ic .Platform .Name () {
3579 case awstypes .Name :
3680 subnets := map [string ]string {}
3781 if len (ic .Platform .AWS .Subnets ) > 0 {
3882 subnetMeta , err := installConfig .AWS .PrivateSubnets (ctx )
3983 if err != nil {
40- return nil , err
84+ return err
4185 }
4286 for id , subnet := range subnetMeta {
4387 subnets [subnet .Zone .Name ] = id
@@ -64,7 +108,7 @@ func GenerateClusterAPI(ctx context.Context, installConfig *installconfig.Instal
64108 } else {
65109 mpool .Zones , err = installConfig .AWS .AvailabilityZones (ctx )
66110 if err != nil {
67- return nil , err
111+ return err
68112 }
69113 zoneDefaults = true
70114 }
@@ -100,9 +144,9 @@ func GenerateClusterAPI(ctx context.Context, installConfig *installconfig.Instal
100144 installConfig .Config .Platform .AWS .UserTags ,
101145 )
102146 if err != nil {
103- return nil , errors .Wrap (err , "failed to create master machine objects" )
147+ return errors .Wrap (err , "failed to create master machine objects" )
104148 }
105- result . Manifests = append (result . Manifests , awsMachines ... )
149+ c . FileList = append (c . FileList , awsMachines ... )
106150
107151 // TODO(vincepri): The following code is almost duplicated from aws.AWSMachines.
108152 // Refactor and generalize around a bootstrap pool, with a single machine and
@@ -142,7 +186,7 @@ func GenerateClusterAPI(ctx context.Context, installConfig *installconfig.Instal
142186 )
143187 }
144188
145- result . Manifests = append (result . Manifests , & asset.RuntimeFile {
189+ c . FileList = append (c . FileList , & asset.RuntimeFile {
146190 File : asset.File {Filename : fmt .Sprintf ("10_inframachine_%s.yaml" , bootstrapAWSMachine .Name )},
147191 Object : bootstrapAWSMachine ,
148192 })
@@ -167,7 +211,7 @@ func GenerateClusterAPI(ctx context.Context, installConfig *installconfig.Instal
167211 },
168212 }
169213
170- result . Manifests = append (result . Manifests , & asset.RuntimeFile {
214+ c . FileList = append (c . FileList , & asset.RuntimeFile {
171215 File : asset.File {Filename : fmt .Sprintf ("10_machine_%s.yaml" , bootstrapMachine .Name )},
172216 Object : bootstrapMachine ,
173217 })
@@ -176,5 +220,76 @@ func GenerateClusterAPI(ctx context.Context, installConfig *installconfig.Instal
176220 default :
177221 // TODO: support other platforms
178222 }
179- return result , nil
223+
224+ // Create the infrastructure manifests.
225+ for _ , m := range c .FileList {
226+ objData , err := yaml .Marshal (m .Object )
227+ if err != nil {
228+ return errors .Wrapf (err , "failed to marshal Cluster API machine manifest %s" , m .Filename )
229+ }
230+ m .Data = objData
231+
232+ // If the filename is already a path, do not append the manifest dir.
233+ if filepath .Dir (m .Filename ) == capiutils .ManifestDir {
234+ continue
235+ }
236+ m .Filename = filepath .Join (capiutils .ManifestDir , m .Filename )
237+ }
238+ asset .SortManifestFiles (c .FileList )
239+ return nil
240+ }
241+
242+ // Files returns the files generated by the asset.
243+ func (c * ClusterAPI ) Files () []* asset.File {
244+ files := []* asset.File {}
245+ for _ , f := range c .FileList {
246+ files = append (files , & f .File )
247+ }
248+ return files
249+ }
250+
251+ // RuntimeFiles returns the files generated by the asset.
252+ func (c * ClusterAPI ) RuntimeFiles () []* asset.RuntimeFile {
253+ return c .FileList
254+ }
255+
256+ // Load returns the openshift asset from disk.
257+ func (c * ClusterAPI ) Load (f asset.FileFetcher ) (bool , error ) {
258+ yamlFileList , err := f .FetchByPattern (filepath .Join (capiutils .ManifestDir , "*.yaml" ))
259+ if err != nil {
260+ return false , errors .Wrap (err , "failed to load *.yaml files" )
261+ }
262+ ymlFileList , err := f .FetchByPattern (filepath .Join (capiutils .ManifestDir , "*.yml" ))
263+ if err != nil {
264+ return false , errors .Wrap (err , "failed to load *.yml files" )
265+ }
266+ jsonFileList , err := f .FetchByPattern (filepath .Join (capiutils .ManifestDir , "*.json" ))
267+ if err != nil {
268+ return false , errors .Wrap (err , "failed to load *.json files" )
269+ }
270+ fileList := append (yamlFileList , ymlFileList ... ) //nolint:gocritic
271+ fileList = append (fileList , jsonFileList ... )
272+
273+ for _ , file := range fileList {
274+ u := & unstructured.Unstructured {}
275+ if err := yaml .Unmarshal (file .Data , u ); err != nil {
276+ return false , errors .Wrap (err , "failed to unmarshal file" )
277+ }
278+ obj , err := clusterapi .Scheme .New (u .GroupVersionKind ())
279+ if err != nil {
280+ return false , errors .Wrap (err , "failed to create object" )
281+ }
282+ if err := clusterapi .Scheme .Convert (u , obj , nil ); err != nil {
283+ return false , errors .Wrap (err , "failed to convert object" )
284+ }
285+ c .FileList = append (c .FileList , & asset.RuntimeFile {
286+ File : asset.File {
287+ Filename : file .Filename ,
288+ Data : file .Data },
289+ Object : obj .(client.Object ),
290+ })
291+ }
292+
293+ asset .SortManifestFiles (c .FileList )
294+ return len (c .FileList ) > 0 , nil
180295}
0 commit comments