-
Notifications
You must be signed in to change notification settings - Fork 325
tags: initial implementation of tags #149
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
8139e29
to
5b1e59d
Compare
0f2fe6d
to
891e3e0
Compare
891e3e0
to
3d37978
Compare
So just to summarize our conversation from this morning, we need to keep the |
So actually as of now I think the resource tagging API is fully supported in all regions, so I don't think we need to prefer tag-on-create for that reason. Tag-on-create might be nice for other reasons, like being eaiser to implement and fewer total number of api calls. |
Thanks @nckturner for the summary |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the late review @nicolehanjing
pkg/providers/v2/cloud.go
Outdated
@@ -61,6 +77,30 @@ type EC2Metadata interface { | |||
GetMetadata(path string) (string, error) | |||
} | |||
|
|||
func readAWSCloudConfig(config io.Reader) (*v1alpha1.AWSCloudConfig, error) { | |||
if config == nil { | |||
return nil, fmt.Errorf("no AWS cloud provider config file given") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: use errors.New instead since there's no args
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gotcha!
pkg/providers/v2/cloud.go
Outdated
return nil, err | ||
} | ||
if cfg.Kind != "AWSCloudConfig" { | ||
return nil, fmt.Errorf("invalid cloud configuration object %q", cfg.Kind) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"invalid Kind for cloud config: %q"
pkg/providers/v2/cloud.go
Outdated
@@ -82,7 +122,7 @@ func azToRegion(az string) (string, error) { | |||
} | |||
|
|||
// newCloud creates a new instance of AWSCloud. | |||
func newCloud() (cloudprovider.Interface, error) { | |||
func newCloud(cfg v1alpha1.AWSCloudConfig) (cloudprovider.Interface, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: pass in the pointer
pkg/providers/v2/tags.go
Outdated
return clusterName, nil | ||
} | ||
|
||
func (t *awsTagging) init(clusterName string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general I tend to avoid naming functions init
because init
is a reserved function name in Go
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Recommend creating a constructor function for awsTagging like NewAWSTags
and have it receive clusterName as one of the parameters
pkg/providers/v2/cloud.go
Outdated
@@ -53,6 +61,14 @@ type cloud struct { | |||
region string | |||
ec2 EC2 | |||
metadata EC2Metadata | |||
tagging awsTagging |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: just name this tags
?
53c8739
to
6e7dfe7
Compare
@andrewsykim updated! PTAL :) |
pkg/providers/v2/tags.go
Outdated
} | ||
|
||
func (t *awsTagging) hasClusterTag(tags []*ec2.Tag) bool { | ||
// if the clusterName is not configured -- we consider all instances. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: wondering if this logic can be refactored slightly. IMO returning true from a function called hasClusterTag
when there isn't a tag to look for is bit confusing (for the sole purpose of causing some side effect behavior in the caller), wondering if its worth separating return values to have distinct values for "is cluster tag configured" and "does cluster tag exist". We could return a specific error (or bool value) that the caller can check for if cluster tag is not configured.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good point, personally I prefer to return a specific error with some info for the caller to check, will update!
6e7dfe7
to
42c3beb
Compare
pkg/providers/v2/cloud.go
Outdated
// we got an error where the decode wasn't related to a missing type | ||
return nil, err | ||
} | ||
if cfg.Kind != "AWSCloudConfig" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there any other required fields we have to verify here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call, I think for this PR we don't technically have to validate anything since ClusterName is optional (I think) but there will be a need to validate field values at some point. Here's one example of how to do it:
|
||
// no clusterName is a sign of misconfigured cluster, but we can't be tagging the resources with empty | ||
// strings | ||
if len(t.ClusterName) == 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is a sign of misconfigured cluster, we should log a warning here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this mean clusterName
is actually required? If so we should validate it when we read the config and return an error if it's empty. I thought clusterName was optional and it can be discovered through instances but I might be mis-remembering the details.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think requiring clusterName is reasonable, it's an explicit step from the user requiring them to understand how/why the cluster name is needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there's a way to infer the cluster name, I think that'd be ideal. "We will add the cluster name automatically, but you can override it via config" sounds reasonable to me. Although I'm not sure if there's a case where the user would want to override it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah I agree, will figure out if we can discover the cluster name through instances
for now I leave a TODO note here and a warning log in https://github.com/kubernetes/cloud-provider-aws/pull/149/files#diff-78811b2c178b96d8cf3e546ccbc24defbe15e8ef228da31b36d17ecfe29174ceR183
42c3beb
to
6c30210
Compare
6c30210
to
b5229bd
Compare
pkg/providers/v2/cloud_test.go
Outdated
for _, testcase := range testcases { | ||
t.Run(testcase.name, func(t *testing.T) { | ||
var buffer bytes.Buffer | ||
_, err := buffer.WriteString(testcase.configData) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be simplieifed to:
bytes.NewBufferString(testcase.configData)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We also need to update the Instances implementation to use the clusterName tags for API calls.
b5229bd
to
d31cbae
Compare
return nil, fmt.Errorf("failed to read AWS cloud provider config file: %v", err) | ||
} | ||
|
||
errs := validateAWSCloudConfig(cfg) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@andrewsykim updated! PTAL :)
- added validation function & unit tests
- update the Instances implementation to use the clusterName tags for API calls
d31cbae
to
253ca08
Compare
pkg/providers/v2/cloud.go
Outdated
cloudprovider "k8s.io/cloud-provider" | ||
"k8s.io/cloud-provider-aws/pkg/apis/config/v1alpha1" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
import alias this to awsconfigv1alpha1
pkg/providers/v2/cloud.go
Outdated
allErrs = append(allErrs, field.Invalid(field.NewPath("Kind"), "invalid Kind for cloud config: %q", config.Kind)) | ||
} | ||
|
||
if config.APIVersion != "config.aws.io/v1alpha1" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use awsconfigv1alpha1.SchemeGroupVersion.String()
instead of config.aws.io/v1alpha1
pkg/providers/v2/cloud.go
Outdated
allErrs := field.ErrorList{} | ||
|
||
if config.Kind != "AWSCloudConfig" { | ||
allErrs = append(allErrs, field.Invalid(field.NewPath("Kind"), "invalid Kind for cloud config: %q", config.Kind)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
field value should be the json serialized version field.NewPath("kind")
pkg/providers/v2/cloud.go
Outdated
} | ||
|
||
if config.APIVersion != "config.aws.io/v1alpha1" { | ||
allErrs = append(allErrs, field.Invalid(field.NewPath("APIVersion"), "invalid APIVersion for cloud config: %q", config.APIVersion)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
APIVersion -> apiVersion
pkg/providers/v2/cloud.go
Outdated
allErrs = append(allErrs, field.Invalid(field.NewPath("APIVersion"), "invalid APIVersion for cloud config: %q", config.APIVersion)) | ||
} | ||
|
||
fieldPath := field.NewPath("Config") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Config -> config
pkg/providers/v2/cloud.go
Outdated
} | ||
|
||
fieldPath := field.NewPath("Config") | ||
if config.Config == (v1alpha1.AWSConfig{}) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this check is required, it would fail in field-specific validation anyways
pkg/providers/v2/cloud.go
Outdated
} | ||
|
||
if len(config.Config.ClusterName) == 0 { | ||
allErrs = append(allErrs, field.Required(fieldPath.Child("ClusterName"), "cluster name cannot be empty")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ClusterName -> clusterName
253ca08
to
fb56cd9
Compare
@andrewsykim @nckturner @ayberk PTAL :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/approve
/lgtm
There's a few TODOs in the comments and the code but I think we can address those with #156
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: andrewsykim, nicolehanjing The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
first pass of tags implementation
What type of PR is this?
/kind feature
What this PR does / why we need it:
We have two formats of the cluster tags in the legacy implementation:
As @nckturner mentioned before, the current format ("
kubernetes.io/cluster/<clusterID>": <ownership>
") causes issues for customers trying to use tags to organize billing.After discussion, we'd like to see tags with formats:
the second format is only used for shared resources e.g. subnets
and once we have other workarounds, will make corresponding updates.
Which issue(s) this PR fixes:
Part of #125
Special notes for your reviewer:
Does this PR introduce a user-facing change?: