Skip to content

Commit 2d5dd7d

Browse files
Merge pull request #8157 from r4f4/capi-aws-copy-ami
CORS-3050: capi/aws: copy AMI to target region, if needed
2 parents 1b4dc65 + 3f5b53f commit 2d5dd7d

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package clusterapi
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"strings"
7+
8+
"github.com/aws/aws-sdk-go/aws"
9+
"github.com/aws/aws-sdk-go/service/ec2"
10+
"github.com/sirupsen/logrus"
11+
12+
"github.com/openshift/installer/pkg/asset/installconfig"
13+
)
14+
15+
// copyAMIToRegion copies the AMI to the region configured in the installConfig if needed.
16+
func copyAMIToRegion(ctx context.Context, installConfig *installconfig.InstallConfig, infraID, rhcosImage string) (string, error) {
17+
osImage := strings.SplitN(rhcosImage, ",", 2)
18+
amiID := osImage[0]
19+
amiRegion := installConfig.Config.AWS.Region
20+
if len(osImage) > 1 {
21+
amiRegion = osImage[1]
22+
}
23+
24+
// Already in target region, nothing to do
25+
if amiRegion == installConfig.Config.AWS.Region {
26+
return amiID, nil
27+
}
28+
29+
logrus.Infof("Copying AMI to region %s", installConfig.AWS.Region)
30+
31+
session, err := installConfig.AWS.Session(ctx)
32+
if err != nil {
33+
return "", fmt.Errorf("failed to get AWS session: %w", err)
34+
}
35+
client := ec2.New(session)
36+
37+
res, err := client.CopyImageWithContext(ctx, &ec2.CopyImageInput{
38+
Name: aws.String(fmt.Sprintf("%s-master", infraID)),
39+
ClientToken: aws.String(infraID),
40+
Description: aws.String("Created by Openshift Installer"),
41+
SourceImageId: aws.String(amiID),
42+
SourceRegion: aws.String(amiRegion),
43+
Encrypted: aws.Bool(true),
44+
})
45+
if err != nil {
46+
return "", err
47+
}
48+
49+
name := fmt.Sprintf("%s-ami-%s", infraID, installConfig.AWS.Region)
50+
amiTags := make([]*ec2.Tag, 0, len(installConfig.Config.AWS.UserTags)+4)
51+
for k, v := range installConfig.Config.AWS.UserTags {
52+
amiTags = append(amiTags, &ec2.Tag{
53+
Key: aws.String(k),
54+
Value: aws.String(v),
55+
})
56+
}
57+
for k, v := range map[string]string{
58+
"Name": name,
59+
"sourceAMI": amiID,
60+
"sourceRegion": amiRegion,
61+
fmt.Sprintf("kubernetes.io/cluster/%s", infraID): "owned",
62+
} {
63+
amiTags = append(amiTags, &ec2.Tag{
64+
Key: aws.String(k),
65+
Value: aws.String(v),
66+
})
67+
}
68+
69+
_, err = client.CreateTagsWithContext(ctx, &ec2.CreateTagsInput{
70+
Resources: []*string{res.ImageId},
71+
Tags: amiTags,
72+
})
73+
if err != nil {
74+
return "", fmt.Errorf("failed to tag AMI copy (%s): %w", name, err)
75+
}
76+
77+
return aws.StringValue(res.ImageId), nil
78+
}

pkg/infrastructure/aws/clusterapi/aws.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/aws/aws-sdk-go/aws/session"
99
"github.com/aws/aws-sdk-go/service/ec2"
1010
"github.com/sirupsen/logrus"
11+
"k8s.io/utils/ptr"
1112
capa "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2"
1213
k8sClient "sigs.k8s.io/controller-runtime/pkg/client"
1314

@@ -32,6 +33,16 @@ func (*Provider) PreProvision(ctx context.Context, in clusterapi.PreProvisionInp
3233
if err := createIAMRoles(ctx, in.InfraID, in.InstallConfig); err != nil {
3334
return fmt.Errorf("failed to create IAM roles: %w", err)
3435
}
36+
37+
amiID, err := copyAMIToRegion(ctx, in.InstallConfig, in.InfraID, string(*in.RhcosImage))
38+
if err != nil {
39+
return fmt.Errorf("failed to copy AMI: %w", err)
40+
}
41+
for i := range in.MachineManifests {
42+
if awsMachine, ok := in.MachineManifests[i].(*capa.AWSMachine); ok {
43+
awsMachine.Spec.AMI = capa.AMIReference{ID: ptr.To(amiID)}
44+
}
45+
}
3546
return nil
3647
}
3748

0 commit comments

Comments
 (0)