-
Notifications
You must be signed in to change notification settings - Fork 15
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
CFE-1133: Watch Infrastructure and update AWS tags #137
base: main
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -21,6 +21,8 @@ import ( | |||||||||||||||||||||||||||||||||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" | ||||||||||||||||||||||||||||||||||||
"sigs.k8s.io/controller-runtime/pkg/log" | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
configv1 "github.com/openshift/api/config/v1" | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
albo "github.com/openshift/aws-load-balancer-operator/api/v1" | ||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
|
@@ -69,7 +71,7 @@ const ( | |||||||||||||||||||||||||||||||||||
allCapabilities = "ALL" | ||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
func (r *AWSLoadBalancerControllerReconciler) ensureDeployment(ctx context.Context, sa *corev1.ServiceAccount, crSecretName, servingSecretName string, controller *albo.AWSLoadBalancerController, trustCAConfigMap *corev1.ConfigMap) (*appsv1.Deployment, error) { | ||||||||||||||||||||||||||||||||||||
func (r *AWSLoadBalancerControllerReconciler) ensureDeployment(ctx context.Context, sa *corev1.ServiceAccount, crSecretName, servingSecretName string, controller *albo.AWSLoadBalancerController, platformStatus *configv1.PlatformStatus, trustCAConfigMap *corev1.ConfigMap) (*appsv1.Deployment, error) { | ||||||||||||||||||||||||||||||||||||
deploymentName := fmt.Sprintf("%s-%s", controllerResourcePrefix, controller.Name) | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
reqLogger := log.FromContext(ctx).WithValues("deployment", deploymentName) | ||||||||||||||||||||||||||||||||||||
|
@@ -90,7 +92,11 @@ func (r *AWSLoadBalancerControllerReconciler) ensureDeployment(ctx context.Conte | |||||||||||||||||||||||||||||||||||
trustCAConfigMapHash = configMapHash | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
desired := r.desiredDeployment(deploymentName, crSecretName, servingSecretName, controller, sa, trustCAConfigMapName, trustCAConfigMapHash) | ||||||||||||||||||||||||||||||||||||
desired, err := r.desiredDeployment(deploymentName, crSecretName, servingSecretName, controller, platformStatus, sa, trustCAConfigMapName, trustCAConfigMapHash) | ||||||||||||||||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||||||||||||||||
return nil, fmt.Errorf("failed to get desired deployment %s: %w", deploymentName, err) | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
err = controllerutil.SetControllerReference(controller, desired, r.Scheme) | ||||||||||||||||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||||||||||||||||
return nil, fmt.Errorf("failed to set owner reference on deployment %s: %w", deploymentName, err) | ||||||||||||||||||||||||||||||||||||
|
@@ -120,7 +126,11 @@ func (r *AWSLoadBalancerControllerReconciler) ensureDeployment(ctx context.Conte | |||||||||||||||||||||||||||||||||||
return current, nil | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
func (r *AWSLoadBalancerControllerReconciler) desiredDeployment(name, credentialsRequestSecretName, servingSecret string, controller *albo.AWSLoadBalancerController, sa *corev1.ServiceAccount, trustedCAConfigMapName, trustedCAConfigMapHash string) *appsv1.Deployment { | ||||||||||||||||||||||||||||||||||||
func (r *AWSLoadBalancerControllerReconciler) desiredDeployment(name, credentialsRequestSecretName, servingSecret string, controller *albo.AWSLoadBalancerController, platformStatus *configv1.PlatformStatus, sa *corev1.ServiceAccount, trustedCAConfigMapName, trustedCAConfigMapHash string) (*appsv1.Deployment, error) { | ||||||||||||||||||||||||||||||||||||
containerArgs, err := desiredContainerArgs(controller, platformStatus, r.ClusterName, r.VPCID) | ||||||||||||||||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||||||||||||||||
return nil, fmt.Errorf("failed to get container args: %w", err) | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
d := &appsv1.Deployment{ | ||||||||||||||||||||||||||||||||||||
ObjectMeta: metav1.ObjectMeta{ | ||||||||||||||||||||||||||||||||||||
Name: name, | ||||||||||||||||||||||||||||||||||||
|
@@ -145,7 +155,7 @@ func (r *AWSLoadBalancerControllerReconciler) desiredDeployment(name, credential | |||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||
Name: awsLoadBalancerControllerContainerName, | ||||||||||||||||||||||||||||||||||||
Image: r.Image, | ||||||||||||||||||||||||||||||||||||
Args: desiredContainerArgs(controller, r.ClusterName, r.VPCID), | ||||||||||||||||||||||||||||||||||||
Args: containerArgs, | ||||||||||||||||||||||||||||||||||||
Env: append([]corev1.EnvVar{ | ||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||
Name: awsRegionEnvVarName, | ||||||||||||||||||||||||||||||||||||
|
@@ -257,21 +267,23 @@ func (r *AWSLoadBalancerControllerReconciler) desiredDeployment(name, credential | |||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
return d | ||||||||||||||||||||||||||||||||||||
return d, nil | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
func desiredContainerArgs(controller *albo.AWSLoadBalancerController, clusterName, vpcID string) []string { | ||||||||||||||||||||||||||||||||||||
func desiredContainerArgs(controller *albo.AWSLoadBalancerController, platformStatus *configv1.PlatformStatus, clusterName, vpcID string) ([]string, error) { | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cluster name and vpcID are still more fundamental inputs for the flags than the resource tags:
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good! Updated |
||||||||||||||||||||||||||||||||||||
var args []string | ||||||||||||||||||||||||||||||||||||
args = append(args, fmt.Sprintf("--webhook-cert-dir=%s", webhookTLSDir)) | ||||||||||||||||||||||||||||||||||||
args = append(args, fmt.Sprintf("--aws-vpc-id=%s", vpcID)) | ||||||||||||||||||||||||||||||||||||
args = append(args, fmt.Sprintf("--cluster-name=%s", clusterName)) | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
// if additional keys are present then sort them and append it to the arguments | ||||||||||||||||||||||||||||||||||||
if controller.Spec.AdditionalResourceTags != nil { | ||||||||||||||||||||||||||||||||||||
var tags []string | ||||||||||||||||||||||||||||||||||||
for _, t := range controller.Spec.AdditionalResourceTags { | ||||||||||||||||||||||||||||||||||||
tags = append(tags, fmt.Sprintf("%s=%s", t.Key, t.Value)) | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
tags := mergeTags(controller, platformStatus) | ||||||||||||||||||||||||||||||||||||
// `--default-tags` arg allows a maximum of 24 user tags, but the combination of | ||||||||||||||||||||||||||||||||||||
// controller.Spec.AdditionalResourceTags and platformStatus.AWS.ResourceTags can result in more. | ||||||||||||||||||||||||||||||||||||
// Ensure a maximum of 24 merged tags are added. | ||||||||||||||||||||||||||||||||||||
if len(tags) > 24 { | ||||||||||||||||||||||||||||||||||||
Comment on lines
+280
to
+283
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can this be a constant? And can you please add some links which confirm this number. AWS limitation is 50 tags per resource so I don't quite get where There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
aws-load-balancer-operator/api/v1/awsloadbalancercontroller_types.go Lines 61 to 77 in 59f0616
Since we are now merging these tags with the Infrastructure tags, isn't this number still valid? |
||||||||||||||||||||||||||||||||||||
return nil, fmt.Errorf("exceeded maximum of 24 allowed tags, got %d", len(tags)) | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
if len(tags) > 0 { | ||||||||||||||||||||||||||||||||||||
sort.Strings(tags) | ||||||||||||||||||||||||||||||||||||
args = append(args, fmt.Sprintf(`--default-tags=%s`, strings.Join(tags, ","))) | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
@@ -302,7 +314,7 @@ func desiredContainerArgs(controller *albo.AWSLoadBalancerController, clusterNam | |||||||||||||||||||||||||||||||||||
args = append(args, fmt.Sprintf("--ingress-class=%s", controller.Spec.IngressClass)) | ||||||||||||||||||||||||||||||||||||
args = append(args, "--feature-gates=EnableIPTargetType=false") | ||||||||||||||||||||||||||||||||||||
sort.Strings(args) | ||||||||||||||||||||||||||||||||||||
return args | ||||||||||||||||||||||||||||||||||||
return args, nil | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
func (r *AWSLoadBalancerControllerReconciler) currentDeployment(ctx context.Context, name string, namespace string) (bool, *appsv1.Deployment, error) { | ||||||||||||||||||||||||||||||||||||
|
@@ -542,3 +554,37 @@ func buildMapHash(data map[string]string) (string, error) { | |||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
return hex.EncodeToString(hash.Sum(nil)), nil | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
// mergeTags merges tags from an AWSLoadBalancerController and PlatformStatus into a slice of strings. | ||||||||||||||||||||||||||||||||||||
// Tags from `controller.Spec.AdditionalResourceTags` take precedence over those in `platformStatus.AWS.ResourceTags`. | ||||||||||||||||||||||||||||||||||||
// If a tag key already exists, the value from AdditionalResourceTags will overwrite the one from ResourceTags. | ||||||||||||||||||||||||||||||||||||
func mergeTags(controller *albo.AWSLoadBalancerController, platformStatus *configv1.PlatformStatus) []string { | ||||||||||||||||||||||||||||||||||||
// tagMap holds tags with unique keys | ||||||||||||||||||||||||||||||||||||
tagMap := make(map[string]string) | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
// Add tags from controller.Spec.AdditionalResourceTags since operator tags has higher precedence | ||||||||||||||||||||||||||||||||||||
if controller.Spec.AdditionalResourceTags != nil { | ||||||||||||||||||||||||||||||||||||
for _, t := range controller.Spec.AdditionalResourceTags { | ||||||||||||||||||||||||||||||||||||
tagMap[t.Key] = t.Value | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
// Add tags from platformStatus.AWS.ResourceTags to the map, only if the key doesn't exist | ||||||||||||||||||||||||||||||||||||
if platformStatus.AWS != nil && len(platformStatus.AWS.ResourceTags) > 0 { | ||||||||||||||||||||||||||||||||||||
for _, t := range platformStatus.AWS.ResourceTags { | ||||||||||||||||||||||||||||||||||||
if len(t.Key) > 0 { | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
So, this is redundant. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the catch. Removed the if block. |
||||||||||||||||||||||||||||||||||||
if _, exists := tagMap[t.Key]; !exists { | ||||||||||||||||||||||||||||||||||||
tagMap[t.Key] = t.Value | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
// Convert map back to a slice | ||||||||||||||||||||||||||||||||||||
var tags []string | ||||||||||||||||||||||||||||||||||||
for key, value := range tagMap { | ||||||||||||||||||||||||||||||||||||
tags = append(tags, fmt.Sprintf("%s=%s", key, value)) | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
return tags | ||||||||||||||||||||||||||||||||||||
} |
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.
Can the platform status ever be
nil
? If it can, I don't think we have to block the reconciliation - we just don't add platform tags in that case.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.
platform status should not be
nil
for clusters deployed on AWS. We need the AWS region as well from the platform status for the operator to function correctly.aws-load-balancer-operator/main.go
Lines 230 to 233 in 59f0616
So, I think we should block the reconciliation if it is
nil
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.
Right, that's what we ensure at the startup of the operator. The region is fundamental for the operator, without it the operator cannot function. Unlike resource tags (platform or additional).
I don't see why a cluster may not have any platform resource tags. So, I consider
platformStatus==nil
as the same use case as "customer didn't set any resource tags during installation".