sigs.k8s.io/cluster-api@v1.7.1/util/log/log_test.go (about)

     1  /*
     2  Copyright 2022 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package log
    18  
    19  import (
    20  	"context"
    21  	"testing"
    22  
    23  	"github.com/go-logr/logr"
    24  	. "github.com/onsi/gomega"
    25  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    26  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    27  	"k8s.io/apimachinery/pkg/runtime"
    28  	"k8s.io/klog/v2"
    29  	ctrl "sigs.k8s.io/controller-runtime"
    30  	"sigs.k8s.io/controller-runtime/pkg/client"
    31  	"sigs.k8s.io/controller-runtime/pkg/client/fake"
    32  	"sigs.k8s.io/controller-runtime/pkg/log"
    33  
    34  	clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
    35  )
    36  
    37  func Test_AddObjectHierarchy(t *testing.T) {
    38  	g := NewWithT(t)
    39  
    40  	scheme := runtime.NewScheme()
    41  	g.Expect(clusterv1.AddToScheme(scheme)).To(Succeed())
    42  
    43  	md := &clusterv1.MachineSet{
    44  		TypeMeta: metav1.TypeMeta{
    45  			APIVersion: clusterv1.GroupVersion.String(),
    46  			Kind:       "MachineDeployment",
    47  		},
    48  		ObjectMeta: metav1.ObjectMeta{
    49  			Namespace: metav1.NamespaceDefault,
    50  			Name:      "development-3961-md-0-l4zn6",
    51  		},
    52  	}
    53  	mdOwnerRef := metav1.OwnerReference{
    54  		APIVersion: md.APIVersion,
    55  		Kind:       md.Kind,
    56  		Name:       md.Name,
    57  	}
    58  
    59  	ms := &clusterv1.MachineSet{
    60  		TypeMeta: metav1.TypeMeta{
    61  			APIVersion: clusterv1.GroupVersion.String(),
    62  			Kind:       "MachineSet",
    63  		},
    64  		ObjectMeta: metav1.ObjectMeta{
    65  			Namespace:       metav1.NamespaceDefault,
    66  			Name:            "development-3961-md-0-l4zn6-758c9b7677",
    67  			OwnerReferences: []metav1.OwnerReference{mdOwnerRef},
    68  		},
    69  	}
    70  	msOwnerRef := metav1.OwnerReference{
    71  		APIVersion: ms.APIVersion,
    72  		Kind:       ms.Kind,
    73  		Name:       ms.Name,
    74  	}
    75  
    76  	tests := []struct {
    77  		name                  string
    78  		obj                   metav1.Object
    79  		objects               []client.Object
    80  		expectedKeysAndValues []interface{}
    81  	}{
    82  		{
    83  			name: "MachineSet owning Machine is added",
    84  			// MachineSet does not exist in Kubernetes so only MachineSet is added
    85  			// and MachineDeployment is not.
    86  			obj: &clusterv1.Machine{
    87  				ObjectMeta: metav1.ObjectMeta{
    88  					OwnerReferences: []metav1.OwnerReference{msOwnerRef},
    89  					Namespace:       metav1.NamespaceDefault,
    90  				},
    91  			},
    92  			expectedKeysAndValues: []interface{}{
    93  				"MachineSet",
    94  				klog.ObjectRef{Namespace: ms.Namespace, Name: ms.Name},
    95  			},
    96  		},
    97  		{
    98  			name: "MachineDeployment and MachineSet owning Machine is added",
    99  			obj: &clusterv1.Machine{
   100  				ObjectMeta: metav1.ObjectMeta{
   101  					OwnerReferences: []metav1.OwnerReference{msOwnerRef},
   102  					Namespace:       metav1.NamespaceDefault,
   103  				},
   104  			},
   105  			objects: []client.Object{ms},
   106  			expectedKeysAndValues: []interface{}{
   107  				"MachineSet",
   108  				klog.ObjectRef{Namespace: ms.Namespace, Name: ms.Name},
   109  				"MachineDeployment",
   110  				klog.ObjectRef{Namespace: md.Namespace, Name: md.Name},
   111  			},
   112  		},
   113  		{
   114  			name: "MachineDeployment owning MachineSet is added",
   115  			obj: &clusterv1.MachineSet{
   116  				ObjectMeta: metav1.ObjectMeta{
   117  					OwnerReferences: []metav1.OwnerReference{mdOwnerRef},
   118  					Namespace:       metav1.NamespaceDefault,
   119  				},
   120  			},
   121  			expectedKeysAndValues: []interface{}{
   122  				"MachineDeployment",
   123  				klog.ObjectRef{Namespace: md.Namespace, Name: md.Name},
   124  			},
   125  		},
   126  		{
   127  			name: "KubeadmControlPlane and Machine owning DockerMachine are added",
   128  			obj: &unstructured.Unstructured{
   129  				Object: map[string]interface{}{
   130  					"apiVersion": "infrastructure.cluster.x-k8s.io/v1beta1",
   131  					"kind":       "DockerMachine",
   132  					"metadata": map[string]interface{}{
   133  						"ownerReferences": []interface{}{
   134  							map[string]interface{}{
   135  								"apiVersion": clusterv1.GroupVersion.String(),
   136  								"kind":       "Machine",
   137  								"name":       "development-3961-4flkb-gzxnb",
   138  							},
   139  							map[string]interface{}{
   140  								"apiVersion": clusterv1.GroupVersion.String(),
   141  								"kind":       "KubeadmControlPlane",
   142  								"name":       "development-3961-4flkb",
   143  							},
   144  						},
   145  						"namespace": metav1.NamespaceDefault,
   146  					},
   147  				},
   148  			},
   149  			expectedKeysAndValues: []interface{}{
   150  				"Machine",
   151  				klog.ObjectRef{Namespace: metav1.NamespaceDefault, Name: "development-3961-4flkb-gzxnb"},
   152  				"KubeadmControlPlane",
   153  				klog.ObjectRef{Namespace: metav1.NamespaceDefault, Name: "development-3961-4flkb"},
   154  			},
   155  		},
   156  		{
   157  			name: "Duplicate Cluster ownerRef should be deduplicated",
   158  			obj: &unstructured.Unstructured{
   159  				Object: map[string]interface{}{
   160  					"apiVersion": "infrastructure.cluster.x-k8s.io/v1beta1",
   161  					"kind":       "DockerCluster",
   162  					"metadata": map[string]interface{}{
   163  						"ownerReferences": []interface{}{
   164  							map[string]interface{}{
   165  								"apiVersion": clusterv1.GroupVersion.String(),
   166  								"kind":       "Cluster",
   167  								"name":       "development-3961",
   168  							},
   169  							map[string]interface{}{
   170  								"apiVersion": clusterv1.GroupVersion.String(),
   171  								"kind":       "Cluster",
   172  								"name":       "development-3961",
   173  							},
   174  						},
   175  						"namespace": metav1.NamespaceDefault,
   176  					},
   177  				},
   178  			},
   179  			expectedKeysAndValues: []interface{}{
   180  				"Cluster",
   181  				klog.ObjectRef{Namespace: metav1.NamespaceDefault, Name: "development-3961"},
   182  			},
   183  		},
   184  	}
   185  	for _, tt := range tests {
   186  		t.Run(tt.name, func(t *testing.T) {
   187  			g := NewWithT(t)
   188  
   189  			c := fake.NewClientBuilder().
   190  				WithScheme(scheme).
   191  				WithObjects(tt.objects...).
   192  				Build()
   193  
   194  			// Create fake log sink so we can later verify the added k/v pairs.
   195  			ctx := ctrl.LoggerInto(context.Background(), logr.New(&fakeLogSink{}))
   196  
   197  			_, logger, err := AddOwners(ctx, c, tt.obj)
   198  			g.Expect(err).ToNot(HaveOccurred())
   199  			g.Expect(logger.GetSink().(fakeLogSink).keysAndValues).To(Equal(tt.expectedKeysAndValues))
   200  		})
   201  	}
   202  }
   203  
   204  type fakeLogSink struct {
   205  	// Embedding NullLogSink so we don't have to implement all funcs
   206  	// of the LogSink interface.
   207  	log.NullLogSink
   208  	keysAndValues []interface{}
   209  }
   210  
   211  // WithValues stores keysAndValues so we can later check if the
   212  // right keysAndValues have been added.
   213  func (f fakeLogSink) WithValues(keysAndValues ...interface{}) logr.LogSink {
   214  	f.keysAndValues = keysAndValues
   215  	return f
   216  }