github.com/zppinho/prow@v0.0.0-20240510014325-1738badeb017/cmd/config-bootstrapper/main_test.go (about)

     1  /*
     2  Copyright 2019 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 main
    18  
    19  import (
    20  	"context"
    21  	"path/filepath"
    22  	"testing"
    23  
    24  	"github.com/google/go-cmp/cmp"
    25  
    26  	coreapi "k8s.io/api/core/v1"
    27  	"k8s.io/apimachinery/pkg/api/equality"
    28  	"k8s.io/apimachinery/pkg/api/errors"
    29  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    30  	"k8s.io/apimachinery/pkg/runtime"
    31  	"k8s.io/client-go/kubernetes/fake"
    32  
    33  	"sigs.k8s.io/prow/pkg/git/localgit"
    34  	"sigs.k8s.io/prow/pkg/plugins"
    35  )
    36  
    37  var (
    38  	defaultNamespace = "default"
    39  	defaultBranch    = localgit.DefaultBranch("")
    40  )
    41  
    42  func TestRunV2(t *testing.T) {
    43  	testRun(localgit.NewV2, t)
    44  }
    45  
    46  func testRun(clients localgit.Clients, t *testing.T) {
    47  	lg, c, err := clients()
    48  	if err != nil {
    49  		t.Fatalf("Making local git repo: %v", err)
    50  	}
    51  
    52  	defer func() {
    53  		if err := c.Clean(); err != nil {
    54  			t.Errorf("Could not clean up git client cache: %v.", err)
    55  		}
    56  	}()
    57  
    58  	if err := lg.MakeFakeRepo("openshift", "release"); err != nil {
    59  		t.Fatalf("Making fake repo: %v", err)
    60  	}
    61  	if err := lg.Checkout("openshift", "release", defaultBranch); err != nil {
    62  		t.Fatalf("Checkout new branch: %v", err)
    63  	}
    64  
    65  	if err := lg.AddCommit("openshift", "release", map[string][]byte{
    66  		"config/foo.yaml": []byte(`#foo.yaml`),
    67  		"config/bar.yaml": []byte(`#bar.yaml`),
    68  		"VERSION":         []byte("some-git-sha"),
    69  	}); err != nil {
    70  		t.Fatalf("Add commit: %v", err)
    71  	}
    72  
    73  	if err := lg.MakeFakeRepo("openshift", "other"); err != nil {
    74  		t.Fatalf("Making fake repo: %v", err)
    75  	}
    76  	if err := lg.Checkout("openshift", "other", defaultBranch); err != nil {
    77  		t.Fatalf("Checkout new branch: %v", err)
    78  	}
    79  
    80  	if err := lg.AddCommit("openshift", "other", map[string][]byte{
    81  		"config/other-foo.yaml": []byte(`#other-foo.yaml`),
    82  		"config/other-bar.yaml": []byte(`#other-bar.yaml`),
    83  	}); err != nil {
    84  		t.Fatalf("Add commit: %v", err)
    85  	}
    86  
    87  	if err := lg.MakeFakeRepo("org", "partition-test"); err != nil {
    88  		t.Fatalf("Making fake repo: %v", err)
    89  	}
    90  	if err := lg.Checkout("org", "partition-test", defaultBranch); err != nil {
    91  		t.Fatalf("Checkout new branch: %v", err)
    92  	}
    93  
    94  	if err := lg.AddCommit("org", "partition-test", map[string][]byte{
    95  		"config/foo.yaml": []byte(`#foo.yaml`),
    96  		"config/bar.yaml": []byte(`#bar.yaml`),
    97  		"config/baz.yaml": []byte(`#baz.yaml`),
    98  	}); err != nil {
    99  		t.Fatalf("Add commit: %v", err)
   100  	}
   101  
   102  	if err := lg.MakeFakeRepo("org", "partition-test2"); err != nil {
   103  		t.Fatalf("Making fake repo: %v", err)
   104  	}
   105  	if err := lg.Checkout("org", "partition-test2", defaultBranch); err != nil {
   106  		t.Fatalf("Checkout new branch: %v", err)
   107  	}
   108  
   109  	if err := lg.AddCommit("org", "partition-test2", map[string][]byte{
   110  		"config/foo.yaml": []byte(`#foo.yaml`),
   111  		"config/bar.yaml": []byte(`#bar.yaml`),
   112  	}); err != nil {
   113  		t.Fatalf("Add commit: %v", err)
   114  	}
   115  
   116  	testcases := []struct {
   117  		name             string
   118  		sourcePaths      []string
   119  		defaultNamespace string
   120  		configUpdater    plugins.ConfigUpdater
   121  		expected         int
   122  
   123  		existConfigMaps    []runtime.Object
   124  		expectedConfigMaps []*coreapi.ConfigMap
   125  	}{
   126  		{
   127  			name:             "issues/15570 is covered",
   128  			sourcePaths:      []string{filepath.Join(lg.Dir, "openshift/release")},
   129  			defaultNamespace: defaultNamespace,
   130  			configUpdater: plugins.ConfigUpdater{
   131  				Maps: map[string]plugins.ConfigMapSpec{
   132  					"config/foo.yaml": {
   133  						Name: "multikey-config",
   134  						Clusters: map[string][]string{
   135  							"default": {defaultNamespace},
   136  						},
   137  					},
   138  					"config/bar.yaml": {
   139  						Name: "multikey-config",
   140  					},
   141  				},
   142  			},
   143  			existConfigMaps: []runtime.Object{
   144  				&coreapi.ConfigMap{
   145  					ObjectMeta: metav1.ObjectMeta{
   146  						Name:      "multikey-config",
   147  						Namespace: defaultNamespace,
   148  						Labels: map[string]string{
   149  							"app.kubernetes.io/name":      "prow",
   150  							"app.kubernetes.io/component": "updateconfig-plugin",
   151  						},
   152  					},
   153  					Data: map[string]string{},
   154  				},
   155  			},
   156  			expectedConfigMaps: []*coreapi.ConfigMap{
   157  				{
   158  					ObjectMeta: metav1.ObjectMeta{
   159  						Name:      "multikey-config",
   160  						Namespace: defaultNamespace,
   161  						Labels: map[string]string{
   162  							"app.kubernetes.io/name":      "prow",
   163  							"app.kubernetes.io/component": "updateconfig-plugin",
   164  						},
   165  					},
   166  					Data: map[string]string{
   167  						"VERSION":  "some-git-sha",
   168  						"foo.yaml": "#foo.yaml",
   169  						"bar.yaml": "#bar.yaml",
   170  					},
   171  				},
   172  			},
   173  		},
   174  		{
   175  			name:             "multiple sources",
   176  			sourcePaths:      []string{filepath.Join(lg.Dir, "openshift/release"), filepath.Join(lg.Dir, "openshift/other")},
   177  			defaultNamespace: defaultNamespace,
   178  			configUpdater: plugins.ConfigUpdater{
   179  				Maps: map[string]plugins.ConfigMapSpec{
   180  					"config/foo.yaml": {
   181  						Name: "multikey-config",
   182  						Clusters: map[string][]string{
   183  							"default": {defaultNamespace},
   184  						},
   185  					},
   186  					"config/bar.yaml": {
   187  						Name: "multikey-config",
   188  					},
   189  					"config/other-foo.yaml": {
   190  						Name: "other",
   191  						Clusters: map[string][]string{
   192  							"default": {defaultNamespace},
   193  						},
   194  					},
   195  					"config/other-bar.yaml": {
   196  						Name: "bar",
   197  					},
   198  				},
   199  			},
   200  			existConfigMaps: []runtime.Object{
   201  				&coreapi.ConfigMap{
   202  					ObjectMeta: metav1.ObjectMeta{
   203  						Name:      "multikey-config",
   204  						Namespace: defaultNamespace,
   205  						Labels: map[string]string{
   206  							"app.kubernetes.io/name":      "prow",
   207  							"app.kubernetes.io/component": "updateconfig-plugin",
   208  						},
   209  					},
   210  					Data: map[string]string{},
   211  				},
   212  			},
   213  			expectedConfigMaps: []*coreapi.ConfigMap{
   214  				{
   215  					ObjectMeta: metav1.ObjectMeta{
   216  						Name:      "multikey-config",
   217  						Namespace: defaultNamespace,
   218  						Labels: map[string]string{
   219  							"app.kubernetes.io/name":      "prow",
   220  							"app.kubernetes.io/component": "updateconfig-plugin",
   221  						},
   222  					},
   223  					Data: map[string]string{
   224  						"VERSION":  "some-git-sha",
   225  						"foo.yaml": "#foo.yaml",
   226  						"bar.yaml": "#bar.yaml",
   227  					},
   228  				},
   229  				{
   230  					ObjectMeta: metav1.ObjectMeta{
   231  						Name:      "other",
   232  						Namespace: defaultNamespace,
   233  						Labels: map[string]string{
   234  							"app.kubernetes.io/name":      "prow",
   235  							"app.kubernetes.io/component": "updateconfig-plugin",
   236  						},
   237  					},
   238  					Data: map[string]string{
   239  						"VERSION":        "some-git-sha",
   240  						"other-foo.yaml": "#other-foo.yaml",
   241  					},
   242  				},
   243  				{
   244  					ObjectMeta: metav1.ObjectMeta{
   245  						Name:      "bar",
   246  						Namespace: defaultNamespace,
   247  						Labels: map[string]string{
   248  							"app.kubernetes.io/name":      "prow",
   249  							"app.kubernetes.io/component": "updateconfig-plugin",
   250  						},
   251  					},
   252  					Data: map[string]string{
   253  						"VERSION":        "some-git-sha",
   254  						"other-bar.yaml": "#other-bar.yaml",
   255  					},
   256  				},
   257  			},
   258  		},
   259  		{
   260  			name:             "undefined cluster errors",
   261  			sourcePaths:      []string{filepath.Join(lg.Dir, "openshift/release")},
   262  			defaultNamespace: defaultNamespace,
   263  			configUpdater: plugins.ConfigUpdater{
   264  				Maps: map[string]plugins.ConfigMapSpec{
   265  					"config/foo.yaml": {
   266  						Name: "multikey-config",
   267  						Clusters: map[string][]string{
   268  							"undef": {defaultNamespace},
   269  						},
   270  					},
   271  				},
   272  			},
   273  			expected: 1,
   274  		},
   275  		{
   276  			name:             "PartitionedNames properly partitions",
   277  			sourcePaths:      []string{filepath.Join(lg.Dir, "org/partition-test")},
   278  			defaultNamespace: defaultNamespace,
   279  			configUpdater: plugins.ConfigUpdater{
   280  				Maps: map[string]plugins.ConfigMapSpec{
   281  					"config/**/*.yaml": {
   282  						PartitionedNames: []string{"job-config-part-1", "job-config-part-2"},
   283  					},
   284  				},
   285  			},
   286  			expectedConfigMaps: []*coreapi.ConfigMap{
   287  				{
   288  					ObjectMeta: metav1.ObjectMeta{
   289  						Name:      "job-config-part-1",
   290  						Namespace: defaultNamespace,
   291  						Labels: map[string]string{
   292  							"app.kubernetes.io/name":      "prow",
   293  							"app.kubernetes.io/component": "updateconfig-plugin",
   294  						},
   295  					},
   296  					Data: map[string]string{
   297  						"foo.yaml": "#foo.yaml",
   298  						"bar.yaml": "#bar.yaml",
   299  					},
   300  				},
   301  				{
   302  					ObjectMeta: metav1.ObjectMeta{
   303  						Name:      "job-config-part-2",
   304  						Namespace: defaultNamespace,
   305  						Labels: map[string]string{
   306  							"app.kubernetes.io/name":      "prow",
   307  							"app.kubernetes.io/component": "updateconfig-plugin",
   308  						},
   309  					},
   310  					Data: map[string]string{
   311  						"baz.yaml": "#baz.yaml",
   312  					},
   313  				},
   314  			},
   315  		},
   316  		{
   317  			name:             "PartitionedNames file moves between partitions properly",
   318  			sourcePaths:      []string{filepath.Join(lg.Dir, "org/partition-test")},
   319  			defaultNamespace: defaultNamespace,
   320  			configUpdater: plugins.ConfigUpdater{
   321  				Maps: map[string]plugins.ConfigMapSpec{
   322  					"config/**/*.yaml": {
   323  						PartitionedNames: []string{"job-config-part-1", "job-config-part-2"},
   324  					},
   325  				},
   326  			},
   327  			existConfigMaps: []runtime.Object{
   328  				&coreapi.ConfigMap{
   329  					ObjectMeta: metav1.ObjectMeta{
   330  						Name:      "job-config-part-1",
   331  						Namespace: defaultNamespace,
   332  						Labels: map[string]string{
   333  							"app.kubernetes.io/name":      "prow",
   334  							"app.kubernetes.io/component": "updateconfig-plugin",
   335  						},
   336  					},
   337  					Data: map[string]string{
   338  						"foo.yaml": "#foo.yaml",
   339  					},
   340  				},
   341  				&coreapi.ConfigMap{
   342  					ObjectMeta: metav1.ObjectMeta{
   343  						Name:      "job-config-part-2",
   344  						Namespace: defaultNamespace,
   345  						Labels: map[string]string{
   346  							"app.kubernetes.io/name":      "prow",
   347  							"app.kubernetes.io/component": "updateconfig-plugin",
   348  						},
   349  					},
   350  					Data: map[string]string{
   351  						"baz.yaml":       "#baz.yaml",
   352  						"barbarbar.yaml": "#bar.yaml",
   353  					},
   354  				},
   355  			},
   356  			expectedConfigMaps: []*coreapi.ConfigMap{
   357  				{
   358  					ObjectMeta: metav1.ObjectMeta{
   359  						Name:      "job-config-part-1",
   360  						Namespace: defaultNamespace,
   361  						Labels: map[string]string{
   362  							"app.kubernetes.io/name":      "prow",
   363  							"app.kubernetes.io/component": "updateconfig-plugin",
   364  						},
   365  					},
   366  					Data: map[string]string{
   367  						"foo.yaml": "#foo.yaml",
   368  						"bar.yaml": "#bar.yaml",
   369  					},
   370  				},
   371  				{
   372  					ObjectMeta: metav1.ObjectMeta{
   373  						Name:      "job-config-part-2",
   374  						Namespace: defaultNamespace,
   375  						Labels: map[string]string{
   376  							"app.kubernetes.io/name":      "prow",
   377  							"app.kubernetes.io/component": "updateconfig-plugin",
   378  						},
   379  					},
   380  					Data: map[string]string{
   381  						"baz.yaml": "#baz.yaml",
   382  					},
   383  				},
   384  			},
   385  		},
   386  		{
   387  			name:             "PartitionedNames: emptied partition is properly wiped",
   388  			sourcePaths:      []string{filepath.Join(lg.Dir, "org/partition-test2")},
   389  			defaultNamespace: defaultNamespace,
   390  			configUpdater: plugins.ConfigUpdater{
   391  				Maps: map[string]plugins.ConfigMapSpec{
   392  					"config/**/*.yaml": {
   393  						PartitionedNames: []string{"job-config-part-1", "job-config-part-2"},
   394  					},
   395  				},
   396  			},
   397  			existConfigMaps: []runtime.Object{
   398  				&coreapi.ConfigMap{
   399  					ObjectMeta: metav1.ObjectMeta{
   400  						Name:      "job-config-part-1",
   401  						Namespace: defaultNamespace,
   402  						Labels: map[string]string{
   403  							"app.kubernetes.io/name":      "prow",
   404  							"app.kubernetes.io/component": "updateconfig-plugin",
   405  						},
   406  					},
   407  					Data: map[string]string{
   408  						"foo.yaml": "#foo.yaml",
   409  					},
   410  				},
   411  				&coreapi.ConfigMap{
   412  					ObjectMeta: metav1.ObjectMeta{
   413  						Name:      "job-config-part-2",
   414  						Namespace: defaultNamespace,
   415  						Labels: map[string]string{
   416  							"app.kubernetes.io/name":      "prow",
   417  							"app.kubernetes.io/component": "updateconfig-plugin",
   418  						},
   419  					},
   420  					Data: map[string]string{
   421  						"barbarbar.yaml": "#bar.yaml",
   422  					},
   423  				},
   424  			},
   425  			expectedConfigMaps: []*coreapi.ConfigMap{
   426  				{
   427  					ObjectMeta: metav1.ObjectMeta{
   428  						Name:      "job-config-part-1",
   429  						Namespace: defaultNamespace,
   430  						Labels: map[string]string{
   431  							"app.kubernetes.io/name":      "prow",
   432  							"app.kubernetes.io/component": "updateconfig-plugin",
   433  						},
   434  					},
   435  					Data: map[string]string{
   436  						"foo.yaml": "#foo.yaml",
   437  						"bar.yaml": "#bar.yaml", // renamed from barbarbar.yaml
   438  					},
   439  				},
   440  				{
   441  					ObjectMeta: metav1.ObjectMeta{
   442  						Name:      "job-config-part-2",
   443  						Namespace: defaultNamespace,
   444  						Labels: map[string]string{
   445  							"app.kubernetes.io/name":      "prow",
   446  							"app.kubernetes.io/component": "updateconfig-plugin",
   447  						},
   448  					},
   449  					Data: map[string]string{},
   450  				},
   451  			},
   452  		},
   453  		{
   454  			// The keys for files a, b, and c are unaccounted for (they don't
   455  			// exist in the repo), so they should be deleted.
   456  			name:             "untouched keys are deleted",
   457  			sourcePaths:      []string{filepath.Join(lg.Dir, "openshift/other")},
   458  			defaultNamespace: defaultNamespace,
   459  			configUpdater: plugins.ConfigUpdater{
   460  				Maps: map[string]plugins.ConfigMapSpec{
   461  					"config/other-foo.yaml": {
   462  						Name: "job-config",
   463  					},
   464  					"config/other-bar.yaml": {
   465  						Name: "job-config",
   466  					},
   467  				},
   468  			},
   469  			existConfigMaps: []runtime.Object{
   470  				&coreapi.ConfigMap{
   471  					ObjectMeta: metav1.ObjectMeta{
   472  						Name:      "job-config",
   473  						Namespace: defaultNamespace,
   474  						Labels: map[string]string{
   475  							"app.kubernetes.io/name":      "prow",
   476  							"app.kubernetes.io/component": "updateconfig-plugin",
   477  						},
   478  					},
   479  					Data: map[string]string{
   480  						"other-foo.yaml": "#other-foo.yaml",
   481  						"other-bar.yaml": "#other-bar.yaml",
   482  
   483  						// The ones below should be deleted.
   484  						"a": "xxx",
   485  						"b": "xxx",
   486  						"c": "xxx",
   487  					},
   488  				},
   489  			},
   490  			expectedConfigMaps: []*coreapi.ConfigMap{
   491  				{
   492  					ObjectMeta: metav1.ObjectMeta{
   493  						Name:      "job-config",
   494  						Namespace: defaultNamespace,
   495  						Labels: map[string]string{
   496  							"app.kubernetes.io/name":      "prow",
   497  							"app.kubernetes.io/component": "updateconfig-plugin",
   498  						},
   499  					},
   500  					Data: map[string]string{
   501  						"other-foo.yaml": "#other-foo.yaml",
   502  						"other-bar.yaml": "#other-bar.yaml",
   503  					},
   504  				},
   505  			},
   506  		},
   507  	}
   508  
   509  	for _, tc := range testcases {
   510  		t.Run(tc.name, func(t *testing.T) {
   511  			fkc := fake.NewSimpleClientset(tc.existConfigMaps...)
   512  			tc.configUpdater.SetDefaults()
   513  			actual := run(tc.sourcePaths, tc.defaultNamespace, tc.configUpdater, fkc, nil)
   514  			if tc.expected != actual {
   515  				t.Errorf("%s: incorrect errors '%d': expecting '%d'", tc.name, actual, tc.expected)
   516  			}
   517  
   518  			for _, expected := range tc.expectedConfigMaps {
   519  				actual, err := fkc.CoreV1().ConfigMaps(expected.Namespace).Get(context.TODO(), expected.Name, metav1.GetOptions{})
   520  				if err != nil && errors.IsNotFound(err) {
   521  					t.Errorf("%s: Should have updated or created configmap for '%s'", tc.name, expected)
   522  				} else if !equality.Semantic.DeepEqual(expected, actual) {
   523  					t.Errorf("%s: incorrect ConfigMap state after update: %v", tc.name, cmp.Diff(expected, actual))
   524  				}
   525  			}
   526  		})
   527  
   528  	}
   529  }