|
1 | 1 | # TEST DRY RUN: mandatory_tags = None |
2 | 2 | import json |
3 | 3 | import os |
| 4 | +from unittest.mock import patch |
4 | 5 |
|
5 | 6 | import pytest |
6 | 7 | from moto import mock_ec2, mock_cloudtrail, mock_iam, mock_s3, mock_elb, mock_elbv2 |
@@ -236,3 +237,108 @@ def test_cluster_ec2(): |
236 | 237 | tag_resources = TagClusterResources(cluster_prefix=cluster_prefix, cluster_name=cluster_name, |
237 | 238 | input_tags=mandatory_tags, region='us-east-2') |
238 | 239 | assert len(tag_resources.cluster_instance()) == 3 |
| 240 | + |
| 241 | + |
| 242 | +# --- Hypershift / tag_cluster propagation (PR #976): do not propagate kubernetes.io/ or sigs.k8s.io/ tags --- |
| 243 | + |
| 244 | +CLUSTER_STAMP_KEY = 'kubernetes.io/cluster/hyper2-unittest' |
| 245 | + |
| 246 | + |
| 247 | +def test_get_cluster_tags_for_propagation_excludes_cluster_and_k8s_sigs_tags(): |
| 248 | + """ |
| 249 | + Tags returned for propagation must not include kubernetes.io/cluster, other kubernetes.io/*, |
| 250 | + sigs.k8s.io/*, or Name — only governance-style tags (e.g. User) should propagate. |
| 251 | + """ |
| 252 | + with mock_ec2(), mock_iam(), mock_cloudtrail(), mock_s3(), mock_elb(), mock_elbv2(): |
| 253 | + tcr = TagClusterResources( |
| 254 | + cluster_prefix=cluster_prefix, |
| 255 | + cluster_name=cluster_name, |
| 256 | + input_tags=mandatory_tags, |
| 257 | + region='us-east-2', |
| 258 | + ) |
| 259 | + fake_instance = [{ |
| 260 | + 'InstanceId': 'i-hyper2test', |
| 261 | + 'Tags': [ |
| 262 | + {'Key': CLUSTER_STAMP_KEY, 'Value': 'owned'}, |
| 263 | + { |
| 264 | + 'Key': 'sigs.k8s.io/cluster-api-provider-aws/cluster/hyper2-unittest', |
| 265 | + 'Value': 'owned', |
| 266 | + }, |
| 267 | + {'Key': 'kubernetes.io/role/worker', 'Value': 'true'}, |
| 268 | + {'Key': 'User', 'Value': 'alice'}, |
| 269 | + {'Key': 'Manager', 'Value': 'bob'}, |
| 270 | + {'Key': 'Name', 'Value': 'hypershift-node-1'}, |
| 271 | + ], |
| 272 | + }] |
| 273 | + with patch.object(tcr, '_get_instances_data', return_value=[fake_instance]): |
| 274 | + result = tcr._TagClusterResources__get_cluster_tags_by_instance_cluster(CLUSTER_STAMP_KEY) |
| 275 | + |
| 276 | + assert result == [ |
| 277 | + {'Key': 'User', 'Value': 'alice'}, |
| 278 | + {'Key': 'Manager', 'Value': 'bob'}, |
| 279 | + ] |
| 280 | + assert not any(t['Key'].startswith('kubernetes.io/') for t in result) |
| 281 | + assert not any(t['Key'].startswith('sigs.k8s.io/') for t in result) |
| 282 | + assert not any(t['Key'] == 'Name' for t in result) |
| 283 | + |
| 284 | + |
| 285 | +def test_get_cluster_tags_for_propagation_empty_when_only_cluster_system_tags(): |
| 286 | + """If the instance has only cluster stamp and k8s/sigs system tags (plus Name), nothing should propagate.""" |
| 287 | + with mock_ec2(), mock_iam(), mock_cloudtrail(), mock_s3(), mock_elb(), mock_elbv2(): |
| 288 | + tcr = TagClusterResources( |
| 289 | + cluster_prefix=cluster_prefix, |
| 290 | + cluster_name=cluster_name, |
| 291 | + input_tags=mandatory_tags, |
| 292 | + region='us-east-2', |
| 293 | + ) |
| 294 | + fake_instance = [{ |
| 295 | + 'InstanceId': 'i-onlysys', |
| 296 | + 'Tags': [ |
| 297 | + {'Key': CLUSTER_STAMP_KEY, 'Value': 'owned'}, |
| 298 | + { |
| 299 | + 'Key': 'sigs.k8s.io/cluster-api-provider-aws/cluster/hyper2-unittest', |
| 300 | + 'Value': 'owned', |
| 301 | + }, |
| 302 | + {'Key': 'kubernetes.io/role/master', 'Value': 'true'}, |
| 303 | + {'Key': 'Name', 'Value': 'cp-0'}, |
| 304 | + ], |
| 305 | + }] |
| 306 | + with patch.object(tcr, '_get_instances_data', return_value=[fake_instance]): |
| 307 | + result = tcr._TagClusterResources__get_cluster_tags_by_instance_cluster(CLUSTER_STAMP_KEY) |
| 308 | + |
| 309 | + assert result == [] |
| 310 | + |
| 311 | + |
| 312 | +def test_get_cluster_tags_for_propagation_uses_cluster_prefix_from_environment_variables(): |
| 313 | + """ |
| 314 | + no_propagate_prefixes must follow CLUSTER_PREFIX in environment_variables (same derivation as production). |
| 315 | + """ |
| 316 | + from cloud_governance.main.environment_variables import environment_variables |
| 317 | + |
| 318 | + custom_prefixes = ['api.openshift.com/cluster', 'kubernetes.io/cluster'] |
| 319 | + original = environment_variables.environment_variables_dict['CLUSTER_PREFIX'] |
| 320 | + try: |
| 321 | + environment_variables.environment_variables_dict['CLUSTER_PREFIX'] = custom_prefixes |
| 322 | + with mock_ec2(), mock_iam(), mock_cloudtrail(), mock_s3(), mock_elb(), mock_elbv2(): |
| 323 | + tcr = TagClusterResources( |
| 324 | + cluster_prefix=custom_prefixes, |
| 325 | + cluster_name=cluster_name, |
| 326 | + input_tags=mandatory_tags, |
| 327 | + region='us-east-2', |
| 328 | + ) |
| 329 | + stamp = 'api.openshift.com/cluster/hyper2-unittest' |
| 330 | + fake_instance = [{ |
| 331 | + 'InstanceId': 'i-custom', |
| 332 | + 'Tags': [ |
| 333 | + {'Key': stamp, 'Value': 'owned'}, |
| 334 | + {'Key': 'api.openshift.com/something-else', 'Value': 'x'}, |
| 335 | + {'Key': 'User', 'Value': 'carol'}, |
| 336 | + ], |
| 337 | + }] |
| 338 | + with patch.object(tcr, '_get_instances_data', return_value=[fake_instance]): |
| 339 | + result = tcr._TagClusterResources__get_cluster_tags_by_instance_cluster(stamp) |
| 340 | + # api.openshift.com/ and kubernetes.io/ blocked; User kept |
| 341 | + assert result == [{'Key': 'User', 'Value': 'carol'}] |
| 342 | + assert not any(t['Key'].startswith('api.openshift.com/') for t in result) |
| 343 | + finally: |
| 344 | + environment_variables.environment_variables_dict['CLUSTER_PREFIX'] = original |
0 commit comments