Skip to content

Commit f2ab021

Browse files
Merge pull request #8255 from jhixson74/master_cap_ignite_bootstrap
CORS-3269: Azure CAPI Ignite Bootstrap
2 parents d27a7bd + b53042d commit f2ab021

File tree

2 files changed

+130
-7
lines changed

2 files changed

+130
-7
lines changed

pkg/infrastructure/azure/azure.go

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
capz "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1"
2222
"sigs.k8s.io/controller-runtime/pkg/client"
2323

24+
"github.com/openshift/installer/pkg/asset/ignition/bootstrap"
2425
"github.com/openshift/installer/pkg/asset/manifests/capiutils"
2526
"github.com/openshift/installer/pkg/infrastructure/clusterapi"
2627
"github.com/openshift/installer/pkg/rhcos"
@@ -43,6 +44,7 @@ type Provider struct {
4344
var _ clusterapi.PreProvider = (*Provider)(nil)
4445
var _ clusterapi.InfraReadyProvider = (*Provider)(nil)
4546
var _ clusterapi.PostProvider = (*Provider)(nil)
47+
var _ clusterapi.IgnitionProvider = (*Provider)(nil)
4648

4749
// Name returns the name of the provider.
4850
func (p *Provider) Name() string {
@@ -69,6 +71,7 @@ func (p *Provider) PreProvision(ctx context.Context, in clusterapi.PreProvisionI
6971
for k, v := range userTags {
7072
tags[k] = ptr.To(v)
7173
}
74+
p.Tags = tags
7275

7376
// Create resource group
7477
resourcesClientFactory, err := armresources.NewClientFactory(
@@ -98,9 +101,7 @@ func (p *Provider) PreProvision(ctx context.Context, in clusterapi.PreProvisionI
98101
return fmt.Errorf("error creating resource group %s: %w", resourceGroupName, err)
99102
}
100103
logrus.Debugf("ResourceGroup.ID=%s", *resourceGroup.ID)
101-
102104
p.ResourceGroupName = resourceGroupName
103-
p.Tags = tags
104105

105106
return nil
106107
}
@@ -116,9 +117,8 @@ func (p *Provider) InfraReady(ctx context.Context, in clusterapi.InfraReadyInput
116117
platform := installConfig.Platform.Azure
117118
subscriptionID := session.Credentials.SubscriptionID
118119
cloudConfiguration := session.CloudConfig
119-
resourceGroupName := p.ResourceGroupName
120-
tags := p.Tags
121120

121+
resourceGroupName := p.ResourceGroupName
122122
storageAccountName := fmt.Sprintf("cluster%s", randomString(5))
123123
containerName := "vhd"
124124
blobName := fmt.Sprintf("rhcos%s.vhd", randomString(5))
@@ -155,6 +155,13 @@ func (p *Provider) InfraReady(ctx context.Context, in clusterapi.InfraReadyInput
155155
return fmt.Errorf("image length is not alisnged on a 512 byte boundary")
156156
}
157157

158+
userTags := platform.UserTags
159+
tags := make(map[string]*string, len(userTags)+1)
160+
tags[fmt.Sprintf("kubernetes.io_cluster.%s", in.InfraID)] = ptr.To("owned")
161+
for k, v := range userTags {
162+
tags[k] = ptr.To(v)
163+
}
164+
158165
tokenCredential := session.TokenCreds
159166
storageURL := fmt.Sprintf("https://%s.blob.core.windows.net", storageAccountName)
160167
blobURL := fmt.Sprintf("%s/%s/%s", storageURL, containerName, blobName)
@@ -471,3 +478,53 @@ func randomString(length int) string {
471478

472479
return string(s)
473480
}
481+
482+
// Ignition provisions the Azure container that holds the bootstrap ignition
483+
// file.
484+
func (p Provider) Ignition(ctx context.Context, in clusterapi.IgnitionInput) ([]byte, error) {
485+
session, err := in.InstallConfig.Azure.Session()
486+
if err != nil {
487+
return nil, fmt.Errorf("failed to get session: %w", err)
488+
}
489+
490+
bootstrapIgnData := in.BootstrapIgnData
491+
subscriptionID := session.Credentials.SubscriptionID
492+
cloudConfiguration := session.CloudConfig
493+
494+
ignitionContainerName := "ignition"
495+
blobName := "bootstrap.ign"
496+
blobURL := fmt.Sprintf("%s/%s/%s", p.StorageURL, ignitionContainerName, blobName)
497+
498+
// Create ignition blob storage container
499+
createBlobContainerOutput, err := CreateBlobContainer(ctx, &CreateBlobContainerInput{
500+
ContainerName: ignitionContainerName,
501+
SubscriptionID: subscriptionID,
502+
ResourceGroupName: p.ResourceGroupName,
503+
StorageAccountName: p.StorageAccountName,
504+
StorageClientFactory: p.StorageClientFactory,
505+
})
506+
if err != nil {
507+
return nil, err
508+
}
509+
510+
blobIgnitionContainer := createBlobContainerOutput.BlobContainer
511+
logrus.Debugf("BlobIgnitionContainer.ID=%s", *blobIgnitionContainer.ID)
512+
513+
sasURL, err := CreateBlockBlob(ctx, &CreateBlockBlobInput{
514+
StorageURL: p.StorageURL,
515+
BlobURL: blobURL,
516+
StorageAccountName: p.StorageAccountName,
517+
StorageAccountKeys: p.StorageAccountKeys,
518+
CloudConfiguration: cloudConfiguration,
519+
BootstrapIgnData: bootstrapIgnData,
520+
})
521+
if err != nil {
522+
return nil, err
523+
}
524+
ignShim, err := bootstrap.GenerateIgnitionShimWithCertBundleAndProxy(sasURL, in.InstallConfig.Config.AdditionalTrustBundle, in.InstallConfig.Config.Proxy)
525+
if err != nil {
526+
return nil, fmt.Errorf("failed to create ignition shim: %w", err)
527+
}
528+
529+
return ignShim, nil
530+
}

pkg/infrastructure/azure/storage.go

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
package azure
22

33
import (
4+
"bytes"
45
"context"
56
"fmt"
67
"sync"
8+
"time"
79

810
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
911
"github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
1012
"github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
1113
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
14+
"github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming"
1215
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
1316
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage"
1417
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
18+
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob"
19+
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blockblob"
1520
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/pageblob"
21+
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/sas"
1622
"github.com/sirupsen/logrus"
1723

1824
aztypes "github.com/openshift/installer/pkg/types/azure"
@@ -181,15 +187,15 @@ type CreatePageBlobOutput struct {
181187

182188
// CreatePageBlob creates a blob and uploads a file from a URL to it.
183189
func CreatePageBlob(ctx context.Context, in *CreatePageBlobInput) (*CreatePageBlobOutput, error) {
184-
logrus.Debugf("Getting blob credentials")
190+
logrus.Debugf("Getting page blob credentials")
185191

186192
// XXX: Should try all of them until one is successful
187193
sharedKeyCredential, err := azblob.NewSharedKeyCredential(in.StorageAccountName, *in.StorageAccountKeys[0].Value)
188194
if err != nil {
189-
return nil, fmt.Errorf("failed to get shared crdentials for storage account: %w", err)
195+
return nil, fmt.Errorf("failed to get shared credentials for storage account: %w", err)
190196
}
191197

192-
logrus.Debugf("Getting blob client")
198+
logrus.Debugf("Getting page blob client")
193199
pageBlobClient, err := pageblob.NewClientWithSharedKeyCredential(
194200
in.BlobURL,
195201
sharedKeyCredential,
@@ -318,3 +324,63 @@ func doUploadPagesFromURL(ctx context.Context, pageBlobClient *pageblob.Client,
318324
logrus.Debugf("Done uploading")
319325
return res
320326
}
327+
328+
// CreateBlockBlobInput containers the input parameters used for creating a
329+
// block blob.
330+
type CreateBlockBlobInput struct {
331+
StorageURL string
332+
BlobURL string
333+
StorageAccountName string
334+
BootstrapIgnData []byte
335+
StorageAccountKeys []armstorage.AccountKey
336+
CloudConfiguration cloud.Configuration
337+
}
338+
339+
// CreateBlockBlobOutput contains the return values after creating a block
340+
// blob.
341+
type CreateBlockBlobOutput struct {
342+
PageBlobClient *pageblob.Client
343+
SharedKeyCredential *azblob.SharedKeyCredential
344+
}
345+
346+
// CreateBlockBlob creates a block blob and uploads a file from a URL to it.
347+
func CreateBlockBlob(ctx context.Context, in *CreateBlockBlobInput) (string, error) {
348+
logrus.Debugf("Getting block blob credentials")
349+
350+
// XXX: Should try all of them until one is successful
351+
sharedKeyCredential, err := azblob.NewSharedKeyCredential(in.StorageAccountName, *in.StorageAccountKeys[0].Value)
352+
if err != nil {
353+
return "", fmt.Errorf("failed to get shared crdentials for storage account: %w", err)
354+
}
355+
356+
logrus.Debugf("Getting block blob client")
357+
blockBlobClient, err := blockblob.NewClientWithSharedKeyCredential(
358+
in.BlobURL,
359+
sharedKeyCredential,
360+
&blockblob.ClientOptions{
361+
ClientOptions: azcore.ClientOptions{
362+
Cloud: in.CloudConfiguration,
363+
},
364+
},
365+
)
366+
if err != nil {
367+
return "", fmt.Errorf("failed to get page blob client: %w", err)
368+
}
369+
370+
logrus.Debugf("Creating block blob")
371+
372+
accessTier := blob.AccessTierHot
373+
_, err = blockBlobClient.Upload(ctx, streaming.NopCloser(bytes.NewReader(in.BootstrapIgnData)), &blockblob.UploadOptions{
374+
Tier: &accessTier,
375+
})
376+
if err != nil {
377+
return "", fmt.Errorf("failed to create block blob: %w", err)
378+
}
379+
380+
sasURL, err := blockBlobClient.GetSASURL(sas.BlobPermissions{Read: true}, time.Now().Add(time.Minute*60), &blob.GetSASURLOptions{})
381+
if err != nil {
382+
return "", fmt.Errorf("failed to get SAS URL: %w", err)
383+
}
384+
385+
return sasURL, nil
386+
}

0 commit comments

Comments
 (0)