@@ -19,17 +19,16 @@ package network
19
19
import (
20
20
"fmt"
21
21
22
- kerrors "k8s.io/apimachinery/pkg/util/errors"
23
- "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services"
24
- "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/wait"
25
-
26
22
"github.com/aws/aws-sdk-go/aws"
27
23
"github.com/aws/aws-sdk-go/service/ec2"
28
24
"github.com/pkg/errors"
25
+ kerrors "k8s.io/apimachinery/pkg/util/errors"
29
26
infrav1 "sigs.k8s.io/cluster-api-provider-aws/api/v1alpha4"
30
27
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/awserrors"
31
28
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/converters"
32
29
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/filter"
30
+ "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services"
31
+ "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/wait"
33
32
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/tags"
34
33
"sigs.k8s.io/cluster-api-provider-aws/pkg/record"
35
34
clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha4"
@@ -43,55 +42,55 @@ const (
43
42
func (s * Service ) reconcileVPC () error {
44
43
s .scope .V (2 ).Info ("Reconciling VPC" )
45
44
46
- vpc , err := s .describeVPC ()
47
- if awserrors .IsNotFound (err ) { // nolint:nestif
48
- // Create a new managed vpc.
49
- if ! conditions .Has (s .scope .InfraCluster (), infrav1 .VpcReadyCondition ) {
50
- conditions .MarkFalse (s .scope .InfraCluster (), infrav1 .VpcReadyCondition , infrav1 .VpcCreationStartedReason , clusterv1 .ConditionSeverityInfo , "" )
45
+ // If the ID is not nil, VPC is either managed or unmanaged but should exist in the AWS.
46
+ if s .scope .VPC ().ID != "" {
47
+ vpc , err := s .describeVPCByID ()
48
+ if err != nil {
49
+ return errors .Wrap (err , ".spec.vpc.id is set but VPC resource is missing in AWS; failed to describe VPC resources. (might be in creation process)" )
50
+ }
51
+
52
+ s .scope .VPC ().CidrBlock = vpc .CidrBlock
53
+ s .scope .VPC ().Tags = vpc .Tags
54
+
55
+ // If VPC is unmanaged, return early.
56
+ if vpc .IsUnmanaged (s .scope .Name ()) {
57
+ s .scope .V (2 ).Info ("Working on unmanaged VPC" , "vpc-id" , vpc .ID )
51
58
if err := s .scope .PatchObject (); err != nil {
52
- return errors .Wrap (err , "failed to patch conditions " )
59
+ return errors .Wrap (err , "failed to patch unmanaged VPC fields " )
53
60
}
61
+ record .Eventf (s .scope .InfraCluster (), "SuccessfulSetVPCAttributes" , "Set managed VPC attributes for %q" , vpc .ID )
62
+ return nil
54
63
}
55
- vpc , err = s .createVPC ()
56
- if err != nil {
57
- return errors .Wrap (err , "failed to create new vpc" )
58
- }
59
- } else if err != nil {
60
- return errors .Wrap (err , "failed to describe VPCs" )
61
- }
62
64
63
- // This function creates a new infrav1.VPCSpec, populates it with data from AWS, and then deep copies into the
64
- // AWSCluster's VPC spec (see the DeepCopyInto lines below). This is potentially problematic, as it completely
65
- // overwrites the data for the VPC spec as retrieved from the apiserver. This is a temporary band-aid to restore
66
- // recently-added fields that descripe user intent and do not come from AWS resource descriptions.
67
- //
68
- // FIXME(ncdc): rather than copying these values from the scope to vpc, find a better way to merge AWS information
69
- // with data in the scope retrieved from the apiserver. Could use something like mergo.
70
- //
71
- // NOTE: it may look like we are losing InternetGatewayID because it's not populated by describeVPC/createVPC or
72
- // restored here, but that's ok. It is restored by reconcileInternetGateways, which is invoked after this.
73
- vpc .AvailabilityZoneSelection = s .scope .VPC ().AvailabilityZoneSelection
74
- vpc .AvailabilityZoneUsageLimit = s .scope .VPC ().AvailabilityZoneUsageLimit
65
+ // if the VPC is managed, make managed sure attributes are configured.
66
+ if err := wait .WaitForWithRetryable (wait .NewBackoff (), func () (bool , error ) {
67
+ if err := s .ensureManagedVPCAttributes (vpc ); err != nil {
68
+ return false , err
69
+ }
70
+ return true , nil
71
+ }, awserrors .VPCNotFound ); err != nil {
72
+ return errors .Wrapf (err , "failed to to set vpc attributes for %q" , vpc .ID )
73
+ }
75
74
76
- if vpc .IsUnmanaged (s .scope .Name ()) {
77
- vpc .DeepCopyInto (s .scope .VPC ())
78
- s .scope .V (2 ).Info ("Working on unmanaged VPC" , "vpc-id" , vpc .ID )
79
75
return nil
80
76
}
81
77
82
- // Make sure attributes are configured
83
- if err := wait .WaitForWithRetryable (wait .NewBackoff (), func () (bool , error ) {
84
- buildParams := s .getVPCTagParams (vpc .ID )
85
- tagsBuilder := tags .New (& buildParams , tags .WithEC2 (s .EC2Client ))
86
- if err := tagsBuilder .Ensure (vpc .Tags ); err != nil {
87
- return false , err
78
+ // .spec.vpc.id is nil, Create a new managed vpc.
79
+ if ! conditions .Has (s .scope .InfraCluster (), infrav1 .VpcReadyCondition ) {
80
+ conditions .MarkFalse (s .scope .InfraCluster (), infrav1 .VpcReadyCondition , infrav1 .VpcCreationStartedReason , clusterv1 .ConditionSeverityInfo , "" )
81
+ if err := s .scope .PatchObject (); err != nil {
82
+ return errors .Wrap (err , "failed to patch conditions" )
88
83
}
89
- return true , nil
90
- }, awserrors . VPCNotFound ); err != nil {
91
- record . Warnf ( s . scope . InfraCluster (), "FailedTagVPC" , "Failed to tag managed VPC %q: %v" , vpc . ID , err )
92
- return errors .Wrapf (err , "failed to tag vpc %q" , vpc . ID )
84
+ }
85
+ vpc , err := s . createVPC ()
86
+ if err != nil {
87
+ return errors .Wrap (err , "failed to create new vpc" )
93
88
}
94
89
90
+ s .scope .VPC ().CidrBlock = vpc .CidrBlock
91
+ s .scope .VPC ().Tags = vpc .Tags
92
+ s .scope .VPC ().ID = vpc .ID
93
+
95
94
// Make sure attributes are configured
96
95
if err := wait .WaitForWithRetryable (wait .NewBackoff (), func () (bool , error ) {
97
96
if err := s .ensureManagedVPCAttributes (vpc ); err != nil {
@@ -102,8 +101,6 @@ func (s *Service) reconcileVPC() error {
102
101
return errors .Wrapf (err , "failed to to set vpc attributes for %q" , vpc .ID )
103
102
}
104
103
105
- vpc .DeepCopyInto (s .scope .VPC ())
106
- s .scope .V (2 ).Info ("Working on managed VPC" , "vpc-id" , vpc .ID )
107
104
return nil
108
105
}
109
106
@@ -165,10 +162,6 @@ func (s *Service) ensureManagedVPCAttributes(vpc *infrav1.VPCSpec) error {
165
162
}
166
163
167
164
func (s * Service ) createVPC () (* infrav1.VPCSpec , error ) {
168
- if s .scope .VPC ().IsUnmanaged (s .scope .Name ()) {
169
- return nil , errors .Errorf ("cannot create a managed vpc in unmanaged mode" )
170
- }
171
-
172
165
if s .scope .VPC ().CidrBlock == "" {
173
166
s .scope .VPC ().CidrBlock = defaultVPCCidr
174
167
}
@@ -189,15 +182,6 @@ func (s *Service) createVPC() (*infrav1.VPCSpec, error) {
189
182
record .Eventf (s .scope .InfraCluster (), "SuccessfulCreateVPC" , "Created new managed VPC %q" , * out .Vpc .VpcId )
190
183
s .scope .V (2 ).Info ("Created new VPC with cidr" , "vpc-id" , * out .Vpc .VpcId , "cidr-block" , * out .Vpc .CidrBlock )
191
184
192
- // TODO: we should attempt to record the VPC ID as soon as possible by setting s.scope.VPC().ID
193
- // however, the logic used for determining managed vs unmanaged VPCs relies on the tags and will
194
- // need to be updated to accommodate for the recording of the VPC ID prior to the tagging.
195
-
196
- wReq := & ec2.DescribeVpcsInput {VpcIds : []* string {out .Vpc .VpcId }}
197
- if err := s .EC2Client .WaitUntilVpcAvailable (wReq ); err != nil {
198
- return nil , errors .Wrapf (err , "failed to wait for vpc %q" , * out .Vpc .VpcId )
199
- }
200
-
201
185
return & infrav1.VPCSpec {
202
186
ID : * out .Vpc .VpcId ,
203
187
CidrBlock : * out .Vpc .CidrBlock ,
@@ -232,19 +216,18 @@ func (s *Service) deleteVPC() error {
232
216
return nil
233
217
}
234
218
235
- func (s * Service ) describeVPC () (* infrav1.VPCSpec , error ) {
219
+ func (s * Service ) describeVPCByID () (* infrav1.VPCSpec , error ) {
220
+ if s .scope .VPC ().ID == "" {
221
+ return nil , errors .New ("VPC ID is not set, failed to describe VPCs by ID" )
222
+ }
223
+
236
224
input := & ec2.DescribeVpcsInput {
237
225
Filters : []* ec2.Filter {
238
226
filter .EC2 .VPCStates (ec2 .VpcStatePending , ec2 .VpcStateAvailable ),
239
227
},
240
228
}
241
229
242
- if s .scope .VPC ().ID == "" {
243
- // Try to find a previously created and tagged VPC
244
- input .Filters = append (input .Filters , filter .EC2 .Cluster (s .scope .Name ()))
245
- } else {
246
- input .VpcIds = []* string {aws .String (s .scope .VPC ().ID )}
247
- }
230
+ input .VpcIds = []* string {aws .String (s .scope .VPC ().ID )}
248
231
249
232
out , err := s .EC2Client .DescribeVpcs (input )
250
233
if err != nil {
0 commit comments