Skip to content

Commit 645e13d

Browse files
committed
clusterapi: capture manifests on error
Write the cluster api manifests to disk on error-- not just on successful provisioning.
1 parent d33f013 commit 645e13d

File tree

1 file changed

+54
-33
lines changed

1 file changed

+54
-33
lines changed

pkg/infrastructure/clusterapi/clusterapi.go

Lines changed: 54 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
corev1 "k8s.io/api/core/v1"
1414
apierrors "k8s.io/apimachinery/pkg/api/errors"
1515
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
16+
utilerrors "k8s.io/apimachinery/pkg/util/errors"
1617
"k8s.io/apimachinery/pkg/util/wait"
1718
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
1819
utilkubeconfig "sigs.k8s.io/cluster-api/util/kubeconfig"
@@ -61,6 +62,8 @@ const (
6162
// in the lifecycle defined by the Provider interface.
6263
type InfraProvider struct {
6364
impl Provider
65+
66+
appliedManifests []client.Object
6467
}
6568

6669
// InitializeProvider returns a ClusterAPI provider implementation
@@ -72,7 +75,7 @@ func InitializeProvider(platform Provider) infrastructure.Provider {
7275
// Provision creates cluster resources by applying CAPI manifests to a locally running control plane.
7376
//
7477
//nolint:gocyclo
75-
func (i *InfraProvider) Provision(ctx context.Context, dir string, parents asset.Parents) ([]*asset.File, error) {
78+
func (i *InfraProvider) Provision(ctx context.Context, dir string, parents asset.Parents) (fileList []*asset.File, err error) {
7679
manifestsAsset := &manifests.Manifests{}
7780
workersAsset := &machines.Worker{}
7881
capiManifestsAsset := &capimanifests.Cluster{}
@@ -98,8 +101,6 @@ func (i *InfraProvider) Provision(ctx context.Context, dir string, parents asset
98101
tfvarsAsset,
99102
)
100103

101-
fileList := []*asset.File{}
102-
103104
// Collect cluster and non-machine-related infra manifests
104105
// to be applied during the initial stage.
105106
infraManifests := []client.Object{}
@@ -142,15 +143,29 @@ func (i *InfraProvider) Provision(ctx context.Context, dir string, parents asset
142143
// Grab the client.
143144
cl := capiSystem.Client()
144145

146+
// Make sure to always return generated manifests, even if errors happened
147+
defer func(ctx context.Context, cl client.Client) {
148+
var errs []error
149+
// Overriding the named return with the generated list
150+
fileList, errs = i.collectManifests(ctx, cl)
151+
// If Provision returned an error, add it to the list
152+
if err != nil {
153+
errs = append(errs, err)
154+
}
155+
err = utilerrors.NewAggregate(errs)
156+
}(ctx, cl)
157+
158+
i.appliedManifests = []client.Object{}
159+
145160
// Create the infra manifests.
146161
for _, m := range infraManifests {
147162
m.SetNamespace(capiutils.Namespace)
148163
if err := cl.Create(ctx, m); err != nil {
149164
return fileList, fmt.Errorf("failed to create infrastructure manifest: %w", err)
150165
}
166+
i.appliedManifests = append(i.appliedManifests, m)
151167
logrus.Infof("Created manifest %+T, namespace=%s name=%s", m, m.GetNamespace(), m.GetName())
152168
}
153-
154169
// Pass cluster kubeconfig and store it in; this is usually the role of a bootstrap provider.
155170
{
156171
key := client.ObjectKey{
@@ -228,7 +243,7 @@ func (i *InfraProvider) Provision(ctx context.Context, dir string, parents asset
228243

229244
bootstrapIgnData, err := injectInstallInfo(bootstrapIgnAsset.Files()[0].Data)
230245
if err != nil {
231-
return nil, fmt.Errorf("unable to inject installation info: %w", err)
246+
return fileList, fmt.Errorf("unable to inject installation info: %w", err)
232247
}
233248

234249
// The cloud-platform may need to override the default
@@ -261,6 +276,7 @@ func (i *InfraProvider) Provision(ctx context.Context, dir string, parents asset
261276
if err := cl.Create(ctx, m); err != nil {
262277
return fileList, fmt.Errorf("failed to create control-plane manifest: %w", err)
263278
}
279+
i.appliedManifests = append(i.appliedManifests, m)
264280
logrus.Infof("Created manifest %+T, namespace=%s name=%s", m, m.GetNamespace(), m.GetName())
265281
}
266282

@@ -324,34 +340,6 @@ func (i *InfraProvider) Provision(ctx context.Context, dir string, parents asset
324340
timer.StopTimer(postProvisionStage)
325341
}
326342

327-
// For each manifest we created, retrieve it and store it in the asset.
328-
manifests := []client.Object{}
329-
manifests = append(manifests, infraManifests...)
330-
manifests = append(manifests, machineManifests...)
331-
for _, m := range manifests {
332-
key := client.ObjectKey{
333-
Name: m.GetName(),
334-
Namespace: m.GetNamespace(),
335-
}
336-
if err := cl.Get(ctx, key, m); err != nil {
337-
return fileList, fmt.Errorf("failed to get manifest: %w", err)
338-
}
339-
340-
gvk, err := cl.GroupVersionKindFor(m)
341-
if err != nil {
342-
return fileList, fmt.Errorf("failed to get GVK for manifest: %w", err)
343-
}
344-
fileName := filepath.Join(CAPIArtifactsDir, fmt.Sprintf("%s-%s-%s.yaml", gvk.Kind, m.GetNamespace(), m.GetName()))
345-
objData, err := yaml.Marshal(m)
346-
if err != nil {
347-
return fileList, fmt.Errorf("failed to create infrastructure manifest %s from InstallConfig: %w", fileName, err)
348-
}
349-
fileList = append(fileList, &asset.File{
350-
Filename: fileName,
351-
Data: objData,
352-
})
353-
}
354-
355343
logrus.Infof("Cluster API resources have been created. Waiting for cluster to become ready...")
356344

357345
// If we're skipping bootstrap destroy, shutdown the local control plane.
@@ -518,3 +506,36 @@ func IgnitionSecret(ign []byte, infraID, role string) *corev1.Secret {
518506
secret.SetGroupVersionKind(corev1.SchemeGroupVersion.WithKind("Secret"))
519507
return secret
520508
}
509+
510+
func (i *InfraProvider) collectManifests(ctx context.Context, cl client.Client) ([]*asset.File, []error) {
511+
logrus.Debug("Collecting applied cluster api manifests...")
512+
errorList := []error{}
513+
fileList := []*asset.File{}
514+
for _, m := range i.appliedManifests {
515+
key := client.ObjectKey{
516+
Name: m.GetName(),
517+
Namespace: m.GetNamespace(),
518+
}
519+
if err := cl.Get(ctx, key, m); err != nil {
520+
errorList = append(errorList, fmt.Errorf("failed to get manifest %s: %w", m.GetName(), err))
521+
continue
522+
}
523+
524+
gvk, err := cl.GroupVersionKindFor(m)
525+
if err != nil {
526+
errorList = append(errorList, fmt.Errorf("failed to get GVK for manifest %s: %w", m.GetName(), err))
527+
continue
528+
}
529+
fileName := filepath.Join(CAPIArtifactsDir, fmt.Sprintf("%s-%s-%s.yaml", gvk.Kind, m.GetNamespace(), m.GetName()))
530+
objData, err := yaml.Marshal(m)
531+
if err != nil {
532+
errorList = append(errorList, fmt.Errorf("failed to marshal manifest %s: %w", fileName, err))
533+
continue
534+
}
535+
fileList = append(fileList, &asset.File{
536+
Filename: fileName,
537+
Data: objData,
538+
})
539+
}
540+
return fileList, errorList
541+
}

0 commit comments

Comments
 (0)