@@ -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
- "k8s.io/cloud-provider-aws/pkg/apis/config/v1alpha1"
37
+ awsconfigv1alpha1 "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.
@@ -77,9 +85,9 @@ type EC2Metadata interface {
77
85
GetMetadata (path string ) (string , error )
78
86
}
79
87
80
- func readAWSCloudConfig (config io.Reader ) (* v1alpha1 .AWSCloudConfig , error ) {
88
+ func readAWSCloudConfig (config io.Reader ) (* awsconfigv1alpha1 .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
@@ -88,19 +96,37 @@ func readAWSCloudConfig(config io.Reader) (*v1alpha1.AWSCloudConfig, error) {
88
96
return nil , fmt .Errorf ("unable to read cloud configuration from %q [%v]" , config , err )
89
97
}
90
98
91
- var cfg v1alpha1 .AWSCloudConfig
99
+ var cfg awsconfigv1alpha1 .AWSCloudConfig
92
100
err = yaml .Unmarshal (data , & cfg )
93
101
if err != nil {
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 * awsconfigv1alpha1.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 != awsconfigv1alpha1 .SchemeGroupVersion .String () {
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 len (config .Config .ClusterName ) == 0 {
124
+ allErrs = append (allErrs , field .Required (fieldPath .Child ("clusterName" ), "cluster name cannot be empty" ))
125
+ }
126
+
127
+ return allErrs
128
+ }
129
+
104
130
func getAvailabilityZone (metadata EC2Metadata ) (string , error ) {
105
131
return metadata .GetMetadata ("placement/availability-zone" )
106
132
}
@@ -122,7 +148,7 @@ func azToRegion(az string) (string, error) {
122
148
}
123
149
124
150
// newCloud creates a new instance of AWSCloud.
125
- func newCloud (cfg v1alpha1 .AWSCloudConfig ) (cloudprovider.Interface , error ) {
151
+ func newCloud (cfg * awsconfigv1alpha1 .AWSCloudConfig ) (cloudprovider.Interface , error ) {
126
152
sess , err := session .NewSession (& aws.Config {})
127
153
if err != nil {
128
154
return nil , fmt .Errorf ("unable to initialize AWS session: %v" , err )
@@ -152,11 +178,6 @@ func newCloud(cfg v1alpha1.AWSCloudConfig) (cloudprovider.Interface, error) {
152
178
return nil , err
153
179
}
154
180
155
- instances , err := newInstances (az , creds )
156
- if err != nil {
157
- return nil , err
158
- }
159
-
160
181
ec2Sess , err := session .NewSession (& aws.Config {
161
182
Region : aws .String (region ),
162
183
Credentials : creds ,
@@ -170,21 +191,29 @@ func newCloud(cfg v1alpha1.AWSCloudConfig) (cloudprovider.Interface, error) {
170
191
return nil , fmt .Errorf ("error creating AWS ec2 client: %q" , err )
171
192
}
172
193
173
- awsCloud := & cloud {
174
- creds : creds ,
175
- instances : instances ,
176
- region : region ,
177
- metadata : metadataClient ,
178
- ec2 : ec2Service ,
179
- }
180
-
194
+ var tags awsTagging
181
195
if cfg .Config .ClusterName != "" {
182
- if err := awsCloud .tagging .init (cfg .Config .ClusterName ); err != nil {
196
+ tags , err = newAWSTags (cfg .Config .ClusterName )
197
+ if err != nil {
183
198
return nil , err
184
199
}
200
+ } else {
201
+ klog .Warning ("misconfigured cluster: no clusterName" )
202
+ }
203
+
204
+ instances , err := newInstances (az , creds , tags )
205
+ if err != nil {
206
+ return nil , err
185
207
}
186
208
187
- return awsCloud , nil
209
+ return & cloud {
210
+ creds : creds ,
211
+ instances : instances ,
212
+ region : region ,
213
+ metadata : metadataClient ,
214
+ ec2 : ec2Service ,
215
+ tags : tags ,
216
+ }, nil
188
217
}
189
218
190
219
// Initialize passes a Kubernetes clientBuilder interface to the cloud provider
@@ -223,7 +252,7 @@ func (c *cloud) Routes() (cloudprovider.Routes, bool) {
223
252
224
253
// HasClusterID returns true if the cluster has a clusterID
225
254
func (c * cloud ) HasClusterID () bool {
226
- return len (c .tagging .clusterName ()) > 0
255
+ return len (c .tags .clusterName ()) > 0
227
256
}
228
257
229
258
// InstancesV2 is an implementation for instances and should only be implemented by external cloud providers.
0 commit comments