@@ -19,6 +19,7 @@ limitations under the License.
19
19
package v2
20
20
21
21
import (
22
+ "errors"
22
23
"fmt"
23
24
"io"
24
25
"io/ioutil"
@@ -31,8 +32,10 @@ import (
31
32
"github.com/aws/aws-sdk-go/aws/session"
32
33
"github.com/aws/aws-sdk-go/service/ec2"
33
34
35
+ "k8s.io/apimachinery/pkg/util/validation/field"
34
36
cloudprovider "k8s.io/cloud-provider"
35
37
"k8s.io/cloud-provider-aws/pkg/apis/config/v1alpha1"
38
+ "k8s.io/klog/v2"
36
39
"sigs.k8s.io/yaml"
37
40
)
38
41
@@ -43,7 +46,12 @@ func init() {
43
46
return nil , fmt .Errorf ("failed to read AWS cloud provider config file: %v" , err )
44
47
}
45
48
46
- return newCloud (* cfg )
49
+ errs := validateAWSCloudConfig (cfg )
50
+ if len (errs ) > 0 {
51
+ return nil , fmt .Errorf ("failed to validate AWS cloud config: %v" , errs .ToAggregate ())
52
+ }
53
+
54
+ return newCloud (cfg )
47
55
})
48
56
}
49
57
@@ -61,7 +69,7 @@ type cloud struct {
61
69
region string
62
70
ec2 EC2
63
71
metadata EC2Metadata
64
- tagging awsTagging
72
+ tags awsTagging
65
73
}
66
74
67
75
// EC2 is an interface defining only the methods we call from the AWS EC2 SDK.
@@ -79,7 +87,7 @@ type EC2Metadata interface {
79
87
80
88
func readAWSCloudConfig (config io.Reader ) (* v1alpha1.AWSCloudConfig , error ) {
81
89
if config == nil {
82
- return nil , fmt . Errorf ("no AWS cloud provider config file given" )
90
+ return nil , errors . New ("no AWS cloud provider config file given" )
83
91
}
84
92
85
93
// read the config file
@@ -94,13 +102,35 @@ func readAWSCloudConfig(config io.Reader) (*v1alpha1.AWSCloudConfig, error) {
94
102
// we got an error where the decode wasn't related to a missing type
95
103
return nil , err
96
104
}
97
- if cfg .Kind != "AWSCloudConfig" {
98
- return nil , fmt .Errorf ("invalid cloud configuration object %q" , cfg .Kind )
99
- }
100
105
101
106
return & cfg , nil
102
107
}
103
108
109
+ // validateAWSCloudConfig validates AWSCloudConfig
110
+ // clusterName is required
111
+ func validateAWSCloudConfig (config * v1alpha1.AWSCloudConfig ) field.ErrorList {
112
+ allErrs := field.ErrorList {}
113
+
114
+ if config .Kind != "AWSCloudConfig" {
115
+ allErrs = append (allErrs , field .Invalid (field .NewPath ("Kind" ), "invalid Kind for cloud config: %q" , config .Kind ))
116
+ }
117
+
118
+ if config .APIVersion != "config.aws.io/v1alpha1" {
119
+ allErrs = append (allErrs , field .Invalid (field .NewPath ("APIVersion" ), "invalid APIVersion for cloud config: %q" , config .APIVersion ))
120
+ }
121
+
122
+ fieldPath := field .NewPath ("Config" )
123
+ if config .Config == (v1alpha1.AWSConfig {}) {
124
+ allErrs = append (allErrs , field .Required (fieldPath , "Config is required, should not be empty" ))
125
+ }
126
+
127
+ if len (config .Config .ClusterName ) == 0 {
128
+ allErrs = append (allErrs , field .Required (fieldPath .Child ("ClusterName" ), "cluster name cannot be empty" ))
129
+ }
130
+
131
+ return allErrs
132
+ }
133
+
104
134
func getAvailabilityZone (metadata EC2Metadata ) (string , error ) {
105
135
return metadata .GetMetadata ("placement/availability-zone" )
106
136
}
@@ -122,7 +152,7 @@ func azToRegion(az string) (string, error) {
122
152
}
123
153
124
154
// newCloud creates a new instance of AWSCloud.
125
- func newCloud (cfg v1alpha1.AWSCloudConfig ) (cloudprovider.Interface , error ) {
155
+ func newCloud (cfg * v1alpha1.AWSCloudConfig ) (cloudprovider.Interface , error ) {
126
156
sess , err := session .NewSession (& aws.Config {})
127
157
if err != nil {
128
158
return nil , fmt .Errorf ("unable to initialize AWS session: %v" , err )
@@ -152,11 +182,6 @@ func newCloud(cfg v1alpha1.AWSCloudConfig) (cloudprovider.Interface, error) {
152
182
return nil , err
153
183
}
154
184
155
- instances , err := newInstances (az , creds )
156
- if err != nil {
157
- return nil , err
158
- }
159
-
160
185
ec2Sess , err := session .NewSession (& aws.Config {
161
186
Region : aws .String (region ),
162
187
Credentials : creds ,
@@ -170,21 +195,29 @@ func newCloud(cfg v1alpha1.AWSCloudConfig) (cloudprovider.Interface, error) {
170
195
return nil , fmt .Errorf ("error creating AWS ec2 client: %q" , err )
171
196
}
172
197
173
- awsCloud := & cloud {
174
- creds : creds ,
175
- instances : instances ,
176
- region : region ,
177
- metadata : metadataClient ,
178
- ec2 : ec2Service ,
179
- }
180
-
198
+ var tags awsTagging
181
199
if cfg .Config .ClusterName != "" {
182
- if err := awsCloud .tagging .init (cfg .Config .ClusterName ); err != nil {
200
+ tags , err = newAWSTags (cfg .Config .ClusterName )
201
+ if err != nil {
183
202
return nil , err
184
203
}
204
+ } else {
205
+ klog .Warning ("misconfigured cluster: no clusterName" )
185
206
}
186
207
187
- return awsCloud , nil
208
+ instances , err := newInstances (az , creds , tags )
209
+ if err != nil {
210
+ return nil , err
211
+ }
212
+
213
+ return & cloud {
214
+ creds : creds ,
215
+ instances : instances ,
216
+ region : region ,
217
+ metadata : metadataClient ,
218
+ ec2 : ec2Service ,
219
+ tags : tags ,
220
+ }, nil
188
221
}
189
222
190
223
// Initialize passes a Kubernetes clientBuilder interface to the cloud provider
@@ -223,7 +256,7 @@ func (c *cloud) Routes() (cloudprovider.Routes, bool) {
223
256
224
257
// HasClusterID returns true if the cluster has a clusterID
225
258
func (c * cloud ) HasClusterID () bool {
226
- return len (c .tagging .clusterName ()) > 0
259
+ return len (c .tags .clusterName ()) > 0
227
260
}
228
261
229
262
// InstancesV2 is an implementation for instances and should only be implemented by external cloud providers.
0 commit comments