github.com/zppinho/prow@v0.0.0-20240510014325-1738badeb017/pkg/plugins/updateconfig/updateconfig_test.go (about)

     1  /*
     2  Copyright 2017 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 updateconfig
    18  
    19  import (
    20  	"context"
    21  	"strings"
    22  	"testing"
    23  	"testing/fstest"
    24  
    25  	"github.com/google/go-cmp/cmp"
    26  	"github.com/google/go-cmp/cmp/cmpopts"
    27  	"github.com/prometheus/client_golang/prometheus"
    28  	prometheus_model "github.com/prometheus/client_model/go"
    29  	"github.com/sirupsen/logrus"
    30  	coreapi "k8s.io/api/core/v1"
    31  	"k8s.io/apimachinery/pkg/api/equality"
    32  	"k8s.io/apimachinery/pkg/api/errors"
    33  	"k8s.io/apimachinery/pkg/api/meta"
    34  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    35  	"k8s.io/apimachinery/pkg/runtime"
    36  	"k8s.io/apimachinery/pkg/util/diff"
    37  	"k8s.io/apimachinery/pkg/util/sets"
    38  	"k8s.io/client-go/kubernetes/fake"
    39  	clienttesting "k8s.io/client-go/testing"
    40  
    41  	"sigs.k8s.io/prow/pkg/git/localgit"
    42  	"sigs.k8s.io/prow/pkg/git/v2"
    43  	"sigs.k8s.io/prow/pkg/github"
    44  	"sigs.k8s.io/prow/pkg/github/fakegithub"
    45  	"sigs.k8s.io/prow/pkg/kube"
    46  	"sigs.k8s.io/prow/pkg/plugins"
    47  )
    48  
    49  const defaultNamespace = "default"
    50  
    51  var defaultBranch = localgit.DefaultBranch("")
    52  
    53  var remoteFiles = map[string]map[string]string{
    54  	"prow/config.yaml": {
    55  		defaultBranch: "old-config",
    56  		"12345":       "new-config",
    57  	},
    58  	"prow/binary.yaml": {
    59  		defaultBranch: "old-binary\x00\xFF\xFF",
    60  		"12345":       "new-binary\x00\xFF\xFF",
    61  	},
    62  	"prow/binary.yml": {
    63  		defaultBranch: "old-binary\x00\xFF\xFF",
    64  		"12345":       "new-binary\x00\xFF\xFF",
    65  	},
    66  	"prow/becoming-binary.yaml": {
    67  		defaultBranch: "not-yet-binary",
    68  		"12345":       "now-binary\x00\xFF\xFF",
    69  	},
    70  	"prow/becoming-text.yaml": {
    71  		defaultBranch: "not-yet-text\x00\xFF\xFF",
    72  		"12345":       "now-text",
    73  	},
    74  	"prow/plugins.yaml": {
    75  		defaultBranch: "old-plugins",
    76  		"12345":       "new-plugins",
    77  	},
    78  	"boskos/resources.yaml": {
    79  		defaultBranch: "old-boskos-config",
    80  		"12345":       "new-boskos-config",
    81  	},
    82  	"config/foo.yaml": {
    83  		defaultBranch: "old-foo-config",
    84  		"12345":       "new-foo-config",
    85  	},
    86  	"config/bar.yaml": {
    87  		defaultBranch: "old-bar-config",
    88  		"12345":       "new-bar-config",
    89  	},
    90  	"dir/subdir/fejta.yaml": {
    91  		defaultBranch: "old-fejta-config",
    92  		"12345":       "new-fejta-config",
    93  	},
    94  	"dir/subdir/fejtaverse/krzyzacy.yaml": {
    95  		defaultBranch: "old-krzyzacy-config",
    96  		"12345":       "new-krzyzacy-config",
    97  	},
    98  	"dir/subdir/fejtaverse/fejtabot.yaml": {
    99  		"54321": "new-fejtabot-config",
   100  	},
   101  	"dir/subdir/fejtaverse/sig-foo/added.yaml": {
   102  		"12345": "new-added-config",
   103  	},
   104  	"dir/subdir/fejtaverse/sig-bar/removed.yaml": {
   105  		defaultBranch: "old-removed-config",
   106  	},
   107  	"dir/subdir/even.yaml": {
   108  		"12345": "even SHA256",
   109  	},
   110  }
   111  
   112  func setupLocalGitRepo(clients localgit.Clients, t *testing.T, org, repo string) git.ClientFactory {
   113  	lg, c, err := clients()
   114  	if err != nil {
   115  		t.Fatalf("Making local git repo: %v", err)
   116  	}
   117  	if err := lg.MakeFakeRepo(org, repo); err != nil {
   118  		t.Fatalf("Making fake repo: %v", err)
   119  	}
   120  	if err := lg.Checkout(org, repo, defaultBranch); err != nil {
   121  		t.Fatalf("Checkout new branch: %v", err)
   122  	}
   123  	if err := lg.AddCommit(org, repo, getFileMap(defaultBranch)); err != nil {
   124  		t.Fatalf("Add commit: %v", err)
   125  	}
   126  	if err := lg.CheckoutNewBranch(org, repo, "12345"); err != nil {
   127  		t.Fatalf("Checkout new branch: %v", err)
   128  	}
   129  	if err := lg.AddCommit(org, repo, getFileMap("12345")); err != nil {
   130  		t.Fatalf("Add commit: %v", err)
   131  	}
   132  	if err := lg.Checkout(org, repo, defaultBranch); err != nil {
   133  		t.Fatalf("Checkout new branch: %v", err)
   134  	}
   135  	if err := lg.CheckoutNewBranch(org, repo, "54321"); err != nil {
   136  		t.Fatalf("Checkout new branch: %v", err)
   137  	}
   138  	if err := lg.AddCommit(org, repo, getFileMap("54321")); err != nil {
   139  		t.Fatalf("Add commit: %v", err)
   140  	}
   141  	if err := lg.Checkout(org, repo, defaultBranch); err != nil {
   142  		t.Fatalf("Checkout new branch: %v", err)
   143  	}
   144  	return c
   145  }
   146  
   147  func TestUpdateConfigV2(t *testing.T) {
   148  	testUpdateConfig(localgit.NewV2, t)
   149  }
   150  
   151  func testUpdateConfig(clients localgit.Clients, t *testing.T) {
   152  	basicPR := github.PullRequest{
   153  		Number: 1,
   154  		Base: github.PullRequestBranch{
   155  			Repo: github.Repo{
   156  				Owner: github.User{
   157  					Login: "kubernetes",
   158  				},
   159  				Name: "kubernetes",
   160  			},
   161  		},
   162  		User: github.User{
   163  			Login: "foo",
   164  		},
   165  	}
   166  
   167  	testcases := []struct {
   168  		name               string
   169  		prAction           github.PullRequestEventAction
   170  		merged             bool
   171  		mergeCommit        string
   172  		changes            []github.PullRequestChange
   173  		existConfigMaps    []runtime.Object
   174  		expectedConfigMaps []*coreapi.ConfigMap
   175  		config             *plugins.ConfigUpdater
   176  	}{
   177  		{
   178  			name:     "Opened PR, no update",
   179  			prAction: github.PullRequestActionOpened,
   180  			merged:   false,
   181  			changes: []github.PullRequestChange{
   182  				{
   183  					Filename:  "prow/config.yaml",
   184  					Additions: 1,
   185  				},
   186  			},
   187  			existConfigMaps: []runtime.Object{},
   188  		},
   189  		{
   190  			name:   "Opened PR, not merged, no update",
   191  			merged: false,
   192  			changes: []github.PullRequestChange{
   193  				{
   194  					Filename:  "prow/config.yaml",
   195  					Additions: 1,
   196  				},
   197  			},
   198  			existConfigMaps: []runtime.Object{},
   199  		},
   200  		{
   201  			name:     "Closed PR, no prow changes, no update",
   202  			prAction: github.PullRequestActionClosed,
   203  			merged:   false,
   204  			changes: []github.PullRequestChange{
   205  				{
   206  					Filename:  "foo.txt",
   207  					Additions: 1,
   208  				},
   209  			},
   210  			existConfigMaps: []runtime.Object{},
   211  		},
   212  		{
   213  			name:     "For whatever reason no merge commit SHA",
   214  			prAction: github.PullRequestActionClosed,
   215  			merged:   true,
   216  			changes: []github.PullRequestChange{
   217  				{
   218  					Filename:  "prow/config.yaml",
   219  					Additions: 1,
   220  				},
   221  			},
   222  			existConfigMaps: []runtime.Object{},
   223  		},
   224  		{
   225  			name:        "changed config.yaml, 1 update",
   226  			prAction:    github.PullRequestActionClosed,
   227  			merged:      true,
   228  			mergeCommit: "12345",
   229  			changes: []github.PullRequestChange{
   230  				{
   231  					Filename:  "prow/config.yaml",
   232  					Additions: 1,
   233  				},
   234  			},
   235  			existConfigMaps: []runtime.Object{
   236  				&coreapi.ConfigMap{
   237  					ObjectMeta: metav1.ObjectMeta{
   238  						Name:      "config",
   239  						Namespace: defaultNamespace,
   240  						Labels: map[string]string{
   241  							"app.kubernetes.io/name":      "prow",
   242  							"app.kubernetes.io/component": "updateconfig-plugin",
   243  						},
   244  					},
   245  					Data: map[string]string{
   246  						"VERSION":     "12345",
   247  						"config.yaml": "old-config",
   248  					},
   249  				},
   250  			},
   251  			expectedConfigMaps: []*coreapi.ConfigMap{
   252  				{
   253  					ObjectMeta: metav1.ObjectMeta{
   254  						Name:      "config",
   255  						Namespace: defaultNamespace,
   256  						Labels: map[string]string{
   257  							"app.kubernetes.io/name":      "prow",
   258  							"app.kubernetes.io/component": "updateconfig-plugin",
   259  						},
   260  					},
   261  					Data: map[string]string{
   262  						"VERSION":     "12345",
   263  						"config.yaml": "new-config",
   264  					},
   265  				},
   266  			},
   267  		},
   268  		{
   269  			name:        "changed config.yaml, existed configmap, 1 update",
   270  			prAction:    github.PullRequestActionClosed,
   271  			merged:      true,
   272  			mergeCommit: "12345",
   273  			changes: []github.PullRequestChange{
   274  				{
   275  					Filename:  "prow/config.yaml",
   276  					Additions: 1,
   277  				},
   278  			},
   279  			existConfigMaps: []runtime.Object{
   280  				&coreapi.ConfigMap{
   281  					ObjectMeta: metav1.ObjectMeta{
   282  						Name:      "config",
   283  						Namespace: defaultNamespace,
   284  						Labels: map[string]string{
   285  							"app.kubernetes.io/name":      "prow",
   286  							"app.kubernetes.io/component": "updateconfig-plugin",
   287  						},
   288  					},
   289  					Data: map[string]string{
   290  						"config.yaml": "old-config",
   291  					},
   292  				},
   293  			},
   294  			expectedConfigMaps: []*coreapi.ConfigMap{
   295  				{
   296  					ObjectMeta: metav1.ObjectMeta{
   297  						Name:      "config",
   298  						Namespace: defaultNamespace,
   299  						Labels: map[string]string{
   300  							"app.kubernetes.io/name":      "prow",
   301  							"app.kubernetes.io/component": "updateconfig-plugin",
   302  						},
   303  					},
   304  					Data: map[string]string{
   305  						"config.yaml": "new-config",
   306  						"VERSION":     "12345",
   307  					},
   308  				},
   309  			},
   310  		},
   311  		{
   312  			name:        "changed plugins.yaml, 1 update with custom key",
   313  			prAction:    github.PullRequestActionClosed,
   314  			merged:      true,
   315  			mergeCommit: "12345",
   316  			changes: []github.PullRequestChange{
   317  				{
   318  					Filename:  "prow/plugins.yaml",
   319  					Additions: 1,
   320  				},
   321  			},
   322  			existConfigMaps: []runtime.Object{
   323  				&coreapi.ConfigMap{
   324  					ObjectMeta: metav1.ObjectMeta{
   325  						Name:      "plugins",
   326  						Namespace: defaultNamespace,
   327  						Labels: map[string]string{
   328  							"app.kubernetes.io/name":      "prow",
   329  							"app.kubernetes.io/component": "updateconfig-plugin",
   330  						},
   331  					},
   332  					Data: map[string]string{
   333  						"test-key": "old-plugins",
   334  					},
   335  				},
   336  			},
   337  			expectedConfigMaps: []*coreapi.ConfigMap{
   338  				{
   339  					ObjectMeta: metav1.ObjectMeta{
   340  						Name:      "plugins",
   341  						Namespace: defaultNamespace,
   342  						Labels: map[string]string{
   343  							"app.kubernetes.io/name":      "prow",
   344  							"app.kubernetes.io/component": "updateconfig-plugin",
   345  						},
   346  					},
   347  					Data: map[string]string{
   348  						"test-key": "new-plugins",
   349  						"VERSION":  "12345",
   350  					},
   351  				},
   352  			},
   353  		},
   354  		{
   355  			name:        "changed resources.yaml, 1 update with custom namespace",
   356  			prAction:    github.PullRequestActionClosed,
   357  			merged:      true,
   358  			mergeCommit: "12345",
   359  			changes: []github.PullRequestChange{
   360  				{
   361  					Filename:  "boskos/resources.yaml",
   362  					Additions: 1,
   363  				},
   364  			},
   365  			existConfigMaps: []runtime.Object{
   366  				&coreapi.ConfigMap{
   367  					ObjectMeta: metav1.ObjectMeta{
   368  						Name:      "boskos-config",
   369  						Namespace: "boskos",
   370  						Labels: map[string]string{
   371  							"app.kubernetes.io/name":      "prow",
   372  							"app.kubernetes.io/component": "updateconfig-plugin",
   373  						},
   374  					},
   375  					Data: map[string]string{
   376  						"resources.yaml": "old-boskos-config",
   377  					},
   378  				},
   379  			},
   380  			expectedConfigMaps: []*coreapi.ConfigMap{
   381  				{
   382  					ObjectMeta: metav1.ObjectMeta{
   383  						Name:      "boskos-config",
   384  						Namespace: "boskos",
   385  						Labels: map[string]string{
   386  							"app.kubernetes.io/name":      "prow",
   387  							"app.kubernetes.io/component": "updateconfig-plugin",
   388  						},
   389  					},
   390  					Data: map[string]string{
   391  						"resources.yaml": "new-boskos-config",
   392  						"VERSION":        "12345",
   393  					},
   394  				},
   395  			},
   396  		},
   397  		{
   398  			name:        "changed config.yaml, plugins.yaml and resources.yaml, 3 update",
   399  			prAction:    github.PullRequestActionClosed,
   400  			merged:      true,
   401  			mergeCommit: "12345",
   402  			changes: []github.PullRequestChange{
   403  				{
   404  					Filename:  "prow/plugins.yaml",
   405  					Additions: 1,
   406  				},
   407  				{
   408  					Filename:  "prow/config.yaml",
   409  					Additions: 1,
   410  				},
   411  				{
   412  					Filename:  "boskos/resources.yaml",
   413  					Additions: 1,
   414  				},
   415  			},
   416  			existConfigMaps: []runtime.Object{
   417  				&coreapi.ConfigMap{
   418  					ObjectMeta: metav1.ObjectMeta{
   419  						Name:      "config",
   420  						Namespace: defaultNamespace,
   421  						Labels: map[string]string{
   422  							"app.kubernetes.io/name":      "prow",
   423  							"app.kubernetes.io/component": "updateconfig-plugin",
   424  						},
   425  					},
   426  					Data: map[string]string{
   427  						"config.yaml": "old-config",
   428  					},
   429  				},
   430  				&coreapi.ConfigMap{
   431  					ObjectMeta: metav1.ObjectMeta{
   432  						Name:      "plugins",
   433  						Namespace: defaultNamespace,
   434  						Labels: map[string]string{
   435  							"app.kubernetes.io/name":      "prow",
   436  							"app.kubernetes.io/component": "updateconfig-plugin",
   437  						},
   438  					},
   439  					Data: map[string]string{
   440  						"test-key": "old-plugins",
   441  					},
   442  				},
   443  				&coreapi.ConfigMap{
   444  					ObjectMeta: metav1.ObjectMeta{
   445  						Name:      "boskos-config",
   446  						Namespace: "boskos",
   447  					},
   448  					Data: map[string]string{
   449  						"resources.yaml": "old-boskos-config",
   450  					},
   451  				},
   452  			},
   453  			expectedConfigMaps: []*coreapi.ConfigMap{
   454  				{
   455  					ObjectMeta: metav1.ObjectMeta{
   456  						Name:      "config",
   457  						Namespace: defaultNamespace,
   458  						Labels: map[string]string{
   459  							"app.kubernetes.io/name":      "prow",
   460  							"app.kubernetes.io/component": "updateconfig-plugin",
   461  						},
   462  					},
   463  					Data: map[string]string{
   464  						"config.yaml": "new-config",
   465  						"VERSION":     "12345",
   466  					},
   467  				},
   468  				{
   469  					ObjectMeta: metav1.ObjectMeta{
   470  						Name:      "plugins",
   471  						Namespace: defaultNamespace,
   472  						Labels: map[string]string{
   473  							"app.kubernetes.io/name":      "prow",
   474  							"app.kubernetes.io/component": "updateconfig-plugin",
   475  						},
   476  					},
   477  					Data: map[string]string{
   478  						"test-key": "new-plugins",
   479  						"VERSION":  "12345",
   480  					},
   481  				},
   482  				{
   483  					ObjectMeta: metav1.ObjectMeta{
   484  						Name:      "boskos-config",
   485  						Namespace: "boskos",
   486  						Labels: map[string]string{
   487  							"app.kubernetes.io/name":      "prow",
   488  							"app.kubernetes.io/component": "updateconfig-plugin",
   489  						},
   490  					},
   491  					Data: map[string]string{
   492  						"resources.yaml": "new-boskos-config",
   493  						"VERSION":        "12345",
   494  					},
   495  				},
   496  			},
   497  		},
   498  		{
   499  			name:        "edited both config/foo.yaml and config/bar.yaml, 2 update",
   500  			prAction:    github.PullRequestActionClosed,
   501  			merged:      true,
   502  			mergeCommit: "12345",
   503  			changes: []github.PullRequestChange{
   504  				{
   505  					Filename:  "config/foo.yaml",
   506  					Additions: 1,
   507  				},
   508  				{
   509  					Filename:  "config/bar.yaml",
   510  					Additions: 1,
   511  				},
   512  			},
   513  			existConfigMaps: []runtime.Object{
   514  				&coreapi.ConfigMap{
   515  					ObjectMeta: metav1.ObjectMeta{
   516  						Name:      "multikey-config",
   517  						Namespace: defaultNamespace,
   518  						Labels: map[string]string{
   519  							"app.kubernetes.io/name":      "prow",
   520  							"app.kubernetes.io/component": "updateconfig-plugin",
   521  						},
   522  					},
   523  					Data: map[string]string{
   524  						"foo.yaml": "old-foo-config",
   525  						"bar.yaml": "old-bar-config",
   526  					},
   527  				},
   528  			},
   529  			expectedConfigMaps: []*coreapi.ConfigMap{
   530  				{
   531  					ObjectMeta: metav1.ObjectMeta{
   532  						Name:      "multikey-config",
   533  						Namespace: defaultNamespace,
   534  						Labels: map[string]string{
   535  							"app.kubernetes.io/name":      "prow",
   536  							"app.kubernetes.io/component": "updateconfig-plugin",
   537  						},
   538  					},
   539  					Data: map[string]string{
   540  						"foo.yaml": "new-foo-config",
   541  						"bar.yaml": "new-bar-config",
   542  						"VERSION":  "12345",
   543  					},
   544  				},
   545  			},
   546  		},
   547  		{
   548  			name:        "edited config/foo.yaml, 1 update",
   549  			prAction:    github.PullRequestActionClosed,
   550  			merged:      true,
   551  			mergeCommit: "12345",
   552  			changes: []github.PullRequestChange{
   553  				{
   554  					Filename:  "config/foo.yaml",
   555  					Status:    "modified",
   556  					Additions: 1,
   557  				},
   558  			},
   559  			existConfigMaps: []runtime.Object{
   560  				&coreapi.ConfigMap{
   561  					ObjectMeta: metav1.ObjectMeta{
   562  						Name:      "multikey-config",
   563  						Namespace: defaultNamespace,
   564  						Labels: map[string]string{
   565  							"app.kubernetes.io/name":      "prow",
   566  							"app.kubernetes.io/component": "updateconfig-plugin",
   567  						},
   568  					},
   569  					Data: map[string]string{
   570  						"foo.yaml": "old-foo-config",
   571  						"bar.yaml": "old-bar-config",
   572  					},
   573  				},
   574  			},
   575  			expectedConfigMaps: []*coreapi.ConfigMap{
   576  				{
   577  					ObjectMeta: metav1.ObjectMeta{
   578  						Name:      "multikey-config",
   579  						Namespace: defaultNamespace,
   580  						Labels: map[string]string{
   581  							"app.kubernetes.io/name":      "prow",
   582  							"app.kubernetes.io/component": "updateconfig-plugin",
   583  						},
   584  					},
   585  					Data: map[string]string{
   586  						"foo.yaml": "new-foo-config",
   587  						"bar.yaml": "old-bar-config",
   588  						"VERSION":  "12345",
   589  					},
   590  				},
   591  			},
   592  		},
   593  		{
   594  			name:        "remove config/foo.yaml, 1 update",
   595  			prAction:    github.PullRequestActionClosed,
   596  			merged:      true,
   597  			mergeCommit: "12345",
   598  			changes: []github.PullRequestChange{
   599  				{
   600  					Filename: "config/foo.yaml",
   601  					Status:   "removed",
   602  				},
   603  			},
   604  			existConfigMaps: []runtime.Object{
   605  				&coreapi.ConfigMap{
   606  					ObjectMeta: metav1.ObjectMeta{
   607  						Name:      "multikey-config",
   608  						Namespace: defaultNamespace,
   609  						Labels: map[string]string{
   610  							"app.kubernetes.io/name":      "prow",
   611  							"app.kubernetes.io/component": "updateconfig-plugin",
   612  						},
   613  					},
   614  					Data: map[string]string{
   615  						"foo.yaml": "old-foo-config",
   616  						"bar.yaml": "old-bar-config",
   617  					},
   618  				},
   619  			},
   620  			expectedConfigMaps: []*coreapi.ConfigMap{
   621  				{
   622  					ObjectMeta: metav1.ObjectMeta{
   623  						Name:      "multikey-config",
   624  						Namespace: defaultNamespace,
   625  						Labels: map[string]string{
   626  							"app.kubernetes.io/name":      "prow",
   627  							"app.kubernetes.io/component": "updateconfig-plugin",
   628  						},
   629  					},
   630  					Data: map[string]string{
   631  						"bar.yaml": "old-bar-config",
   632  						"VERSION":  "12345",
   633  					},
   634  				},
   635  			},
   636  		},
   637  		{
   638  			name:        "edited dir/subdir/fejtaverse/krzyzacy.yaml, 1 update",
   639  			prAction:    github.PullRequestActionClosed,
   640  			merged:      true,
   641  			mergeCommit: "12345",
   642  			changes: []github.PullRequestChange{
   643  				{
   644  					Filename:  "dir/subdir/fejtaverse/krzyzacy.yaml",
   645  					Status:    "modified",
   646  					Additions: 1,
   647  				},
   648  			},
   649  			existConfigMaps: []runtime.Object{
   650  				&coreapi.ConfigMap{
   651  					ObjectMeta: metav1.ObjectMeta{
   652  						Name:      "glob-config",
   653  						Namespace: defaultNamespace,
   654  						Labels: map[string]string{
   655  							"app.kubernetes.io/name":      "prow",
   656  							"app.kubernetes.io/component": "updateconfig-plugin",
   657  						},
   658  					},
   659  					Data: map[string]string{
   660  						"fejta.yaml":    "old-fejta-config",
   661  						"krzyzacy.yaml": "old-krzyzacy-config",
   662  					},
   663  				},
   664  			},
   665  			expectedConfigMaps: []*coreapi.ConfigMap{
   666  				{
   667  					ObjectMeta: metav1.ObjectMeta{
   668  						Name:      "glob-config",
   669  						Namespace: defaultNamespace,
   670  						Labels: map[string]string{
   671  							"app.kubernetes.io/name":      "prow",
   672  							"app.kubernetes.io/component": "updateconfig-plugin",
   673  						},
   674  					},
   675  					Data: map[string]string{
   676  						"fejta.yaml":    "old-fejta-config",
   677  						"krzyzacy.yaml": "new-krzyzacy-config",
   678  						"VERSION":       "12345",
   679  					},
   680  				},
   681  			},
   682  		},
   683  		{
   684  			name:        "renamed dir/subdir/fejtaverse/krzyzacy.yaml, 1 update",
   685  			prAction:    github.PullRequestActionClosed,
   686  			merged:      true,
   687  			mergeCommit: "54321",
   688  			changes: []github.PullRequestChange{
   689  				{
   690  					Filename:         "dir/subdir/fejtaverse/fejtabot.yaml",
   691  					PreviousFilename: "dir/subdir/fejtaverse/krzyzacy.yaml",
   692  					Status:           "renamed",
   693  					Additions:        1,
   694  				},
   695  			},
   696  			existConfigMaps: []runtime.Object{
   697  				&coreapi.ConfigMap{
   698  					ObjectMeta: metav1.ObjectMeta{
   699  						Name:      "glob-config",
   700  						Namespace: defaultNamespace,
   701  						Labels: map[string]string{
   702  							"app.kubernetes.io/name":      "prow",
   703  							"app.kubernetes.io/component": "updateconfig-plugin",
   704  						},
   705  					},
   706  					Data: map[string]string{
   707  						"krzyzacy.yaml": "old-krzyzacy-config",
   708  					},
   709  				},
   710  			},
   711  			expectedConfigMaps: []*coreapi.ConfigMap{
   712  				{
   713  					ObjectMeta: metav1.ObjectMeta{
   714  						Name:      "glob-config",
   715  						Namespace: defaultNamespace,
   716  						Labels: map[string]string{
   717  							"app.kubernetes.io/name":      "prow",
   718  							"app.kubernetes.io/component": "updateconfig-plugin",
   719  						},
   720  					},
   721  					Data: map[string]string{
   722  						"fejtabot.yaml": "new-fejtabot-config",
   723  						"VERSION":       "54321",
   724  					},
   725  				},
   726  			},
   727  		},
   728  		{
   729  			name:        "Renamed with UseFullPathAsKey set, old entry gets deleted",
   730  			prAction:    github.PullRequestActionClosed,
   731  			merged:      true,
   732  			mergeCommit: "54321",
   733  			changes: []github.PullRequestChange{
   734  				{
   735  					Filename:         "dir/subdir/fejtaverse/fejtabot.yaml",
   736  					PreviousFilename: "dir/subdir/fejtaverse/krzyzacy.yaml",
   737  					Status:           "renamed",
   738  					Additions:        1,
   739  				},
   740  			},
   741  			existConfigMaps: []runtime.Object{
   742  				&coreapi.ConfigMap{
   743  					ObjectMeta: metav1.ObjectMeta{
   744  						Name:      "glob-config",
   745  						Namespace: defaultNamespace,
   746  						Labels: map[string]string{
   747  							"app.kubernetes.io/name":      "prow",
   748  							"app.kubernetes.io/component": "updateconfig-plugin",
   749  						},
   750  					},
   751  					Data: map[string]string{
   752  						"dir-subdir-fejtaverse-krzyzacy.yaml": "retired",
   753  					},
   754  				},
   755  			},
   756  			expectedConfigMaps: []*coreapi.ConfigMap{
   757  				{
   758  					ObjectMeta: metav1.ObjectMeta{
   759  						Name:      "config",
   760  						Namespace: defaultNamespace,
   761  						Labels: map[string]string{
   762  							"app.kubernetes.io/name":      "prow",
   763  							"app.kubernetes.io/component": "updateconfig-plugin",
   764  						},
   765  					},
   766  					Data: map[string]string{
   767  						"dir-subdir-fejtaverse-fejtabot.yaml": "new-fejtabot-config",
   768  						"VERSION":                             "54321",
   769  					},
   770  				},
   771  			},
   772  			config: &plugins.ConfigUpdater{
   773  				Maps: map[string]plugins.ConfigMapSpec{
   774  					"dir/subdir/**/*.yaml": {
   775  						Name:             "config",
   776  						UseFullPathAsKey: true,
   777  					},
   778  				},
   779  			},
   780  		},
   781  		{
   782  			name:        "add delete edit glob config, 3 update",
   783  			prAction:    github.PullRequestActionClosed,
   784  			merged:      true,
   785  			mergeCommit: "12345",
   786  			changes: []github.PullRequestChange{
   787  				{
   788  					Filename:  "dir/subdir/fejta.yaml",
   789  					Status:    "modified",
   790  					Additions: 1,
   791  				},
   792  				{
   793  					Filename:  "dir/subdir/fejtaverse/sig-foo/added.yaml",
   794  					Status:    "added",
   795  					Additions: 1,
   796  				},
   797  				{
   798  					Filename: "dir/subdir/fejtaverse/sig-bar/removed.yaml",
   799  					Status:   "removed",
   800  				},
   801  			},
   802  			existConfigMaps: []runtime.Object{
   803  				&coreapi.ConfigMap{
   804  					ObjectMeta: metav1.ObjectMeta{
   805  						Name:      "glob-config",
   806  						Namespace: defaultNamespace,
   807  						Labels: map[string]string{
   808  							"app.kubernetes.io/name":      "prow",
   809  							"app.kubernetes.io/component": "updateconfig-plugin",
   810  						},
   811  					},
   812  					Data: map[string]string{
   813  						"fejta.yaml":    "old-fejta-config",
   814  						"krzyzacy.yaml": "old-krzyzacy-config",
   815  						"removed.yaml":  "old-removed-config",
   816  					},
   817  				},
   818  			},
   819  			expectedConfigMaps: []*coreapi.ConfigMap{
   820  				{
   821  					ObjectMeta: metav1.ObjectMeta{
   822  						Name:      "glob-config",
   823  						Namespace: defaultNamespace,
   824  						Labels: map[string]string{
   825  							"app.kubernetes.io/name":      "prow",
   826  							"app.kubernetes.io/component": "updateconfig-plugin",
   827  						},
   828  					},
   829  					Data: map[string]string{
   830  						"fejta.yaml":    "new-fejta-config",
   831  						"krzyzacy.yaml": "old-krzyzacy-config",
   832  						"added.yaml":    "new-added-config",
   833  						"VERSION":       "12345",
   834  					},
   835  				},
   836  			},
   837  		},
   838  		{
   839  			name:        "config changes without a backing configmap causes creation",
   840  			prAction:    github.PullRequestActionClosed,
   841  			merged:      true,
   842  			mergeCommit: "12345",
   843  			changes: []github.PullRequestChange{
   844  				{
   845  					Filename:  "prow/config.yaml",
   846  					Status:    "modified",
   847  					Additions: 1,
   848  				},
   849  			},
   850  			existConfigMaps: []runtime.Object{},
   851  			expectedConfigMaps: []*coreapi.ConfigMap{
   852  				{
   853  					ObjectMeta: metav1.ObjectMeta{
   854  						Name:      "config",
   855  						Namespace: defaultNamespace,
   856  						Labels: map[string]string{
   857  							"app.kubernetes.io/name":      "prow",
   858  							"app.kubernetes.io/component": "updateconfig-plugin",
   859  						},
   860  					},
   861  					Data: map[string]string{
   862  						"config.yaml": "new-config",
   863  						"VERSION":     "12345",
   864  					},
   865  				},
   866  			},
   867  		},
   868  		{
   869  			name:        "gzips all content if the top level gzip flag is set",
   870  			prAction:    github.PullRequestActionClosed,
   871  			merged:      true,
   872  			mergeCommit: "12345",
   873  			changes: []github.PullRequestChange{
   874  				{
   875  					Filename:  "prow/config.yaml",
   876  					Status:    "modified",
   877  					Additions: 1,
   878  				},
   879  			},
   880  			existConfigMaps: []runtime.Object{},
   881  			expectedConfigMaps: []*coreapi.ConfigMap{
   882  				{
   883  					ObjectMeta: metav1.ObjectMeta{
   884  						Name:      "config",
   885  						Namespace: defaultNamespace,
   886  						Labels: map[string]string{
   887  							"app.kubernetes.io/name":      "prow",
   888  							"app.kubernetes.io/component": "updateconfig-plugin",
   889  						},
   890  					},
   891  					BinaryData: map[string][]byte{
   892  						"config.yaml": {31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 202, 75, 45, 215, 77, 206, 207, 75, 203, 76, 7, 4, 0, 0, 255, 255, 84, 214, 231, 87, 10, 0, 0, 0},
   893  					},
   894  					Data: map[string]string{
   895  						"VERSION": "12345",
   896  					},
   897  				},
   898  			},
   899  			config: &plugins.ConfigUpdater{
   900  				GZIP: true,
   901  				Maps: map[string]plugins.ConfigMapSpec{
   902  					"prow/config.yaml": {
   903  						Name: "config",
   904  					},
   905  					"prow/plugins.yaml": {
   906  						Name: "plugins",
   907  						Key:  "test-key",
   908  					},
   909  				},
   910  			},
   911  		},
   912  		{
   913  			name:        "gzips all content except one marked false if the top level gzip flag is set",
   914  			prAction:    github.PullRequestActionClosed,
   915  			merged:      true,
   916  			mergeCommit: "12345",
   917  			changes: []github.PullRequestChange{
   918  				{
   919  					Filename:  "prow/config.yaml",
   920  					Status:    "modified",
   921  					Additions: 1,
   922  				},
   923  				{
   924  					Filename:  "prow/plugins.yaml",
   925  					Status:    "modified",
   926  					Additions: 1,
   927  				},
   928  			},
   929  			existConfigMaps: []runtime.Object{},
   930  			expectedConfigMaps: []*coreapi.ConfigMap{
   931  				{
   932  					ObjectMeta: metav1.ObjectMeta{
   933  						Name:      "config",
   934  						Namespace: defaultNamespace,
   935  						Labels: map[string]string{
   936  							"app.kubernetes.io/name":      "prow",
   937  							"app.kubernetes.io/component": "updateconfig-plugin",
   938  						},
   939  					},
   940  					BinaryData: map[string][]byte{
   941  						"config.yaml": {31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 202, 75, 45, 215, 77, 206, 207, 75, 203, 76, 7, 4, 0, 0, 255, 255, 84, 214, 231, 87, 10, 0, 0, 0},
   942  					},
   943  					Data: map[string]string{
   944  						"VERSION": "12345",
   945  					},
   946  				},
   947  				{
   948  					ObjectMeta: metav1.ObjectMeta{
   949  						Name:      "plugins",
   950  						Namespace: defaultNamespace,
   951  						Labels: map[string]string{
   952  							"app.kubernetes.io/name":      "prow",
   953  							"app.kubernetes.io/component": "updateconfig-plugin",
   954  						},
   955  					},
   956  					Data: map[string]string{
   957  						"plugins.yaml": "new-plugins",
   958  						"VERSION":      "12345",
   959  					},
   960  				},
   961  			},
   962  			config: &plugins.ConfigUpdater{
   963  				GZIP: true,
   964  				Maps: map[string]plugins.ConfigMapSpec{
   965  					"prow/config.yaml": {
   966  						Name: "config",
   967  					},
   968  					"prow/plugins.yaml": {
   969  						Name: "plugins",
   970  						GZIP: boolPtr(false),
   971  					},
   972  				},
   973  			},
   974  		},
   975  		{
   976  			name:        "gzips only one marked file if the top level gzip flag is set to false",
   977  			prAction:    github.PullRequestActionClosed,
   978  			merged:      true,
   979  			mergeCommit: "12345",
   980  			changes: []github.PullRequestChange{
   981  				{
   982  					Filename:  "prow/config.yaml",
   983  					Status:    "modified",
   984  					Additions: 1,
   985  				},
   986  				{
   987  					Filename:  "prow/plugins.yaml",
   988  					Status:    "modified",
   989  					Additions: 1,
   990  				},
   991  			},
   992  			existConfigMaps: []runtime.Object{},
   993  			expectedConfigMaps: []*coreapi.ConfigMap{
   994  				{
   995  					ObjectMeta: metav1.ObjectMeta{
   996  						Name:      "config",
   997  						Namespace: defaultNamespace,
   998  						Labels: map[string]string{
   999  							"app.kubernetes.io/name":      "prow",
  1000  							"app.kubernetes.io/component": "updateconfig-plugin",
  1001  						},
  1002  					},
  1003  					BinaryData: map[string][]byte{
  1004  						"config.yaml": {31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 202, 75, 45, 215, 77, 206, 207, 75, 203, 76, 7, 4, 0, 0, 255, 255, 84, 214, 231, 87, 10, 0, 0, 0},
  1005  					},
  1006  					Data: map[string]string{
  1007  						"VERSION": "12345",
  1008  					},
  1009  				},
  1010  				{
  1011  					ObjectMeta: metav1.ObjectMeta{
  1012  						Name:      "plugins",
  1013  						Namespace: defaultNamespace,
  1014  						Labels: map[string]string{
  1015  							"app.kubernetes.io/name":      "prow",
  1016  							"app.kubernetes.io/component": "updateconfig-plugin",
  1017  						},
  1018  					},
  1019  					Data: map[string]string{
  1020  						"plugins.yaml": "new-plugins",
  1021  						"VERSION":      "12345",
  1022  					},
  1023  				},
  1024  			},
  1025  			config: &plugins.ConfigUpdater{
  1026  				GZIP: false,
  1027  				Maps: map[string]plugins.ConfigMapSpec{
  1028  					"prow/config.yaml": {
  1029  						Name: "config",
  1030  						GZIP: boolPtr(true),
  1031  					},
  1032  					"prow/plugins.yaml": {
  1033  						Name: "plugins",
  1034  					},
  1035  				},
  1036  			},
  1037  		},
  1038  		{
  1039  			name:        "adds both binary and text keys for a single configmap",
  1040  			prAction:    github.PullRequestActionClosed,
  1041  			merged:      true,
  1042  			mergeCommit: "12345",
  1043  			changes: []github.PullRequestChange{
  1044  				{
  1045  					Filename:  "prow/config.yaml",
  1046  					Status:    "modified",
  1047  					Additions: 1,
  1048  				},
  1049  				{
  1050  					Filename:  "prow/binary.yaml",
  1051  					Status:    "modified",
  1052  					Additions: 1,
  1053  				},
  1054  			},
  1055  			existConfigMaps: []runtime.Object{},
  1056  			expectedConfigMaps: []*coreapi.ConfigMap{
  1057  				{
  1058  					ObjectMeta: metav1.ObjectMeta{
  1059  						Name:      "config",
  1060  						Namespace: defaultNamespace,
  1061  						Labels: map[string]string{
  1062  							"app.kubernetes.io/name":      "prow",
  1063  							"app.kubernetes.io/component": "updateconfig-plugin",
  1064  						},
  1065  					},
  1066  					Data: map[string]string{
  1067  						"config.yaml": "new-config",
  1068  						"VERSION":     "12345",
  1069  					},
  1070  					BinaryData: map[string][]byte{
  1071  						"binary.yaml": []byte("new-binary\x00\xFF\xFF"),
  1072  					},
  1073  				},
  1074  			},
  1075  			config: &plugins.ConfigUpdater{
  1076  				Maps: map[string]plugins.ConfigMapSpec{
  1077  					"prow/*.yaml": {
  1078  						Name: "config",
  1079  					},
  1080  				},
  1081  			},
  1082  		},
  1083  		{
  1084  			name:        "both yaml and yml",
  1085  			prAction:    github.PullRequestActionClosed,
  1086  			merged:      true,
  1087  			mergeCommit: "12345",
  1088  			changes: []github.PullRequestChange{
  1089  				{
  1090  					Filename:  "prow/config.yaml",
  1091  					Status:    "modified",
  1092  					Additions: 1,
  1093  				},
  1094  				{
  1095  					Filename:  "prow/binary.yml",
  1096  					Status:    "modified",
  1097  					Additions: 1,
  1098  				},
  1099  			},
  1100  			existConfigMaps: []runtime.Object{},
  1101  			expectedConfigMaps: []*coreapi.ConfigMap{
  1102  				{
  1103  					ObjectMeta: metav1.ObjectMeta{
  1104  						Name:      "config",
  1105  						Namespace: defaultNamespace,
  1106  						Labels: map[string]string{
  1107  							"app.kubernetes.io/name":      "prow",
  1108  							"app.kubernetes.io/component": "updateconfig-plugin",
  1109  						},
  1110  					},
  1111  					Data: map[string]string{
  1112  						"config.yaml": "new-config",
  1113  						"VERSION":     "12345",
  1114  					},
  1115  					BinaryData: map[string][]byte{
  1116  						"binary.yml": []byte("new-binary\x00\xFF\xFF"),
  1117  					},
  1118  				},
  1119  			},
  1120  			config: &plugins.ConfigUpdater{
  1121  				Maps: map[string]plugins.ConfigMapSpec{
  1122  					"prow/*.{yaml,yml}": {
  1123  						Name: "config",
  1124  					},
  1125  				},
  1126  			},
  1127  		},
  1128  		{
  1129  			name:        "converts a text key to a binary key when it becomes binary",
  1130  			prAction:    github.PullRequestActionClosed,
  1131  			merged:      true,
  1132  			mergeCommit: "12345",
  1133  			changes: []github.PullRequestChange{
  1134  				{
  1135  					Filename:  "prow/becoming-binary.yaml",
  1136  					Status:    "modified",
  1137  					Additions: 1,
  1138  				},
  1139  			},
  1140  			existConfigMaps: []runtime.Object{
  1141  				&coreapi.ConfigMap{
  1142  					ObjectMeta: metav1.ObjectMeta{
  1143  						Name:      "config",
  1144  						Namespace: defaultNamespace,
  1145  						Labels: map[string]string{
  1146  							"app.kubernetes.io/name":      "prow",
  1147  							"app.kubernetes.io/component": "updateconfig-plugin",
  1148  						},
  1149  					},
  1150  					Data: map[string]string{
  1151  						"becoming-binary.yaml": "not-yet-binary",
  1152  					},
  1153  				},
  1154  			},
  1155  			expectedConfigMaps: []*coreapi.ConfigMap{
  1156  				{
  1157  					ObjectMeta: metav1.ObjectMeta{
  1158  						Name:      "config",
  1159  						Namespace: defaultNamespace,
  1160  						Labels: map[string]string{
  1161  							"app.kubernetes.io/name":      "prow",
  1162  							"app.kubernetes.io/component": "updateconfig-plugin",
  1163  						},
  1164  					},
  1165  					BinaryData: map[string][]byte{
  1166  						"becoming-binary.yaml": []byte("now-binary\x00\xFF\xFF"),
  1167  					},
  1168  					Data: map[string]string{
  1169  						"VERSION": "12345",
  1170  					},
  1171  				},
  1172  			},
  1173  			config: &plugins.ConfigUpdater{
  1174  				Maps: map[string]plugins.ConfigMapSpec{
  1175  					"prow/*.yaml": {
  1176  						Name: "config",
  1177  					},
  1178  				},
  1179  			},
  1180  		},
  1181  		{
  1182  			name:        "converts a binary key to a text key when it becomes text",
  1183  			prAction:    github.PullRequestActionClosed,
  1184  			merged:      true,
  1185  			mergeCommit: "12345",
  1186  			changes: []github.PullRequestChange{
  1187  				{
  1188  					Filename:  "prow/becoming-text.yaml",
  1189  					Status:    "modified",
  1190  					Additions: 1,
  1191  				},
  1192  			},
  1193  			existConfigMaps: []runtime.Object{
  1194  				&coreapi.ConfigMap{
  1195  					ObjectMeta: metav1.ObjectMeta{
  1196  						Name:      "config",
  1197  						Namespace: defaultNamespace,
  1198  						Labels: map[string]string{
  1199  							"app.kubernetes.io/name":      "prow",
  1200  							"app.kubernetes.io/component": "updateconfig-plugin",
  1201  						},
  1202  					},
  1203  					BinaryData: map[string][]byte{
  1204  						"becoming-text.yaml": []byte("not-yet-text\x00\xFF\xFF"),
  1205  					},
  1206  				},
  1207  			},
  1208  			expectedConfigMaps: []*coreapi.ConfigMap{
  1209  				{
  1210  					ObjectMeta: metav1.ObjectMeta{
  1211  						Name:      "config",
  1212  						Namespace: defaultNamespace,
  1213  						Labels: map[string]string{
  1214  							"app.kubernetes.io/name":      "prow",
  1215  							"app.kubernetes.io/component": "updateconfig-plugin",
  1216  						},
  1217  					},
  1218  					Data: map[string]string{
  1219  						"becoming-text.yaml": "now-text",
  1220  						"VERSION":            "12345",
  1221  					},
  1222  					BinaryData: map[string][]uint8{},
  1223  				},
  1224  			},
  1225  			config: &plugins.ConfigUpdater{
  1226  				Maps: map[string]plugins.ConfigMapSpec{
  1227  					"prow/*.yaml": {
  1228  						Name: "config",
  1229  					},
  1230  				},
  1231  			},
  1232  		},
  1233  		{
  1234  			name:        "simultaneously converts text to binary and binary to text",
  1235  			prAction:    github.PullRequestActionClosed,
  1236  			merged:      true,
  1237  			mergeCommit: "12345",
  1238  			changes: []github.PullRequestChange{
  1239  				{
  1240  					Filename:  "prow/becoming-text.yaml",
  1241  					Status:    "modified",
  1242  					Additions: 1,
  1243  				},
  1244  				{
  1245  					Filename:  "prow/becoming-binary.yaml",
  1246  					Status:    "modified",
  1247  					Additions: 1,
  1248  				},
  1249  			},
  1250  			existConfigMaps: []runtime.Object{
  1251  				&coreapi.ConfigMap{
  1252  					ObjectMeta: metav1.ObjectMeta{
  1253  						Name:      "config",
  1254  						Namespace: defaultNamespace,
  1255  						Labels: map[string]string{
  1256  							"app.kubernetes.io/name":      "prow",
  1257  							"app.kubernetes.io/component": "updateconfig-plugin",
  1258  						},
  1259  					},
  1260  					BinaryData: map[string][]byte{
  1261  						"becoming-text.yaml": []byte("not-yet-text\x00\xFF\xFF"),
  1262  					},
  1263  					Data: map[string]string{
  1264  						"becoming-binary.yaml": "not-yet-binary",
  1265  					},
  1266  				},
  1267  			},
  1268  			expectedConfigMaps: []*coreapi.ConfigMap{
  1269  				{
  1270  					ObjectMeta: metav1.ObjectMeta{
  1271  						Name:      "config",
  1272  						Namespace: defaultNamespace,
  1273  						Labels: map[string]string{
  1274  							"app.kubernetes.io/name":      "prow",
  1275  							"app.kubernetes.io/component": "updateconfig-plugin",
  1276  						},
  1277  					},
  1278  					BinaryData: map[string][]byte{
  1279  						"becoming-binary.yaml": []byte("now-binary\x00\xFF\xFF"),
  1280  					},
  1281  					Data: map[string]string{
  1282  						"becoming-text.yaml": "now-text",
  1283  						"VERSION":            "12345",
  1284  					},
  1285  				},
  1286  			},
  1287  			config: &plugins.ConfigUpdater{
  1288  				Maps: map[string]plugins.ConfigMapSpec{
  1289  					"prow/*.yaml": {
  1290  						Name: "config",
  1291  					},
  1292  				},
  1293  			},
  1294  		},
  1295  		{
  1296  			name:        "correctly converts to binary when gzipping",
  1297  			prAction:    github.PullRequestActionClosed,
  1298  			merged:      true,
  1299  			mergeCommit: "12345",
  1300  			changes: []github.PullRequestChange{
  1301  				{
  1302  					Filename:  "prow/config.yaml",
  1303  					Status:    "modified",
  1304  					Additions: 1,
  1305  				},
  1306  			},
  1307  			existConfigMaps: []runtime.Object{
  1308  				&coreapi.ConfigMap{
  1309  					ObjectMeta: metav1.ObjectMeta{
  1310  						Name:      "config",
  1311  						Namespace: defaultNamespace,
  1312  						Labels: map[string]string{
  1313  							"app.kubernetes.io/name":      "prow",
  1314  							"app.kubernetes.io/component": "updateconfig-plugin",
  1315  						},
  1316  					},
  1317  					Data: map[string]string{
  1318  						"config.yaml": "old-config",
  1319  					},
  1320  				},
  1321  			},
  1322  			expectedConfigMaps: []*coreapi.ConfigMap{
  1323  				{
  1324  					ObjectMeta: metav1.ObjectMeta{
  1325  						Name:      "config",
  1326  						Namespace: defaultNamespace,
  1327  						Labels: map[string]string{
  1328  							"app.kubernetes.io/name":      "prow",
  1329  							"app.kubernetes.io/component": "updateconfig-plugin",
  1330  						},
  1331  					},
  1332  					BinaryData: map[string][]byte{
  1333  						"config.yaml": {31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 202, 75, 45, 215, 77, 206, 207, 75, 203, 76, 7, 4, 0, 0, 255, 255, 84, 214, 231, 87, 10, 0, 0, 0},
  1334  					},
  1335  					Data: map[string]string{
  1336  						"VERSION": "12345",
  1337  					},
  1338  				},
  1339  			},
  1340  			config: &plugins.ConfigUpdater{
  1341  				GZIP: true,
  1342  				Maps: map[string]plugins.ConfigMapSpec{
  1343  					"prow/*.yaml": {
  1344  						Name: "config",
  1345  					},
  1346  				},
  1347  			},
  1348  		},
  1349  		{
  1350  			name:        "correctly converts to text when ungzipping",
  1351  			prAction:    github.PullRequestActionClosed,
  1352  			merged:      true,
  1353  			mergeCommit: "12345",
  1354  			changes: []github.PullRequestChange{
  1355  				{
  1356  					Filename:  "prow/config.yaml",
  1357  					Status:    "modified",
  1358  					Additions: 1,
  1359  				},
  1360  			},
  1361  			existConfigMaps: []runtime.Object{
  1362  				&coreapi.ConfigMap{
  1363  					ObjectMeta: metav1.ObjectMeta{
  1364  						Name:      "config",
  1365  						Namespace: defaultNamespace,
  1366  						Labels: map[string]string{
  1367  							"app.kubernetes.io/name":      "prow",
  1368  							"app.kubernetes.io/component": "updateconfig-plugin",
  1369  						},
  1370  					},
  1371  					BinaryData: map[string][]byte{
  1372  						"config.yaml": {31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 202, 75, 45, 215, 77, 206, 207, 75, 203, 76, 7, 4, 0, 0, 255, 255, 84, 214, 231, 87, 10, 0, 0, 0},
  1373  					},
  1374  				},
  1375  			},
  1376  			expectedConfigMaps: []*coreapi.ConfigMap{
  1377  				{
  1378  					ObjectMeta: metav1.ObjectMeta{
  1379  						Name:      "config",
  1380  						Namespace: defaultNamespace,
  1381  						Labels: map[string]string{
  1382  							"app.kubernetes.io/name":      "prow",
  1383  							"app.kubernetes.io/component": "updateconfig-plugin",
  1384  						},
  1385  					},
  1386  					Data: map[string]string{
  1387  						"config.yaml": "new-config",
  1388  						"VERSION":     "12345",
  1389  					},
  1390  				},
  1391  			},
  1392  			config: &plugins.ConfigUpdater{
  1393  				GZIP: false,
  1394  				Maps: map[string]plugins.ConfigMapSpec{
  1395  					"prow/*.yaml": {
  1396  						Name: "config",
  1397  					},
  1398  				},
  1399  			},
  1400  		},
  1401  		{
  1402  			name:        "Uses the full path slash-separated when UseFullPathAsKey is set",
  1403  			prAction:    github.PullRequestActionClosed,
  1404  			merged:      true,
  1405  			mergeCommit: "12345",
  1406  			changes: []github.PullRequestChange{
  1407  				{
  1408  					Filename:  "prow/config.yaml",
  1409  					Status:    "modified",
  1410  					Additions: 1,
  1411  				},
  1412  			},
  1413  			expectedConfigMaps: []*coreapi.ConfigMap{
  1414  				{
  1415  					ObjectMeta: metav1.ObjectMeta{
  1416  						Name:      "config",
  1417  						Namespace: defaultNamespace,
  1418  						Labels: map[string]string{
  1419  							"app.kubernetes.io/name":      "prow",
  1420  							"app.kubernetes.io/component": "updateconfig-plugin",
  1421  						},
  1422  					},
  1423  					Data: map[string]string{
  1424  						"prow-config.yaml": "new-config",
  1425  						"VERSION":          "12345",
  1426  					},
  1427  				},
  1428  			},
  1429  			config: &plugins.ConfigUpdater{
  1430  				GZIP: false,
  1431  				Maps: map[string]plugins.ConfigMapSpec{
  1432  					"prow/*.yaml": {
  1433  						Name:             "config",
  1434  						UseFullPathAsKey: true,
  1435  					},
  1436  				},
  1437  			},
  1438  		},
  1439  		{
  1440  			name:        "Partitioned ConfigMaps actually partition",
  1441  			prAction:    github.PullRequestActionClosed,
  1442  			merged:      true,
  1443  			mergeCommit: "12345",
  1444  			changes: []github.PullRequestChange{
  1445  				{
  1446  					Filename:  "dir/subdir/fejta.yaml",
  1447  					Status:    "added",
  1448  					Additions: 1,
  1449  				},
  1450  				{
  1451  					Filename:  "dir/subdir/fejtaverse/sig-foo/added.yaml",
  1452  					Status:    "added",
  1453  					Additions: 1,
  1454  				},
  1455  				{
  1456  					Filename:  "dir/subdir/even.yaml",
  1457  					Status:    "added",
  1458  					Additions: 1,
  1459  				},
  1460  			},
  1461  			expectedConfigMaps: []*coreapi.ConfigMap{
  1462  				{
  1463  					ObjectMeta: metav1.ObjectMeta{
  1464  						Name:      "job-config-part-1",
  1465  						Namespace: defaultNamespace,
  1466  						Labels: map[string]string{
  1467  							"app.kubernetes.io/name":      "prow",
  1468  							"app.kubernetes.io/component": "updateconfig-plugin",
  1469  						},
  1470  					},
  1471  					Data: map[string]string{
  1472  						"even.yaml": "even SHA256",
  1473  						"VERSION":   "12345",
  1474  					},
  1475  				},
  1476  				{
  1477  					ObjectMeta: metav1.ObjectMeta{
  1478  						Name:      "job-config-part-2",
  1479  						Namespace: defaultNamespace,
  1480  						Labels: map[string]string{
  1481  							"app.kubernetes.io/name":      "prow",
  1482  							"app.kubernetes.io/component": "updateconfig-plugin",
  1483  						},
  1484  					},
  1485  					Data: map[string]string{
  1486  						"fejta.yaml": "new-fejta-config",
  1487  						"added.yaml": "new-added-config",
  1488  						"VERSION":    "12345",
  1489  					},
  1490  				},
  1491  			},
  1492  			config: &plugins.ConfigUpdater{
  1493  				Maps: map[string]plugins.ConfigMapSpec{
  1494  					"dir/**/*.yaml": {
  1495  						PartitionedNames: []string{"job-config-part-1", "job-config-part-2"},
  1496  					},
  1497  				},
  1498  			},
  1499  		},
  1500  	}
  1501  
  1502  	for _, tc := range testcases {
  1503  		log := logrus.WithField("plugin", pluginName)
  1504  		event := github.PullRequestEvent{
  1505  			Action:      tc.prAction,
  1506  			Number:      basicPR.Number,
  1507  			PullRequest: basicPR,
  1508  		}
  1509  		event.PullRequest.Merged = tc.merged
  1510  		if tc.mergeCommit != "" {
  1511  			event.PullRequest.MergeSHA = &tc.mergeCommit
  1512  		}
  1513  
  1514  		fgc := fakegithub.NewFakeClient()
  1515  		fgc.PullRequests = map[int]*github.PullRequest{
  1516  			basicPR.Number: &basicPR,
  1517  		}
  1518  		fgc.PullRequestChanges = map[int][]github.PullRequestChange{
  1519  			basicPR.Number: tc.changes,
  1520  		}
  1521  		fgc.IssueComments = map[int][]github.IssueComment{}
  1522  		fkc := fake.NewSimpleClientset(tc.existConfigMaps...)
  1523  
  1524  		m := tc.config
  1525  		if m == nil {
  1526  			m = &plugins.ConfigUpdater{
  1527  				Maps: map[string]plugins.ConfigMapSpec{
  1528  					"prow/config.yaml": {
  1529  						Name: "config",
  1530  					},
  1531  					"prow/plugins.yaml": {
  1532  						Name: "plugins",
  1533  						Key:  "test-key",
  1534  					},
  1535  					"boskos/resources.yaml": {
  1536  						Name:     "boskos-config",
  1537  						Clusters: map[string][]string{"default": {"boskos"}},
  1538  					},
  1539  					"config/foo.yaml": {
  1540  						Name: "multikey-config",
  1541  					},
  1542  					"config/bar.yaml": {
  1543  						Name: "multikey-config",
  1544  					},
  1545  					"dir/subdir/**/*.yaml": {
  1546  						Name: "glob-config",
  1547  					},
  1548  				},
  1549  			}
  1550  		}
  1551  		m.SetDefaults()
  1552  
  1553  		org := event.PullRequest.Base.Repo.Owner.Login
  1554  		repo := event.PullRequest.Base.Repo.Name
  1555  		c := setupLocalGitRepo(clients, t, org, repo)
  1556  
  1557  		if err := handle(fgc, c, fkc.CoreV1(), nil, defaultNamespace, log, event, *m, nil); err != nil {
  1558  			t.Errorf("%s: unexpected error handling: %s", tc.name, err)
  1559  			continue
  1560  		}
  1561  
  1562  		modifiedConfigMaps := sets.New[string]()
  1563  		for _, action := range fkc.Fake.Actions() {
  1564  			var obj runtime.Object
  1565  			switch action := action.(type) {
  1566  			case clienttesting.CreateActionImpl:
  1567  				obj = action.Object
  1568  			case clienttesting.UpdateActionImpl:
  1569  				obj = action.Object
  1570  			default:
  1571  				continue
  1572  			}
  1573  			objectMeta, err := meta.Accessor(obj)
  1574  			if err != nil {
  1575  				t.Fatalf("%s: client saw an action for something that wasn't an object: %v", tc.name, err)
  1576  			}
  1577  			modifiedConfigMaps.Insert(objectMeta.GetName())
  1578  		}
  1579  
  1580  		if tc.expectedConfigMaps != nil {
  1581  			if len(fgc.IssueComments[basicPR.Number]) != 1 {
  1582  				t.Errorf("%s: Expect 1 comment, actually got %d", tc.name, len(fgc.IssueComments[basicPR.Number]))
  1583  			} else {
  1584  				comment := fgc.IssueComments[basicPR.Number][0].Body
  1585  				if !strings.Contains(comment, "Updated the") {
  1586  					t.Errorf("%s: missing Updated the from %s", tc.name, comment)
  1587  				}
  1588  				for _, configMap := range tc.expectedConfigMaps {
  1589  					if modifiedConfigMaps.Has(configMap.Name) {
  1590  						if !strings.Contains(comment, configMap.Name) {
  1591  							t.Errorf("%s: missing %s from %s", tc.name, configMap.Name, comment)
  1592  						}
  1593  					} else if strings.Contains(comment, configMap.Name) {
  1594  						t.Errorf("%s: should not contain %s in %s", tc.name, configMap.Name, comment)
  1595  					}
  1596  				}
  1597  			}
  1598  		}
  1599  
  1600  		expectedConfigMaps := sets.New[string]()
  1601  		for _, configMap := range tc.expectedConfigMaps {
  1602  			expectedConfigMaps.Insert(configMap.Name)
  1603  		}
  1604  		if missing := expectedConfigMaps.Difference(modifiedConfigMaps); missing.Len() > 0 {
  1605  			t.Errorf("%s: did not update expected configmaps: %v", tc.name, sets.List(missing))
  1606  		}
  1607  		if extra := modifiedConfigMaps.Difference(expectedConfigMaps); extra.Len() > 0 {
  1608  			t.Errorf("%s: found unexpectedly updated configmaps: %v", tc.name, sets.List(extra))
  1609  		}
  1610  
  1611  		for _, expected := range tc.expectedConfigMaps {
  1612  			actual, err := fkc.CoreV1().ConfigMaps(expected.Namespace).Get(context.TODO(), expected.Name, metav1.GetOptions{})
  1613  			if err != nil && errors.IsNotFound(err) {
  1614  				t.Errorf("%s: Should have updated or created configmap for '%s'", tc.name, expected)
  1615  			} else if !equality.Semantic.DeepEqual(expected, actual) {
  1616  				t.Errorf("%s: incorrect ConfigMap state after update: %v", tc.name, diff.ObjectReflectDiff(expected, actual))
  1617  			}
  1618  		}
  1619  	}
  1620  }
  1621  
  1622  func TestHandleDefaultNamespace(t *testing.T) {
  1623  	testcases := []struct {
  1624  		name     string
  1625  		given    map[plugins.ConfigMapID][]ConfigMapUpdate
  1626  		expected map[plugins.ConfigMapID][]ConfigMapUpdate
  1627  	}{
  1628  		{
  1629  			name:     "nil map",
  1630  			given:    nil,
  1631  			expected: map[plugins.ConfigMapID][]ConfigMapUpdate{},
  1632  		},
  1633  		{
  1634  			name:     "empty map",
  1635  			given:    map[plugins.ConfigMapID][]ConfigMapUpdate{},
  1636  			expected: map[plugins.ConfigMapID][]ConfigMapUpdate{},
  1637  		},
  1638  		{
  1639  			name: "no empty string as namespace",
  1640  			given: map[plugins.ConfigMapID][]ConfigMapUpdate{
  1641  				{Name: "some-config", Namespace: "ns1", Cluster: "build01"}: {
  1642  					{Key: "foo.yaml", Filename: "config/foo.yaml"},
  1643  				},
  1644  				{Name: "other-config", Namespace: "default", Cluster: "default"}: {
  1645  					{Key: "foo.yaml", Filename: "config/foo.yaml"},
  1646  					{Key: "bar.yaml", Filename: "config/bar.yaml"},
  1647  				},
  1648  			},
  1649  			expected: map[plugins.ConfigMapID][]ConfigMapUpdate{
  1650  				{Name: "some-config", Namespace: "ns1", Cluster: "build01"}: {
  1651  					{Key: "foo.yaml", Filename: "config/foo.yaml"},
  1652  				},
  1653  				{Name: "other-config", Namespace: "default", Cluster: "default"}: {
  1654  					{Key: "foo.yaml", Filename: "config/foo.yaml"},
  1655  					{Key: "bar.yaml", Filename: "config/bar.yaml"},
  1656  				},
  1657  			},
  1658  		},
  1659  		{
  1660  			name: "some empty string as namespace",
  1661  			given: map[plugins.ConfigMapID][]ConfigMapUpdate{
  1662  				{Name: "some-config", Namespace: "ns1", Cluster: "build01"}: {
  1663  					{Key: "foo.yaml", Filename: "config/foo.yaml"},
  1664  				},
  1665  				{Name: "other-config", Cluster: "default"}: {
  1666  					{Key: "foo.yaml", Filename: "config/foo.yaml"},
  1667  					{Key: "bar.yaml", Filename: "config/bar.yaml"},
  1668  				},
  1669  			},
  1670  			expected: map[plugins.ConfigMapID][]ConfigMapUpdate{
  1671  				{Name: "some-config", Namespace: "ns1", Cluster: "build01"}: {
  1672  					{Key: "foo.yaml", Filename: "config/foo.yaml"},
  1673  				},
  1674  				{Name: "other-config", Namespace: "default", Cluster: "default"}: {
  1675  					{Key: "foo.yaml", Filename: "config/foo.yaml"},
  1676  					{Key: "bar.yaml", Filename: "config/bar.yaml"},
  1677  				},
  1678  			},
  1679  		},
  1680  		{
  1681  			name: "some empty string as namespace with potential conflicting id",
  1682  			given: map[plugins.ConfigMapID][]ConfigMapUpdate{
  1683  				{Name: "some-config", Namespace: "ns1", Cluster: "build01"}: {
  1684  					{Key: "foo.yaml", Filename: "config/foo.yaml"},
  1685  				},
  1686  				{Name: "multikey-config", Cluster: "default"}: {
  1687  					{Key: "foo.yaml", Filename: "config/foo.yaml"},
  1688  				},
  1689  				{Name: "multikey-config", Namespace: "default", Cluster: "default"}: {
  1690  					{Key: "bar.yaml", Filename: "config/bar.yaml"},
  1691  				},
  1692  			},
  1693  			expected: map[plugins.ConfigMapID][]ConfigMapUpdate{
  1694  				{Name: "some-config", Namespace: "ns1", Cluster: "build01"}: {
  1695  					{Key: "foo.yaml", Filename: "config/foo.yaml"},
  1696  				},
  1697  				{Name: "multikey-config", Namespace: "default", Cluster: "default"}: {
  1698  					{Key: "bar.yaml", Filename: "config/bar.yaml"},
  1699  					{Key: "foo.yaml", Filename: "config/foo.yaml"},
  1700  				},
  1701  			},
  1702  		},
  1703  	}
  1704  
  1705  	for _, tc := range testcases {
  1706  		actual := handleDefaultNamespace(tc.given, defaultNamespace)
  1707  		if !equality.Semantic.DeepEqual(tc.expected, actual) {
  1708  			t.Errorf("%s: incorrect changes: %v", tc.name, diff.ObjectReflectDiff(tc.expected, actual))
  1709  		}
  1710  	}
  1711  }
  1712  
  1713  func TestUpdateV2(t *testing.T) {
  1714  	testUpdate(localgit.NewV2, t)
  1715  }
  1716  
  1717  func testUpdate(clients localgit.Clients, t *testing.T) {
  1718  	testcases := []struct {
  1719  		name              string
  1720  		updates           []ConfigMapUpdate
  1721  		existConfigMap    runtime.Object
  1722  		expectedConfigMap *coreapi.ConfigMap
  1723  		config            *plugins.ConfigUpdater
  1724  		bootstrap         bool
  1725  	}{
  1726  		{
  1727  			name:      "stale key removed in bootstrap mode",
  1728  			bootstrap: true,
  1729  			updates: []ConfigMapUpdate{
  1730  				{
  1731  					Filename: "config/foo.yaml",
  1732  					Key:      "foo.yaml",
  1733  				},
  1734  			},
  1735  			existConfigMap: runtime.Object(
  1736  				&coreapi.ConfigMap{
  1737  					ObjectMeta: metav1.ObjectMeta{
  1738  						Name:      "multikey-config",
  1739  						Namespace: defaultNamespace,
  1740  						Labels: map[string]string{
  1741  							"app.kubernetes.io/name":      "prow",
  1742  							"app.kubernetes.io/component": "updateconfig-plugin",
  1743  						},
  1744  					},
  1745  					Data: map[string]string{
  1746  						"foo.yaml": "old-foo-config",
  1747  						"bar.yaml": "old-bar-config",
  1748  					},
  1749  				},
  1750  			),
  1751  			expectedConfigMap: &coreapi.ConfigMap{
  1752  				ObjectMeta: metav1.ObjectMeta{
  1753  					Name:      "multikey-config",
  1754  					Namespace: defaultNamespace,
  1755  					Labels: map[string]string{
  1756  						"app.kubernetes.io/name":      "prow",
  1757  						"app.kubernetes.io/component": "updateconfig-plugin",
  1758  					},
  1759  				},
  1760  				Data: map[string]string{
  1761  					"foo.yaml": "new-foo-config",
  1762  					"VERSION":  "12345",
  1763  				},
  1764  			},
  1765  		},
  1766  		{
  1767  			name:      "stale key kept when not in bootstrap mode",
  1768  			bootstrap: false,
  1769  			updates: []ConfigMapUpdate{
  1770  				{
  1771  					Filename: "config/foo.yaml",
  1772  					Key:      "foo.yaml",
  1773  				},
  1774  			},
  1775  			existConfigMap: runtime.Object(
  1776  				&coreapi.ConfigMap{
  1777  					ObjectMeta: metav1.ObjectMeta{
  1778  						Name:      "multikey-config",
  1779  						Namespace: defaultNamespace,
  1780  						Labels: map[string]string{
  1781  							"app.kubernetes.io/name":      "prow",
  1782  							"app.kubernetes.io/component": "updateconfig-plugin",
  1783  						},
  1784  					},
  1785  					Data: map[string]string{
  1786  						"foo.yaml": "old-foo-config",
  1787  						"bar.yaml": "old-bar-config",
  1788  					},
  1789  				},
  1790  			),
  1791  			expectedConfigMap: &coreapi.ConfigMap{
  1792  				ObjectMeta: metav1.ObjectMeta{
  1793  					Name:      "multikey-config",
  1794  					Namespace: defaultNamespace,
  1795  					Labels: map[string]string{
  1796  						"app.kubernetes.io/name":      "prow",
  1797  						"app.kubernetes.io/component": "updateconfig-plugin",
  1798  					},
  1799  				},
  1800  				Data: map[string]string{
  1801  					"VERSION":  "12345",
  1802  					"foo.yaml": "new-foo-config",
  1803  					"bar.yaml": "old-bar-config",
  1804  				},
  1805  			},
  1806  		},
  1807  	}
  1808  
  1809  	for _, tc := range testcases {
  1810  		log := logrus.WithField("plugin", pluginName)
  1811  		fkc := fake.NewSimpleClientset(tc.existConfigMap)
  1812  		configMapClient, err := GetConfigMapClient(fkc.CoreV1(), tc.expectedConfigMap.Namespace, nil, kube.DefaultClusterAlias)
  1813  		if err != nil {
  1814  			log.WithError(err).Errorf("Failed to find configMap client")
  1815  			continue
  1816  		}
  1817  
  1818  		m := tc.config
  1819  		if m == nil {
  1820  			m = &plugins.ConfigUpdater{
  1821  				Maps: map[string]plugins.ConfigMapSpec{
  1822  					"prow/config.yaml": {
  1823  						Name: "config",
  1824  					},
  1825  					"prow/plugins.yaml": {
  1826  						Name: "plugins",
  1827  						Key:  "test-key",
  1828  					},
  1829  					"boskos/resources.yaml": {
  1830  						Name:     "boskos-config",
  1831  						Clusters: map[string][]string{"default": {"boskos"}},
  1832  					},
  1833  					"config/foo.yaml": {
  1834  						Name: "multikey-config",
  1835  					},
  1836  					"config/bar.yaml": {
  1837  						Name: "multikey-config",
  1838  					},
  1839  					"dir/subdir/**/*.yaml": {
  1840  						Name: "glob-config",
  1841  					},
  1842  				},
  1843  			}
  1844  		}
  1845  		m.SetDefaults()
  1846  
  1847  		org := "org"
  1848  		repo := "repo"
  1849  		c := setupLocalGitRepo(clients, t, org, repo)
  1850  
  1851  		gitRepo, err := c.ClientFor(org, repo)
  1852  		if err != nil {
  1853  			t.Fatalf("Failed to clone: %v.", err)
  1854  		}
  1855  		defer func() {
  1856  			if err := c.Clean(); err != nil {
  1857  				t.Errorf("Could not clean up git client cache: %v.", err)
  1858  			}
  1859  		}()
  1860  		if err := gitRepo.Checkout("12345"); err != nil {
  1861  			t.Errorf("Failed to checkout 12345: %v.", err)
  1862  			continue
  1863  		}
  1864  		if err := Update(&OSFileGetter{Root: gitRepo.Directory()}, configMapClient, tc.expectedConfigMap.Name, tc.expectedConfigMap.Namespace, tc.updates, tc.bootstrap, nil, log, "12345"); err != nil {
  1865  			t.Errorf("%s: unexpected error updating: %s", tc.name, err)
  1866  			continue
  1867  		}
  1868  
  1869  		modifiedConfigMaps := sets.New[string]()
  1870  		for _, action := range fkc.Fake.Actions() {
  1871  			var obj runtime.Object
  1872  			switch action := action.(type) {
  1873  			case clienttesting.CreateActionImpl:
  1874  				obj = action.Object
  1875  			case clienttesting.UpdateActionImpl:
  1876  				obj = action.Object
  1877  			default:
  1878  				continue
  1879  			}
  1880  			objectMeta, err := meta.Accessor(obj)
  1881  			if err != nil {
  1882  				t.Fatalf("%s: client saw an action for something that wasn't an object: %v", tc.name, err)
  1883  			}
  1884  			modifiedConfigMaps.Insert(objectMeta.GetName())
  1885  		}
  1886  
  1887  		expected := tc.expectedConfigMap
  1888  		actual, err := fkc.CoreV1().ConfigMaps(expected.Namespace).Get(context.TODO(), expected.Name, metav1.GetOptions{})
  1889  		if err != nil && errors.IsNotFound(err) {
  1890  			t.Errorf("%s: Should have updated or created configmap for '%s'", tc.name, expected)
  1891  		} else if !equality.Semantic.DeepEqual(expected, actual) {
  1892  			t.Errorf("%s: incorrect ConfigMap state after update: %v", tc.name, diff.ObjectReflectDiff(expected, actual))
  1893  		}
  1894  	}
  1895  }
  1896  
  1897  func getFileMap(s string) map[string][]byte {
  1898  	result := map[string][]byte{}
  1899  	for file, v := range remoteFiles {
  1900  		for sha, content := range v {
  1901  			if sha == s {
  1902  				result[file] = []byte(content)
  1903  			}
  1904  		}
  1905  	}
  1906  	return result
  1907  }
  1908  
  1909  func boolPtr(b bool) *bool {
  1910  	return &b
  1911  }
  1912  
  1913  type MapFS fstest.MapFS
  1914  
  1915  func (m MapFS) GetFile(name string) ([]byte, error) {
  1916  	return fstest.MapFS(m).ReadFile(name)
  1917  }
  1918  
  1919  func TestUpdateSize(t *testing.T) {
  1920  	t.Parallel()
  1921  	ns, name, commit := "ns", "name", "da28634f10160f8c746c387cd33b488909036e1f"
  1922  	log := logrus.NewEntry(logrus.New())
  1923  	fs := MapFS{
  1924  		"s": {Data: []byte("string data"), Mode: 0777},
  1925  		"c": {
  1926  			// $ printf 'string data' | gzip | hexdump -ve '1/1 "0x%02x, "'
  1927  			Data: []byte{
  1928  				0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
  1929  				0x2b, 0x2e, 0x29, 0xca, 0xcc, 0x4b, 0x57, 0x48, 0x49, 0x2c,
  1930  				0x49, 0x04, 0x00, 0x1e, 0xfb, 0x1a, 0x61, 0x0b, 0x00, 0x00,
  1931  				0x00,
  1932  			},
  1933  			Mode: 0777,
  1934  		},
  1935  	}
  1936  	testCases := []struct {
  1937  		name     string
  1938  		updates  []ConfigMapUpdate
  1939  		expected float64
  1940  	}{
  1941  		{
  1942  			name:     "empty",
  1943  			expected: 40,
  1944  		},
  1945  		{
  1946  			name: "string data",
  1947  			updates: []ConfigMapUpdate{
  1948  				{Key: "k0", Filename: "s"},
  1949  				{Key: "k1", Filename: "s"},
  1950  				{Key: "k2", Filename: "s"},
  1951  			},
  1952  			expected: 73,
  1953  		},
  1954  		{
  1955  			name: "compressed data",
  1956  			updates: []ConfigMapUpdate{
  1957  				{Key: "k0", Filename: "c"},
  1958  				{Key: "k1", Filename: "c"},
  1959  				{Key: "k2", Filename: "c"},
  1960  			},
  1961  			expected: 133,
  1962  		},
  1963  		{
  1964  			name: "combined data",
  1965  			updates: []ConfigMapUpdate{
  1966  				{Key: "k0", Filename: "s"},
  1967  				{Key: "k1", Filename: "s"},
  1968  				{Key: "k2", Filename: "s"},
  1969  				{Key: "k3", Filename: "c"},
  1970  				{Key: "k4", Filename: "c"},
  1971  				{Key: "k5", Filename: "c"},
  1972  			},
  1973  			expected: 166,
  1974  		},
  1975  	}
  1976  	for i := range testCases {
  1977  		tc := testCases[i]
  1978  		t.Run(tc.name, func(t *testing.T) {
  1979  			t.Parallel()
  1980  			client, err := GetConfigMapClient(fake.NewSimpleClientset().CoreV1(), ns, nil, kube.DefaultClusterAlias)
  1981  			if err != nil {
  1982  				t.Fatalf("failed to create fake client: %v", err)
  1983  			}
  1984  			metrics := prometheus.NewGaugeVec(prometheus.GaugeOpts{}, []string{name, ns})
  1985  			if err := Update(fs, client, name, ns, tc.updates, true, metrics, log, commit); err != nil {
  1986  				t.Fatalf("unexpected error updating: %v", err)
  1987  			}
  1988  			var metric prometheus_model.Metric
  1989  			metrics.WithLabelValues(name, ns).Write(&metric)
  1990  			if n := *metric.Gauge.Value; n != tc.expected {
  1991  				t.Fatalf("unexpected total, want %v, got %v", tc.expected, n)
  1992  			}
  1993  		})
  1994  	}
  1995  }
  1996  
  1997  func TestMarkStaleKeysForDeletion(t *testing.T) {
  1998  	t.Parallel()
  1999  	testCases := []struct {
  2000  		name      string
  2001  		configMap *coreapi.ConfigMap
  2002  		updates   []ConfigMapUpdate
  2003  		expected  []ConfigMapUpdate
  2004  	}{
  2005  		{
  2006  			name: "empty",
  2007  			configMap: &coreapi.ConfigMap{
  2008  				ObjectMeta: metav1.ObjectMeta{
  2009  					Name: "config",
  2010  				},
  2011  			},
  2012  			updates: []ConfigMapUpdate{
  2013  				{Key: "foo.yaml", Filename: "config/foo.yaml"},
  2014  			},
  2015  			expected: []ConfigMapUpdate{}, // nothing to delete
  2016  		},
  2017  		{
  2018  			name: "delete one key",
  2019  			configMap: &coreapi.ConfigMap{
  2020  				ObjectMeta: metav1.ObjectMeta{
  2021  					Name: "config",
  2022  				},
  2023  				Data: map[string]string{
  2024  					"foo.yaml": "old-foo-config",
  2025  					"bar.yaml": "old-bar-config",
  2026  				},
  2027  			},
  2028  			updates: []ConfigMapUpdate{
  2029  				{Key: "foo.yaml", Filename: "config/foo.yaml"},
  2030  			},
  2031  			expected: []ConfigMapUpdate{
  2032  				{Key: "bar.yaml"}, // delete this one
  2033  			},
  2034  		},
  2035  		{
  2036  			name: "delete 3 keys",
  2037  			configMap: &coreapi.ConfigMap{
  2038  				ObjectMeta: metav1.ObjectMeta{
  2039  					Name: "config",
  2040  				},
  2041  				Data: map[string]string{
  2042  					"foo.yaml": "old-foo-config",
  2043  					"bar.yaml": "old-bar-config",
  2044  					"baz.yaml": "old-baz-config",
  2045  					"qux.yaml": "old-qux-config",
  2046  				},
  2047  			},
  2048  			updates: []ConfigMapUpdate{
  2049  				{Key: "foo.yaml", Filename: "config/foo.yaml"},
  2050  			},
  2051  			expected: []ConfigMapUpdate{
  2052  				{Key: "bar.yaml"}, // delete this one
  2053  				{Key: "baz.yaml"}, // delete this one
  2054  				{Key: "qux.yaml"}, // delete this one
  2055  			},
  2056  		},
  2057  		{
  2058  			// Potential callers of MarkStaleKeysForDeletion() may avoid calling
  2059  			// us if there are no updates for safety, but we can't rely on
  2060  			// callers being safe all the time. So make sure that we do a NOP if
  2061  			// there are no updates (don't try to do a mass deletion if an empty
  2062  			// slice is passed in somehow).
  2063  			name: "for safety, delete nothing if there are no updates",
  2064  			configMap: &coreapi.ConfigMap{
  2065  				ObjectMeta: metav1.ObjectMeta{
  2066  					Name: "config",
  2067  				},
  2068  				Data: map[string]string{
  2069  					"foo.yaml": "old-foo-config",
  2070  					"bar.yaml": "old-bar-config",
  2071  					"baz.yaml": "old-baz-config",
  2072  					"qux.yaml": "old-qux-config",
  2073  				},
  2074  			},
  2075  			updates:  []ConfigMapUpdate{},
  2076  			expected: nil,
  2077  		},
  2078  	}
  2079  	for i := range testCases {
  2080  		tc := testCases[i]
  2081  		t.Run(tc.name, func(t *testing.T) {
  2082  			t.Parallel()
  2083  			actual := MarkStaleKeysForDeletion(tc.configMap, tc.updates)
  2084  			if diff := cmp.Diff(tc.expected, actual, cmpopts.SortSlices(func(a, b ConfigMapUpdate) bool {
  2085  				return a.Key < b.Key
  2086  			})); diff != "" {
  2087  				t.Fatalf("ConfigMapUpdate slice mismatch. want(-), got(+):\n%s", diff)
  2088  			}
  2089  		})
  2090  	}
  2091  }