knative.dev/pkg@v0.0.0-20260602142205-ac97e43f6622/webhook/resourcesemantics/defaulting/user_info_test.go (about)

     1  /*
     2  Copyright 2019 The Knative 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 defaulting
    18  
    19  import (
    20  	"context"
    21  	"reflect"
    22  	"testing"
    23  
    24  	"github.com/google/go-cmp/cmp"
    25  	"github.com/google/go-cmp/cmp/cmpopts"
    26  	authenticationv1 "k8s.io/api/authentication/v1"
    27  	"knative.dev/pkg/apis"
    28  	. "knative.dev/pkg/logging/testing"
    29  	. "knative.dev/pkg/testing"
    30  	. "knative.dev/pkg/webhook/testing"
    31  )
    32  
    33  func TestSetUserInfoAnnotationsWhenWithinCreate(t *testing.T) {
    34  	tests := []struct {
    35  		name                string
    36  		configureContext    func(context.Context) context.Context
    37  		setup               func(context.Context, *Resource)
    38  		expectedAnnotations map[string]string
    39  	}{{
    40  		name: "test create",
    41  		configureContext: func(ctx context.Context) context.Context {
    42  			return apis.WithinCreate(apis.WithUserInfo(ctx, &authenticationv1.UserInfo{Username: user1}))
    43  		},
    44  		setup: func(ctx context.Context, r *Resource) {
    45  			r.Annotations = map[string]string{}
    46  		},
    47  		expectedAnnotations: map[string]string{
    48  			"pkg.knative.dev/creator":      user1,
    49  			"pkg.knative.dev/lastModifier": user1,
    50  		},
    51  	}, {
    52  		name: "test create (should override user info annotations when they are present)",
    53  		configureContext: func(ctx context.Context) context.Context {
    54  			return apis.WithinCreate(apis.WithUserInfo(ctx, &authenticationv1.UserInfo{Username: user1}))
    55  		},
    56  		setup: func(ctx context.Context, r *Resource) {
    57  			r.Annotations = map[string]string{
    58  				"pkg.knative.dev/creator":      user2,
    59  				"pkg.knative.dev/lastModifier": user2,
    60  			}
    61  		},
    62  		expectedAnnotations: map[string]string{
    63  			"pkg.knative.dev/creator":      user1,
    64  			"pkg.knative.dev/lastModifier": user1,
    65  		},
    66  	}, {
    67  		name:                "test create (should not touch annotations when no user info available)",
    68  		configureContext:    apis.WithinCreate,
    69  		setup:               func(ctx context.Context, r *Resource) {},
    70  		expectedAnnotations: nil,
    71  	}}
    72  
    73  	for _, tc := range tests {
    74  		t.Run(tc.name, func(t *testing.T) {
    75  			r := CreateResource("a name")
    76  
    77  			ctx := tc.configureContext(TestContextWithLogger(t))
    78  
    79  			tc.setup(ctx, r)
    80  
    81  			setUserInfoAnnotations(ctx, r, "pkg.knative.dev")
    82  
    83  			if !reflect.DeepEqual(r.Annotations, tc.expectedAnnotations) {
    84  				t.Logf("Got :  %#v", r.Annotations)
    85  				t.Logf("Want: %#v", tc.expectedAnnotations)
    86  				if diff := cmp.Diff(tc.expectedAnnotations, r.Annotations, cmpopts.EquateEmpty()); diff != "" {
    87  					t.Log("diff:", diff)
    88  				}
    89  				t.Fatalf("Annotations don't match")
    90  			}
    91  		})
    92  	}
    93  }
    94  
    95  func TestSetUserInfoAnnotationsWhenWithinUpdate(t *testing.T) {
    96  	tests := []struct {
    97  		name                string
    98  		configureContext    func(context.Context, *Resource) context.Context
    99  		setup               func(context.Context, *Resource)
   100  		expectedAnnotations map[string]string
   101  	}{{
   102  		name: "test update (should add updater annotation when it is not present)",
   103  		configureContext: func(ctx context.Context, r *Resource) context.Context {
   104  			return apis.WithinUpdate(apis.WithUserInfo(ctx, &authenticationv1.UserInfo{Username: user1}), r)
   105  		},
   106  		setup: func(ctx context.Context, r *Resource) {
   107  			r.Annotations = map[string]string{
   108  				"pkg.knative.dev/creator": user2,
   109  			}
   110  			r.Spec.FieldWithDefault = "changing this field"
   111  		},
   112  		expectedAnnotations: map[string]string{
   113  			"pkg.knative.dev/creator":      user2,
   114  			"pkg.knative.dev/lastModifier": user1,
   115  		},
   116  	}, {
   117  		name: "test update (should update updater annotation when it is present)",
   118  		configureContext: func(ctx context.Context, r *Resource) context.Context {
   119  			return apis.WithinUpdate(apis.WithUserInfo(ctx, &authenticationv1.UserInfo{Username: user1}), r)
   120  		},
   121  		setup: func(ctx context.Context, r *Resource) {
   122  			r.Annotations = map[string]string{
   123  				"pkg.knative.dev/creator":      user2,
   124  				"pkg.knative.dev/lastModifier": user2,
   125  			}
   126  			r.Spec.FieldWithDefault = "changing this field"
   127  		},
   128  		expectedAnnotations: map[string]string{
   129  			// should not change
   130  			"pkg.knative.dev/creator":      user2,
   131  			"pkg.knative.dev/lastModifier": user1,
   132  		},
   133  	}, {
   134  		name: "test update (should not touch annotations when no user info available)",
   135  		configureContext: func(ctx context.Context, r *Resource) context.Context {
   136  			return apis.WithinUpdate(ctx, r)
   137  		},
   138  		setup: func(ctx context.Context, r *Resource) {
   139  			// this is not necessary, but let's do this in case the execution flow changes
   140  			r.Spec.FieldWithDefault = "changing this field"
   141  		},
   142  		expectedAnnotations: nil,
   143  	}, {
   144  		name: "test update (should not touch annotations when nothing in spec is changed)",
   145  		configureContext: func(ctx context.Context, r *Resource) context.Context {
   146  			return apis.WithinUpdate(apis.WithUserInfo(ctx, &authenticationv1.UserInfo{Username: user1}), r)
   147  		},
   148  		setup: func(ctx context.Context, r *Resource) {
   149  			// change nothing
   150  		},
   151  		expectedAnnotations: map[string]string{},
   152  	}}
   153  
   154  	for _, tc := range tests {
   155  		t.Run(tc.name, func(t *testing.T) {
   156  			r := CreateResource("a name")
   157  
   158  			ctx := tc.configureContext(TestContextWithLogger(t), r)
   159  
   160  			newObj := r.DeepCopy()
   161  
   162  			tc.setup(ctx, newObj)
   163  
   164  			setUserInfoAnnotations(ctx, newObj, "pkg.knative.dev")
   165  
   166  			if !reflect.DeepEqual(newObj.Annotations, tc.expectedAnnotations) {
   167  				t.Logf("Got :  %#v", newObj.Annotations)
   168  				t.Logf("Want: %#v", tc.expectedAnnotations)
   169  				if diff := cmp.Diff(tc.expectedAnnotations, newObj.Annotations, cmpopts.EquateEmpty()); diff != "" {
   170  					t.Logf("diff:\n%s", diff)
   171  				}
   172  				t.Fatalf("Annotations don't match")
   173  			}
   174  		})
   175  	}
   176  }