Skip to content

Commit 77a6bb5

Browse files
Merge pull request #7672 from vincepri/capi-manifests
CORS-2852: Introduce Cluster API Infrastructure manifest generation
2 parents 1ea1a54 + a437d1c commit 77a6bb5

File tree

50 files changed

+3924
-118
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+3924
-118
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ require (
5959
github.com/microsoftgraph/msgraph-sdk-go v0.47.0
6060
github.com/nutanix-cloud-native/prism-go-client v0.2.1-0.20220804130801-c8a253627c64
6161
github.com/onsi/gomega v1.28.1
62-
github.com/openshift/api v0.0.0-20231020115248-f404f2bc3524
62+
github.com/openshift/api v0.0.0-20231120145327-841b3aa7251d
6363
github.com/openshift/assisted-image-service v0.0.0-20230829160050-0b98ec74397b
6464
github.com/openshift/assisted-service/api v0.0.0
6565
github.com/openshift/assisted-service/client v0.0.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -954,8 +954,8 @@ github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xA
954954
github.com/openshift/api v0.0.0-20200326160804-ecb9283fe820/go.mod h1:RKMJ5CBnljLfnej+BJ/xnOWc3kZDvJUaIAEq2oKSPtE=
955955
github.com/openshift/api v0.0.0-20200827090112-c05698d102cf/go.mod h1:M3xexPhgM8DISzzRpuFUy+jfPjQPIcs9yqEYj17mXV8=
956956
github.com/openshift/api v0.0.0-20200829102639-8a3a835f1acf/go.mod h1:M3xexPhgM8DISzzRpuFUy+jfPjQPIcs9yqEYj17mXV8=
957-
github.com/openshift/api v0.0.0-20231020115248-f404f2bc3524 h1:+hOy0dbg/WIQ2TpBh+aWmoKTHYB82nSM8CfIZtjBmr8=
958-
github.com/openshift/api v0.0.0-20231020115248-f404f2bc3524/go.mod h1:qNtV0315F+f8ld52TLtPvrfivZpdimOzTi3kn9IVbtU=
957+
github.com/openshift/api v0.0.0-20231120145327-841b3aa7251d h1:8vowDTdM3QSfReuzk7L+66yguCySV8ayKkQX7uEpef4=
958+
github.com/openshift/api v0.0.0-20231120145327-841b3aa7251d/go.mod h1:qNtV0315F+f8ld52TLtPvrfivZpdimOzTi3kn9IVbtU=
959959
github.com/openshift/assisted-image-service v0.0.0-20230829160050-0b98ec74397b h1:wLVEgmzQjs3t4Z96gZzSLF/ws6ULliAks7z1lozNJrE=
960960
github.com/openshift/assisted-image-service v0.0.0-20230829160050-0b98ec74397b/go.mod h1:KTt/pnfs9gt0McDPrb0zVTkwd0xIFNik/ZJROIBzsbc=
961961
github.com/openshift/assisted-service/api v0.0.0-20230831114549-1922eda29cf8 h1:+fZLKbycDo4JeLwPGVSAgf2XPaJGLM341l9ZfrrlxG0=

pkg/asset/asset.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88

99
"github.com/pkg/errors"
1010
"github.com/sirupsen/logrus"
11+
"sigs.k8s.io/controller-runtime/pkg/client"
1112
)
1213

1314
const (
@@ -42,6 +43,16 @@ type WritableAsset interface {
4243
Load(FileFetcher) (found bool, err error)
4344
}
4445

46+
// WritableRuntimeAsset is a WriteableAsset that has files that can be written to disk,
47+
// in addition to a manifest file that contains the runtime object.
48+
type WritableRuntimeAsset interface {
49+
WritableAsset
50+
51+
// RuntimeFiles returns the manifest files along with their
52+
// instantiated runtime object.
53+
RuntimeFiles() []*RuntimeFile
54+
}
55+
4556
// File is a file for an Asset.
4657
type File struct {
4758
// Filename is the name of the file.
@@ -50,6 +61,13 @@ type File struct {
5061
Data []byte
5162
}
5263

64+
// RuntimeFile is a file that contains a manifest file and a runtime object.
65+
type RuntimeFile struct {
66+
File
67+
68+
Object client.Object `json:"-"`
69+
}
70+
5371
// PersistToFile writes all of the files of the specified asset into the specified
5472
// directory.
5573
func PersistToFile(asset WritableAsset, directory string) error {
@@ -107,3 +125,8 @@ func isDirEmpty(name string) (bool, error) {
107125
func SortFiles(files []*File) {
108126
sort.Slice(files, func(i, j int) bool { return files[i].Filename < files[j].Filename })
109127
}
128+
129+
// SortManifestFiles sorts the specified files by file name.
130+
func SortManifestFiles(files []*RuntimeFile) {
131+
sort.Slice(files, func(i, j int) bool { return files[i].Filename < files[j].Filename })
132+
}

pkg/asset/manifests/aws/cluster.go

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
package aws
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"time"
7+
8+
"github.com/pkg/errors"
9+
corev1 "k8s.io/api/core/v1"
10+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
11+
"k8s.io/utils/ptr"
12+
capa "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2"
13+
14+
"github.com/openshift/installer/pkg/asset"
15+
"github.com/openshift/installer/pkg/asset/installconfig"
16+
"github.com/openshift/installer/pkg/asset/manifests/capiutils"
17+
)
18+
19+
// GenerateClusterAssets generates the manifests for the cluster-api.
20+
func GenerateClusterAssets(installConfig *installconfig.InstallConfig, clusterID *installconfig.ClusterID) (*capiutils.GenerateClusterAssetsOutput, error) {
21+
manifests := []*asset.RuntimeFile{}
22+
mainCIDR := capiutils.CIDRFromInstallConfig(installConfig)
23+
24+
zones, err := installConfig.AWS.AvailabilityZones(context.TODO())
25+
if err != nil {
26+
return nil, errors.Wrap(err, "failed to get availability zones")
27+
}
28+
29+
awsCluster := &capa.AWSCluster{
30+
ObjectMeta: metav1.ObjectMeta{
31+
Name: clusterID.InfraID,
32+
Namespace: capiutils.Namespace,
33+
},
34+
Spec: capa.AWSClusterSpec{
35+
Region: installConfig.Config.AWS.Region,
36+
NetworkSpec: capa.NetworkSpec{
37+
VPC: capa.VPCSpec{
38+
CidrBlock: mainCIDR.String(),
39+
AvailabilityZoneUsageLimit: ptr.To(len(zones)),
40+
AvailabilityZoneSelection: &capa.AZSelectionSchemeOrdered,
41+
},
42+
CNI: &capa.CNISpec{
43+
CNIIngressRules: capa.CNIIngressRules{
44+
{
45+
Description: "ICMP",
46+
Protocol: capa.SecurityGroupProtocolICMP,
47+
FromPort: -1,
48+
ToPort: -1,
49+
},
50+
{
51+
Description: "Port 22 (TCP)",
52+
Protocol: capa.SecurityGroupProtocolTCP,
53+
FromPort: 22,
54+
ToPort: 22,
55+
},
56+
{
57+
Description: "Port 4789 (UDP) for VXLAN",
58+
Protocol: capa.SecurityGroupProtocolUDP,
59+
FromPort: 4789,
60+
ToPort: 4789,
61+
},
62+
{
63+
Description: "Port 6081 (UDP) for geneve",
64+
Protocol: capa.SecurityGroupProtocolUDP,
65+
FromPort: 6081,
66+
ToPort: 6081,
67+
},
68+
{
69+
Description: "Port 500 (UDP) for IKE",
70+
Protocol: capa.SecurityGroupProtocolUDP,
71+
FromPort: 500,
72+
ToPort: 500,
73+
},
74+
{
75+
Description: "Port 4500 (UDP) for IKE NAT",
76+
Protocol: capa.SecurityGroupProtocolUDP,
77+
FromPort: 4500,
78+
ToPort: 4500,
79+
},
80+
{
81+
Description: "ESP",
82+
Protocol: capa.SecurityGroupProtocolESP,
83+
FromPort: -1,
84+
ToPort: -1,
85+
},
86+
{
87+
Description: "Port 6441-6442 (TCP) for ovndb",
88+
Protocol: capa.SecurityGroupProtocolTCP,
89+
FromPort: 6441,
90+
ToPort: 6442,
91+
},
92+
{
93+
Description: "Port 9000-9999 for node ports (TCP)",
94+
Protocol: capa.SecurityGroupProtocolTCP,
95+
FromPort: 9000,
96+
ToPort: 9999,
97+
},
98+
{
99+
Description: "Port 9000-9999 for node ports (UDP)",
100+
Protocol: capa.SecurityGroupProtocolUDP,
101+
FromPort: 9000,
102+
ToPort: 9999,
103+
},
104+
{
105+
Description: "Service node ports (TCP)",
106+
Protocol: capa.SecurityGroupProtocolTCP,
107+
FromPort: 30000,
108+
ToPort: 32767,
109+
},
110+
{
111+
Description: "Service node ports (UDP)",
112+
Protocol: capa.SecurityGroupProtocolUDP,
113+
FromPort: 30000,
114+
ToPort: 32767,
115+
},
116+
},
117+
},
118+
AdditionalControlPlaneIngressRules: []capa.IngressRule{
119+
{
120+
Description: "MCS traffic from cluster network",
121+
Protocol: capa.SecurityGroupProtocolTCP,
122+
FromPort: 22623,
123+
ToPort: 22623,
124+
SourceSecurityGroupRoles: []capa.SecurityGroupRole{"node", "controlplane"},
125+
},
126+
{
127+
Description: "controller-manager",
128+
Protocol: capa.SecurityGroupProtocolTCP,
129+
FromPort: 10257,
130+
ToPort: 10257,
131+
SourceSecurityGroupRoles: []capa.SecurityGroupRole{"controlplane", "node"},
132+
},
133+
{
134+
Description: "kube-scheduler",
135+
Protocol: capa.SecurityGroupProtocolTCP,
136+
FromPort: 10259,
137+
ToPort: 10259,
138+
SourceSecurityGroupRoles: []capa.SecurityGroupRole{"controlplane", "node"},
139+
},
140+
{
141+
Description: "SSH everyone",
142+
Protocol: capa.SecurityGroupProtocolTCP,
143+
FromPort: 22,
144+
ToPort: 22,
145+
CidrBlocks: []string{"0.0.0.0/0"},
146+
},
147+
},
148+
},
149+
S3Bucket: &capa.S3Bucket{
150+
Name: fmt.Sprintf("openshift-bootstrap-data-%s", clusterID.InfraID),
151+
PresignedURLDuration: &metav1.Duration{Duration: 1 * time.Hour},
152+
},
153+
ControlPlaneLoadBalancer: &capa.AWSLoadBalancerSpec{
154+
Name: ptr.To(clusterID.InfraID + "-ext"),
155+
LoadBalancerType: capa.LoadBalancerTypeNLB,
156+
Scheme: &capa.ELBSchemeInternetFacing,
157+
AdditionalListeners: []capa.AdditionalListenerSpec{
158+
{
159+
Port: 22623,
160+
Protocol: capa.ELBProtocolTCP,
161+
},
162+
},
163+
},
164+
},
165+
}
166+
167+
// If the install config has subnets, use them.
168+
if len(installConfig.AWS.Subnets) > 0 {
169+
privateSubnets, err := installConfig.AWS.PrivateSubnets(context.TODO())
170+
if err != nil {
171+
return nil, errors.Wrap(err, "failed to get private subnets")
172+
}
173+
for _, subnet := range privateSubnets {
174+
awsCluster.Spec.NetworkSpec.Subnets = append(awsCluster.Spec.NetworkSpec.Subnets, capa.SubnetSpec{
175+
ID: subnet.ID,
176+
CidrBlock: subnet.CIDR,
177+
AvailabilityZone: subnet.Zone.Name,
178+
IsPublic: subnet.Public,
179+
})
180+
}
181+
publicSubnets, err := installConfig.AWS.PublicSubnets(context.TODO())
182+
if err != nil {
183+
return nil, errors.Wrap(err, "failed to get public subnets")
184+
}
185+
186+
for _, subnet := range publicSubnets {
187+
awsCluster.Spec.NetworkSpec.Subnets = append(awsCluster.Spec.NetworkSpec.Subnets, capa.SubnetSpec{
188+
ID: subnet.ID,
189+
CidrBlock: subnet.CIDR,
190+
AvailabilityZone: subnet.Zone.Name,
191+
IsPublic: subnet.Public,
192+
})
193+
}
194+
195+
vpc, err := installConfig.AWS.VPC(context.TODO())
196+
if err != nil {
197+
return nil, errors.Wrap(err, "failed to get VPC")
198+
}
199+
awsCluster.Spec.NetworkSpec.VPC = capa.VPCSpec{
200+
ID: vpc,
201+
}
202+
}
203+
204+
manifests = append(manifests, &asset.RuntimeFile{
205+
Object: awsCluster,
206+
File: asset.File{Filename: "02_infra-cluster.yaml"},
207+
})
208+
209+
id := &capa.AWSClusterControllerIdentity{
210+
ObjectMeta: metav1.ObjectMeta{
211+
Name: "default",
212+
Namespace: capiutils.Namespace,
213+
},
214+
Spec: capa.AWSClusterControllerIdentitySpec{
215+
AWSClusterIdentitySpec: capa.AWSClusterIdentitySpec{
216+
AllowedNamespaces: &capa.AllowedNamespaces{}, // Allow all namespaces.
217+
},
218+
},
219+
}
220+
manifests = append(manifests, &asset.RuntimeFile{
221+
Object: id,
222+
File: asset.File{Filename: "01_aws-cluster-controller-identity-default.yaml"},
223+
})
224+
225+
return &capiutils.GenerateClusterAssetsOutput{
226+
Manifests: manifests,
227+
InfrastructureRef: &corev1.ObjectReference{
228+
APIVersion: "infrastructure.cluster.x-k8s.io/v1beta2",
229+
Kind: "AWSCluster",
230+
Name: awsCluster.Name,
231+
Namespace: awsCluster.Namespace,
232+
},
233+
}, nil
234+
}

0 commit comments

Comments
 (0)