-
Notifications
You must be signed in to change notification settings - Fork 354
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 |
andrewsykim
left a comment
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
|
|
||
| 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
|
|
||
| // 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
| 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)
andrewsykim
left a comment
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
|
|
||
| "k8s.io/apimachinery/pkg/util/validation/field" | ||
| 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 :) |
andrewsykim
left a comment
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?: