Skip to content

Commit ba9211c

Browse files
Merge pull request openshift#7824 from patrickdillon/infra-interface-assets
CORS-3139: Move CAPI behind infrastructure provider interface
2 parents ea9d42b + a03afe9 commit ba9211c

File tree

17 files changed

+658
-334
lines changed

17 files changed

+658
-334
lines changed

pkg/asset/cluster/cluster.go

Lines changed: 12 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,23 @@ import (
55
"fmt"
66
"path/filepath"
77
"strings"
8-
"time"
98

109
"github.com/pkg/errors"
1110
"github.com/sirupsen/logrus"
12-
"gopkg.in/yaml.v2"
13-
apierrors "k8s.io/apimachinery/pkg/api/errors"
14-
"k8s.io/apimachinery/pkg/util/wait"
15-
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
16-
utilkubeconfig "sigs.k8s.io/cluster-api/util/kubeconfig"
17-
"sigs.k8s.io/controller-runtime/pkg/client"
18-
"sigs.k8s.io/controller-runtime/pkg/manager/signals"
1911

2012
"github.com/openshift/installer/pkg/asset"
2113
"github.com/openshift/installer/pkg/asset/cluster/aws"
2214
"github.com/openshift/installer/pkg/asset/cluster/azure"
2315
"github.com/openshift/installer/pkg/asset/cluster/openstack"
16+
"github.com/openshift/installer/pkg/asset/cluster/tfvars"
17+
"github.com/openshift/installer/pkg/asset/ignition/bootstrap"
18+
"github.com/openshift/installer/pkg/asset/ignition/machine"
2419
"github.com/openshift/installer/pkg/asset/installconfig"
25-
awsconfig "github.com/openshift/installer/pkg/asset/installconfig/aws"
2620
"github.com/openshift/installer/pkg/asset/kubeconfig"
27-
"github.com/openshift/installer/pkg/asset/manifests/capiutils"
21+
"github.com/openshift/installer/pkg/asset/machines"
2822
capimanifests "github.com/openshift/installer/pkg/asset/manifests/clusterapi"
2923
"github.com/openshift/installer/pkg/asset/password"
3024
"github.com/openshift/installer/pkg/asset/quota"
31-
"github.com/openshift/installer/pkg/clusterapi"
3225
infra "github.com/openshift/installer/pkg/infrastructure/platform"
3326
typesaws "github.com/openshift/installer/pkg/types/aws"
3427
typesazure "github.com/openshift/installer/pkg/types/azure"
@@ -67,10 +60,13 @@ func (c *Cluster) Dependencies() []asset.Asset {
6760
&installconfig.PlatformPermsCheck{},
6861
&installconfig.PlatformProvisionCheck{},
6962
&quota.PlatformQuotaCheck{},
70-
&TerraformVariables{},
63+
&tfvars.TerraformVariables{},
7164
&password.KubeadminPassword{},
7265
&capimanifests.Cluster{},
7366
&kubeconfig.AdminClient{},
67+
&bootstrap.Bootstrap{},
68+
&machine.Master{},
69+
&machines.ClusterAPI{},
7470
}
7571
}
7672

@@ -82,7 +78,7 @@ func (c *Cluster) Generate(parents asset.Parents) (err error) {
8278

8379
clusterID := &installconfig.ClusterID{}
8480
installConfig := &installconfig.InstallConfig{}
85-
terraformVariables := &TerraformVariables{}
81+
terraformVariables := &tfvars.TerraformVariables{}
8682
parents.Get(clusterID, installConfig, terraformVariables)
8783

8884
if fs := installConfig.Config.FeatureSet; strings.HasSuffix(string(fs), "NoUpgrade") {
@@ -97,31 +93,14 @@ func (c *Cluster) Generate(parents asset.Parents) (err error) {
9793
return errors.New("cluster cannot be created with bootstrapInPlace set")
9894
}
9995

100-
// Check if we're using Cluster API.
101-
if capiutils.IsEnabled(installConfig) {
102-
// TODO(vincepri): The context should be passed down from the caller,
103-
// although today the Asset interface doesn't allow it, refactor once it does.
104-
ctx, cancel := context.WithCancel(signals.SetupSignalHandler())
105-
go func() {
106-
<-ctx.Done()
107-
cancel()
108-
clusterapi.System().Teardown()
109-
}()
110-
111-
return c.provisionWithClusterAPI(ctx, parents, installConfig, clusterID)
112-
}
113-
114-
// Otherwise, use the normal path.
115-
return c.provision(installConfig, clusterID, terraformVariables)
116-
}
117-
118-
func (c *Cluster) provision(installConfig *installconfig.InstallConfig, clusterID *installconfig.ClusterID, terraformVariables *TerraformVariables) error {
11996
platform := installConfig.Config.Platform.Name()
12097

12198
if azure := installConfig.Config.Platform.Azure; azure != nil && azure.CloudName == typesazure.StackCloud {
12299
platform = typesazure.StackTerraformName
123100
}
124101

102+
// TODO(padillon): determine whether CAPI handles tagging shared subnets, in which case we should be able
103+
// to encapsulate these into the terraform package.
125104
logrus.Infof("Creating infrastructure resources...")
126105
switch platform {
127106
case typesaws.Name:
@@ -138,16 +117,11 @@ func (c *Cluster) provision(installConfig *installconfig.InstallConfig, clusterI
138117
}
139118
}
140119

141-
tfvarsFiles := []*asset.File{}
142-
for _, file := range terraformVariables.Files() {
143-
tfvarsFiles = append(tfvarsFiles, file)
144-
}
145-
146120
provider, err := infra.ProviderForPlatform(platform, installConfig.Config.EnabledFeatureGates())
147121
if err != nil {
148122
return fmt.Errorf("error getting infrastructure provider: %w", err)
149123
}
150-
files, err := provider.Provision(InstallDir, tfvarsFiles)
124+
files, err := provider.Provision(InstallDir, parents)
151125
if files != nil {
152126
c.FileList = append(c.FileList, files...) // append state files even in case of failure
153127
}
@@ -158,137 +132,6 @@ func (c *Cluster) provision(installConfig *installconfig.InstallConfig, clusterI
158132
return nil
159133
}
160134

161-
func (c *Cluster) provisionWithClusterAPI(ctx context.Context, parents asset.Parents, installConfig *installconfig.InstallConfig, clusterID *installconfig.ClusterID) error {
162-
capiManifests := &capimanifests.Cluster{}
163-
clusterKubeconfigAsset := &kubeconfig.AdminClient{}
164-
parents.Get(
165-
capiManifests,
166-
clusterKubeconfigAsset,
167-
)
168-
169-
// Only need the objects--not the files.
170-
manifests := []client.Object{}
171-
for _, m := range capiManifests.RuntimeFiles() {
172-
manifests = append(manifests, m.Object)
173-
}
174-
175-
// Run the CAPI system.
176-
capiSystem := clusterapi.System()
177-
if err := capiSystem.Run(ctx, installConfig); err != nil {
178-
return fmt.Errorf("failed to run cluster api system: %w", err)
179-
}
180-
181-
// Grab the client.
182-
cl := capiSystem.Client()
183-
184-
// Create all the manifests and store them.
185-
for _, m := range manifests {
186-
m.SetNamespace(capiutils.Namespace)
187-
if err := cl.Create(context.Background(), m); err != nil {
188-
return fmt.Errorf("failed to create manifest: %w", err)
189-
}
190-
logrus.Infof("Created manifest %+T, namespace=%s name=%s", m, m.GetNamespace(), m.GetName())
191-
}
192-
193-
// Pass cluster kubeconfig and store it in; this is usually the role of a bootstrap provider.
194-
{
195-
key := client.ObjectKey{
196-
Name: clusterID.InfraID,
197-
Namespace: capiutils.Namespace,
198-
}
199-
cluster := &clusterv1.Cluster{}
200-
if err := cl.Get(context.Background(), key, cluster); err != nil {
201-
return err
202-
}
203-
// Create the secret.
204-
clusterKubeconfig := clusterKubeconfigAsset.Files()[0].Data
205-
secret := utilkubeconfig.GenerateSecret(cluster, clusterKubeconfig)
206-
if err := cl.Create(context.Background(), secret); err != nil {
207-
return err
208-
}
209-
}
210-
211-
// Wait for the load balancer to be ready by checking the control plane endpoint
212-
// on the cluster object.
213-
var cluster *clusterv1.Cluster
214-
{
215-
if err := wait.ExponentialBackoff(wait.Backoff{
216-
Duration: time.Second * 10,
217-
Factor: float64(1.5),
218-
Steps: 32,
219-
}, func() (bool, error) {
220-
c := &clusterv1.Cluster{}
221-
if err := cl.Get(context.Background(), client.ObjectKey{
222-
Name: clusterID.InfraID,
223-
Namespace: capiutils.Namespace,
224-
}, c); err != nil {
225-
if apierrors.IsNotFound(err) {
226-
return false, nil
227-
}
228-
return false, err
229-
}
230-
cluster = c
231-
return cluster.Spec.ControlPlaneEndpoint.IsValid(), nil
232-
}); err != nil {
233-
return err
234-
}
235-
if cluster == nil {
236-
return errors.New("error occurred during load balancer ready check")
237-
}
238-
if cluster.Spec.ControlPlaneEndpoint.Host == "" {
239-
return errors.New("control plane endpoint is not set")
240-
}
241-
}
242-
243-
// Run the post-provisioning steps for the platform we're on.
244-
// TODO(vincepri): The following should probably be in a separate package with a clear
245-
// interface and multiple hooks at different stages of the cluster lifecycle.
246-
switch installConfig.Config.Platform.Name() {
247-
case typesaws.Name:
248-
ssn, err := installConfig.AWS.Session(context.TODO())
249-
if err != nil {
250-
return fmt.Errorf("failed to create session: %w", err)
251-
}
252-
client := awsconfig.NewClient(ssn)
253-
r53cfg := awsconfig.GetR53ClientCfg(ssn, "")
254-
err = client.CreateOrUpdateRecord(installConfig.Config, cluster.Spec.ControlPlaneEndpoint.Host, r53cfg)
255-
if err != nil {
256-
return fmt.Errorf("failed to create route53 records: %w", err)
257-
}
258-
logrus.Infof("Created Route53 records to control plane load balancer.")
259-
default:
260-
}
261-
262-
// For each manifest we created, retrieve it and store it in the asset.
263-
for _, m := range manifests {
264-
key := client.ObjectKey{
265-
Name: m.GetName(),
266-
Namespace: m.GetNamespace(),
267-
}
268-
if err := cl.Get(context.Background(), key, m); err != nil {
269-
return fmt.Errorf("failed to get manifest: %w", err)
270-
}
271-
272-
gvk, err := cl.GroupVersionKindFor(m)
273-
if err != nil {
274-
return fmt.Errorf("failed to get GVK for manifest: %w", err)
275-
}
276-
fileName := fmt.Sprintf("%s-%s-%s.yaml", gvk.Kind, m.GetNamespace(), m.GetName())
277-
objData, err := yaml.Marshal(m)
278-
if err != nil {
279-
errMsg := fmt.Sprintf("failed to create infrastructure manifest %s from InstallConfig", fileName)
280-
return errors.Wrapf(err, errMsg)
281-
}
282-
c.FileList = append(c.FileList, &asset.File{
283-
Filename: fileName,
284-
Data: objData,
285-
})
286-
}
287-
288-
logrus.Infof("Cluster API resources have been created. Waiting for cluster to become ready...")
289-
return nil
290-
}
291-
292135
// Files returns the FileList generated by the asset.
293136
func (c *Cluster) Files() []*asset.File {
294137
return c.FileList

pkg/asset/cluster/metadata.go

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ package cluster
22

33
import (
44
"encoding/json"
5-
"os"
6-
"path/filepath"
75

86
"github.com/pkg/errors"
97

@@ -15,6 +13,7 @@ import (
1513
"github.com/openshift/installer/pkg/asset/cluster/gcp"
1614
"github.com/openshift/installer/pkg/asset/cluster/ibmcloud"
1715
"github.com/openshift/installer/pkg/asset/cluster/libvirt"
16+
clustermetadata "github.com/openshift/installer/pkg/asset/cluster/metadata"
1817
"github.com/openshift/installer/pkg/asset/cluster/nutanix"
1918
"github.com/openshift/installer/pkg/asset/cluster/openstack"
2019
"github.com/openshift/installer/pkg/asset/cluster/ovirt"
@@ -39,10 +38,6 @@ import (
3938
vspheretypes "github.com/openshift/installer/pkg/types/vsphere"
4039
)
4140

42-
const (
43-
metadataFileName = "metadata.json"
44-
)
45-
4641
// Metadata contains information needed to destroy clusters.
4742
type Metadata struct {
4843
File *asset.File
@@ -119,7 +114,7 @@ func (m *Metadata) Generate(parents asset.Parents) (err error) {
119114
}
120115

121116
m.File = &asset.File{
122-
Filename: metadataFileName,
117+
Filename: clustermetadata.FileName,
123118
Data: data,
124119
}
125120

@@ -139,19 +134,3 @@ func (m *Metadata) Files() []*asset.File {
139134
func (m *Metadata) Load(f asset.FileFetcher) (found bool, err error) {
140135
return false, nil
141136
}
142-
143-
// LoadMetadata loads the cluster metadata from an asset directory.
144-
func LoadMetadata(dir string) (*types.ClusterMetadata, error) {
145-
path := filepath.Join(dir, metadataFileName)
146-
raw, err := os.ReadFile(path)
147-
if err != nil {
148-
return nil, err
149-
}
150-
151-
var metadata *types.ClusterMetadata
152-
if err = json.Unmarshal(raw, &metadata); err != nil {
153-
return nil, errors.Wrapf(err, "failed to Unmarshal data from %q to types.ClusterMetadata", path)
154-
}
155-
156-
return metadata, err
157-
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package metadata
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"os"
7+
"path/filepath"
8+
9+
"github.com/openshift/installer/pkg/types"
10+
)
11+
12+
const (
13+
// FileName is the filename for the cluster metadata.json file.
14+
FileName = "metadata.json"
15+
)
16+
17+
// Load loads the cluster metadata from an asset directory.
18+
func Load(dir string) (*types.ClusterMetadata, error) {
19+
path := filepath.Join(dir, FileName)
20+
raw, err := os.ReadFile(path)
21+
if err != nil {
22+
return nil, err
23+
}
24+
25+
var metadata *types.ClusterMetadata
26+
if err = json.Unmarshal(raw, &metadata); err != nil {
27+
return nil, fmt.Errorf("failed to Unmarshal data from %q to types.ClusterMetadata: %w", path, err)
28+
}
29+
30+
return metadata, err
31+
}

0 commit comments

Comments
 (0)