Skip to content

Commit 42c3beb

Browse files
committed
tags: initial implementation of tags
1 parent b4c79df commit 42c3beb

File tree

3 files changed

+72
-63
lines changed

3 files changed

+72
-63
lines changed

Diff for: pkg/providers/v2/cloud.go

+18-16
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ limitations under the License.
1919
package v2
2020

2121
import (
22+
"errors"
2223
"fmt"
2324
"io"
2425
"io/ioutil"
@@ -43,7 +44,7 @@ func init() {
4344
return nil, fmt.Errorf("failed to read AWS cloud provider config file: %v", err)
4445
}
4546

46-
return newCloud(*cfg)
47+
return newCloud(cfg)
4748
})
4849
}
4950

@@ -61,7 +62,7 @@ type cloud struct {
6162
region string
6263
ec2 EC2
6364
metadata EC2Metadata
64-
tagging awsTagging
65+
tags awsTagging
6566
}
6667

6768
// EC2 is an interface defining only the methods we call from the AWS EC2 SDK.
@@ -79,7 +80,7 @@ type EC2Metadata interface {
7980

8081
func readAWSCloudConfig(config io.Reader) (*v1alpha1.AWSCloudConfig, error) {
8182
if config == nil {
82-
return nil, fmt.Errorf("no AWS cloud provider config file given")
83+
return nil, errors.New("no AWS cloud provider config file given")
8384
}
8485

8586
// read the config file
@@ -95,7 +96,7 @@ func readAWSCloudConfig(config io.Reader) (*v1alpha1.AWSCloudConfig, error) {
9596
return nil, err
9697
}
9798
if cfg.Kind != "AWSCloudConfig" {
98-
return nil, fmt.Errorf("invalid cloud configuration object %q", cfg.Kind)
99+
return nil, fmt.Errorf("invalid Kind for cloud config: %q", cfg.Kind)
99100
}
100101

101102
return &cfg, nil
@@ -122,7 +123,7 @@ func azToRegion(az string) (string, error) {
122123
}
123124

124125
// newCloud creates a new instance of AWSCloud.
125-
func newCloud(cfg v1alpha1.AWSCloudConfig) (cloudprovider.Interface, error) {
126+
func newCloud(cfg *v1alpha1.AWSCloudConfig) (cloudprovider.Interface, error) {
126127
sess, err := session.NewSession(&aws.Config{})
127128
if err != nil {
128129
return nil, fmt.Errorf("unable to initialize AWS session: %v", err)
@@ -170,21 +171,22 @@ func newCloud(cfg v1alpha1.AWSCloudConfig) (cloudprovider.Interface, error) {
170171
return nil, fmt.Errorf("error creating AWS ec2 client: %q", err)
171172
}
172173

173-
awsCloud := &cloud{
174-
creds: creds,
175-
instances: instances,
176-
region: region,
177-
metadata: metadataClient,
178-
ec2: ec2Service,
179-
}
180-
174+
var tags awsTagging
181175
if cfg.Config.ClusterName != "" {
182-
if err := awsCloud.tagging.init(cfg.Config.ClusterName); err != nil {
176+
tags, err = newAWSTags(cfg.Config.ClusterName)
177+
if err != nil {
183178
return nil, err
184179
}
185180
}
186181

187-
return awsCloud, nil
182+
return &cloud{
183+
creds: creds,
184+
instances: instances,
185+
region: region,
186+
metadata: metadataClient,
187+
ec2: ec2Service,
188+
tags: tags,
189+
}, nil
188190
}
189191

190192
// Initialize passes a Kubernetes clientBuilder interface to the cloud provider
@@ -223,7 +225,7 @@ func (c *cloud) Routes() (cloudprovider.Routes, bool) {
223225

224226
// HasClusterID returns true if the cluster has a clusterID
225227
func (c *cloud) HasClusterID() bool {
226-
return len(c.tagging.clusterName()) > 0
228+
return len(c.tags.clusterName()) > 0
227229
}
228230

229231
// InstancesV2 is an implementation for instances and should only be implemented by external cloud providers.

Diff for: pkg/providers/v2/tags.go

+26-38
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ limitations under the License.
1616
package v2
1717

1818
import (
19+
"errors"
1920
"fmt"
2021
"strings"
2122
"time"
@@ -30,7 +31,9 @@ import (
3031
const (
3132
// TagNameKubernetesClusterPrefix is the tag name we use to differentiate multiple
3233
// logically independent clusters running in the same AZ.
33-
// tag format: kubernetes.io/cluster/=<clusterName>
34+
// tag format: kubernetes.io/cluster/<clusterID> = shared|owned
35+
// The tag key = TagNameKubernetesClusterPrefix + clusterID
36+
// The tag value is an ownership value
3437
TagNameKubernetesClusterPrefix = "kubernetes.io/cluster/"
3538

3639
// createTag* is configuration of exponential backoff for CreateTag call. We
@@ -49,6 +52,19 @@ type awsTagging struct {
4952
ClusterName string
5053
}
5154

55+
// newAWSTags is a constructor function for awsTagging
56+
func newAWSTags(clusterName string) (awsTagging, error) {
57+
if clusterName != "" {
58+
klog.Infof("AWS cloud filtering on ClusterName: %v", clusterName)
59+
} else {
60+
return awsTagging{}, errors.New("AWS cloud failed to find ClusterName")
61+
}
62+
63+
return awsTagging{
64+
ClusterName: clusterName,
65+
}, nil
66+
}
67+
5268
// Extracts the cluster name from the given tags, if they are present
5369
// If duplicate tags are found, returns an error
5470
func findClusterName(tags []*ec2.Tag) (string, error) {
@@ -57,7 +73,7 @@ func findClusterName(tags []*ec2.Tag) (string, error) {
5773
for _, tag := range tags {
5874
tagKey := aws.StringValue(tag.Key)
5975
if strings.HasPrefix(tagKey, TagNameKubernetesClusterPrefix) {
60-
name := aws.StringValue(tag.Value)
76+
name := strings.TrimPrefix(tagKey, TagNameKubernetesClusterPrefix)
6177
if clusterName != "" {
6278
return "", fmt.Errorf("Found multiple cluster tags with prefix %s (%q and %q)", TagNameKubernetesClusterPrefix, clusterName, name)
6379
}
@@ -68,48 +84,19 @@ func findClusterName(tags []*ec2.Tag) (string, error) {
6884
return clusterName, nil
6985
}
7086

71-
func (t *awsTagging) init(clusterName string) error {
72-
t.ClusterName = clusterName
73-
74-
if clusterName != "" {
75-
klog.Infof("AWS cloud filtering on ClusterName: %v", clusterName)
76-
} else {
77-
return fmt.Errorf("AWS cloud failed to find ClusterName")
78-
}
79-
80-
return nil
81-
}
82-
83-
// Extracts a cluster name from the given tags, if one is present
84-
// If no clusterName is found, returns "", nil
85-
// If multiple (different) clusterNames are found, returns an error
86-
func (t *awsTagging) initFromTags(tags []*ec2.Tag) error {
87-
clusterName, err := findClusterName(tags)
88-
if err != nil {
89-
return err
90-
}
91-
92-
if clusterName == "" {
93-
klog.Errorf("Tag %q not found; Kubernetes may behave unexpectedly.", TagNameKubernetesClusterPrefix)
94-
}
95-
96-
return t.init(clusterName)
97-
}
98-
99-
func (t *awsTagging) hasClusterTag(tags []*ec2.Tag) bool {
100-
// if the clusterName is not configured -- we consider all instances.
87+
func (t *awsTagging) hasClusterTag(tags []*ec2.Tag) error {
10188
if len(t.ClusterName) == 0 {
102-
return true
89+
return errors.New("cluster name is not configured (an empty value)")
10390
}
10491

10592
for _, tag := range tags {
10693
tagKey := aws.StringValue(tag.Key)
107-
if (tagKey == TagNameKubernetesClusterPrefix) && (aws.StringValue(tag.Value) == t.ClusterName) {
108-
return true
94+
if tagKey == (TagNameKubernetesClusterPrefix + t.ClusterName) {
95+
return nil
10996
}
11097
}
11198

112-
return false
99+
return errors.New("cluster tag does not exist")
113100
}
114101

115102
func (t *awsTagging) buildTags(additionalTags map[string]string, lifecycle string) map[string]string {
@@ -124,8 +111,9 @@ func (t *awsTagging) buildTags(additionalTags map[string]string, lifecycle strin
124111
return tags
125112
}
126113

127-
// tag format: kubernetes.io/cluster/=<clusterName>
128-
tags[TagNameKubernetesClusterPrefix] = t.ClusterName
114+
// tag format: kubernetes.io/cluster/<clusterID> = shared|owned
115+
tagKey := TagNameKubernetesClusterPrefix + t.ClusterName
116+
tags[tagKey] = lifecycle
129117

130118
return tags
131119
}

Diff for: pkg/providers/v2/tags_test.go

+28-9
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import (
2323
)
2424

2525
func TestFindClusterName(t *testing.T) {
26-
grid := []struct {
26+
testCases := []struct {
2727
Tags map[string]string
2828
ExpectedClusterName string
2929
ExpectError bool
@@ -33,7 +33,19 @@ func TestFindClusterName(t *testing.T) {
3333
},
3434
{
3535
Tags: map[string]string{
36-
TagNameKubernetesClusterPrefix: TestClusterID,
36+
TagNameKubernetesClusterPrefix + TestClusterID: "owned",
37+
},
38+
ExpectedClusterName: TestClusterID,
39+
},
40+
{
41+
Tags: map[string]string{
42+
TagNameKubernetesClusterPrefix + TestClusterID: "shared",
43+
},
44+
ExpectedClusterName: TestClusterID,
45+
},
46+
{
47+
Tags: map[string]string{
48+
TagNameKubernetesClusterPrefix + TestClusterID: "",
3749
},
3850
ExpectedClusterName: TestClusterID,
3951
},
@@ -43,26 +55,33 @@ func TestFindClusterName(t *testing.T) {
4355
},
4456
ExpectedClusterName: "",
4557
},
58+
{
59+
Tags: map[string]string{
60+
TagNameKubernetesClusterPrefix + "a": "",
61+
TagNameKubernetesClusterPrefix + "b": "",
62+
},
63+
ExpectError: true,
64+
},
4665
}
47-
for _, g := range grid {
66+
for _, testCase := range testCases {
4867
var ec2Tags []*ec2.Tag
49-
for k, v := range g.Tags {
68+
for k, v := range testCase.Tags {
5069
ec2Tags = append(ec2Tags, &ec2.Tag{Key: aws.String(k), Value: aws.String(v)})
5170
}
5271
clusterName, err := findClusterName(ec2Tags)
53-
if g.ExpectError {
72+
if testCase.ExpectError {
5473
if err == nil {
55-
t.Errorf("expected error for tags %v", g.Tags)
74+
t.Errorf("expected error for tags %v", testCase.Tags)
5675
continue
5776
}
5877
} else {
5978
if err != nil {
60-
t.Errorf("unexpected error for tags %v: %v", g.Tags, err)
79+
t.Errorf("unexpected error for tags %v: %v", testCase.Tags, err)
6180
continue
6281
}
6382

64-
if g.ExpectedClusterName != clusterName {
65-
t.Errorf("unexpected new clusterName for tags %v: %s vs %s", g.Tags, g.ExpectedClusterName, clusterName)
83+
if testCase.ExpectedClusterName != clusterName {
84+
t.Errorf("unexpected new clusterName for tags %v: %s vs %s", testCase.Tags, testCase.ExpectedClusterName, clusterName)
6685
continue
6786
}
6887
}

0 commit comments

Comments
 (0)