Skip to content

Commit c784087

Browse files
Merge pull request #45 from bharath-b-rh/cfe-677
CFE-677 : Add user defined tags to all azure resources created
2 parents d6653dc + c2c97a8 commit c784087

File tree

21 files changed

+515
-142
lines changed

21 files changed

+515
-142
lines changed

pkg/cloud/azure/actuators/machine/actuator_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,7 @@ func TestMachineEvents(t *testing.T) {
544544
Name: globalInfrastuctureName,
545545
},
546546
Status: configv1.InfrastructureStatus{
547+
InfrastructureName: "test-ghfd",
547548
PlatformStatus: &configv1.PlatformStatus{
548549
Azure: &configv1.AzurePlatformStatus{
549550
CloudName: configv1.AzurePublicCloud,
@@ -736,6 +737,7 @@ func TestStatusCodeBasedCreationErrors(t *testing.T) {
736737
Name: globalInfrastuctureName,
737738
},
738739
Status: configv1.InfrastructureStatus{
740+
InfrastructureName: "test-yuhg",
739741
PlatformStatus: &configv1.PlatformStatus{
740742
Azure: &configv1.AzurePlatformStatus{
741743
CloudName: configv1.AzurePublicCloud,
@@ -846,6 +848,7 @@ func TestInvalidConfigurationCreationErrors(t *testing.T) {
846848
Name: globalInfrastuctureName,
847849
},
848850
Status: configv1.InfrastructureStatus{
851+
InfrastructureName: "test-tgfj",
849852
PlatformStatus: &configv1.PlatformStatus{
850853
Azure: &configv1.AzurePlatformStatus{
851854
CloudName: configv1.AzurePublicCloud,

pkg/cloud/azure/actuators/machine/reconciler.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -677,7 +677,7 @@ func (s *Reconciler) createVirtualMachine(ctx context.Context, nicName, asName s
677677
DataDisks: s.scope.MachineConfig.DataDisks,
678678
Image: s.scope.MachineConfig.Image,
679679
Zone: zone,
680-
Tags: s.scope.MachineConfig.Tags,
680+
Tags: s.scope.Tags,
681681
SecurityProfile: s.scope.MachineConfig.SecurityProfile,
682682
UltraSSDCapability: s.scope.MachineConfig.UltraSSDCapability,
683683
AvailabilitySetName: asName,
@@ -688,12 +688,6 @@ func (s *Reconciler) createVirtualMachine(ctx context.Context, nicName, asName s
688688
vmSpec.ManagedIdentity = azure.GenerateManagedIdentityName(s.scope.SubscriptionID, s.scope.MachineConfig.ResourceGroup, s.scope.MachineConfig.ManagedIdentity)
689689
}
690690

691-
if vmSpec.Tags == nil {
692-
vmSpec.Tags = map[string]string{}
693-
}
694-
695-
vmSpec.Tags[fmt.Sprintf("kubernetes.io-cluster-%v", s.scope.Machine.Labels[machinev1.MachineClusterIDLabel])] = "owned"
696-
697691
userData, userDataErr := s.getCustomUserData()
698692
if userDataErr != nil {
699693
return fmt.Errorf("failed to get custom script data: %w", userDataErr)

pkg/cloud/azure/actuators/machine_scope.go

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/Azure/go-autorest/autorest"
2525
"github.com/Azure/go-autorest/autorest/adal"
2626
"github.com/Azure/go-autorest/autorest/azure"
27+
"github.com/Azure/go-autorest/autorest/to"
2728
configv1 "github.com/openshift/api/config/v1"
2829
machinev1 "github.com/openshift/api/machine/v1beta1"
2930
apierrors "github.com/openshift/machine-api-operator/pkg/controller/machine"
@@ -87,6 +88,18 @@ func NewMachineScope(params MachineScopeParams) (*MachineScope, error) {
8788
return nil, fmt.Errorf("failed to get cluster infrastructure: %w", err)
8889
}
8990

91+
infraTags := getInfraResourceTags(infra.Status.PlatformStatus)
92+
93+
ocpTags, err := getOCPTagList(infra.Status.InfrastructureName)
94+
if err != nil {
95+
return nil, fmt.Errorf("failed to get OCP tag list: %w", err)
96+
}
97+
98+
tags, err := getTagList(ocpTags, infraTags, machineConfig.Tags)
99+
if err != nil {
100+
return nil, fmt.Errorf("failed to get combined tag list: %w", err)
101+
}
102+
90103
cloudEnv, armEndpoint := GetCloudEnvironment(infra)
91104

92105
machineScope := &MachineScope{
@@ -107,6 +120,7 @@ func NewMachineScope(params MachineScopeParams) (*MachineScope, error) {
107120
machineToBePatched: controllerclient.MergeFrom(params.Machine.DeepCopy()),
108121
cloudEnv: cloudEnv,
109122
armEndpoint: armEndpoint,
123+
Tags: tags,
110124
}
111125

112126
if err = updateFromSecret(params.CoreClient, machineScope); err != nil {
@@ -141,6 +155,10 @@ type MachineScope struct {
141155
origMachineStatus *machinev1.AzureMachineProviderStatus
142156

143157
machineToBePatched controllerclient.Patch
158+
159+
// Tags is a list of tags to apply to the resources created
160+
// for the cluster
161+
Tags map[string]*string
144162
}
145163

146164
// Name returns the machine name.
@@ -400,3 +418,99 @@ func getEnvironment(m *MachineScope) (*azure.Environment, error) {
400418

401419
return &env, nil
402420
}
421+
422+
// getTagList is for getting the merged tag list present in
423+
// AzureMachineProviderSpec and Infrastructure.Status. Both
424+
// will have the same tags, unless AzureMachineProviderSpec.Tags
425+
// has been modified to add/update/delete any tag. Merge will be
426+
// necessary in delete case, to honour the user-defined tags
427+
// in Infrastructure.Status and those to newly created resources.
428+
func getTagList(ocpTags, infraStatusTags, machineSpecTags map[string]string) (map[string]*string, error) {
429+
if machineSpecTags == nil && infraStatusTags == nil {
430+
return *to.StringMapPtr(ocpTags), nil
431+
}
432+
433+
// Tag keys are case-insensitive. A tag with a key, regardless of
434+
// the casing, is updated or retrieved. An Azure service might keep
435+
// the casing as provided for the tag key. To allow user to choose
436+
// the required variant of the key to add. return error when
437+
// duplicate tag keys are found in machineSpecTags. Tags in
438+
// infraStatusTags is vetted by installer.
439+
if err := findDuplicateTagKeys(machineSpecTags); err != nil {
440+
return nil, fmt.Errorf("Machine.Spec.ProviderSpec.Tags validation failed: %w", err)
441+
}
442+
443+
tags := make(map[string]*string)
444+
// copy user defined tags in Infrastructure.Status.
445+
for k, v := range infraStatusTags {
446+
tags[k] = to.StringPtr(v)
447+
}
448+
449+
// merge tags present in Infrastructure.Status with
450+
// the tags configured in AzureMachineProviderSpec, with
451+
// precedence given to those in AzureMachineProviderSpec
452+
// for new or updated tags.
453+
for k, v := range machineSpecTags {
454+
tags[k] = to.StringPtr(v)
455+
}
456+
457+
// copy OCP tags, overwrite any OCP reserved tags found in
458+
// the user defined tag list.
459+
for k, v := range ocpTags {
460+
tags[k] = to.StringPtr(v)
461+
}
462+
463+
// Automation, Content Delivery Network, DNS Azure resources can have a
464+
// maximum of 15 tags. OpenShift is reserved with 5 tags for internal use,
465+
// allowing 10 tags for user configuration. But this operator does not create
466+
// any of the above resources and supports configuring additional tags, hence
467+
// increasing the user tags max limit to 45.
468+
if len(ocpTags) > 5 || (len(tags)-len(ocpTags)) > 45 {
469+
return nil, fmt.Errorf("ocp can define upto 5 tags and user can define upto 45 tags,"+
470+
"infrstructure.status.resourceTags and Machine.Spec.ProviderSpec.Tags put together, current tag count: %d", len(tags))
471+
}
472+
473+
return tags, nil
474+
}
475+
476+
func getInfraResourceTags(platformStatus *configv1.PlatformStatus) (tags map[string]string) {
477+
if platformStatus != nil && platformStatus.Azure != nil && platformStatus.Azure.ResourceTags != nil {
478+
tags = make(map[string]string, len(platformStatus.Azure.ResourceTags))
479+
for _, tag := range platformStatus.Azure.ResourceTags {
480+
tags[tag.Key] = tag.Value
481+
}
482+
}
483+
return
484+
}
485+
486+
func getOCPTagList(clusterID string) (map[string]string, error) {
487+
if clusterID == "" {
488+
return nil, fmt.Errorf("cluster ID required for generating OCP tag list")
489+
}
490+
return map[string]string{
491+
fmt.Sprintf("kubernetes.io_cluster.%v", clusterID): "owned",
492+
}, nil
493+
}
494+
495+
func findDuplicateTagKeys(tagSet map[string]string) error {
496+
if len(tagSet) == 0 {
497+
return nil
498+
}
499+
500+
dupKeys := make(map[string]int)
501+
for k := range tagSet {
502+
dupKeys[strings.ToTitle(k)]++
503+
}
504+
505+
var errMsg []string
506+
for key, count := range dupKeys {
507+
if count > 1 {
508+
errMsg = append(errMsg, fmt.Sprintf("\"%s\" matches %d keys", key, count))
509+
}
510+
}
511+
if len(errMsg) > 0 {
512+
return fmt.Errorf("found duplicate tag keys: %v", strings.Join(errMsg, ", "))
513+
}
514+
515+
return nil
516+
}

0 commit comments

Comments
 (0)