sigs.k8s.io/prow@v0.0.0-20240503223140-c5e374dc7eb1/hack/prowimagebuilder/main_test.go (about)

     1  /*
     2  Copyright 2022 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package main
    18  
    19  import (
    20  	"errors"
    21  	"fmt"
    22  	"os"
    23  	"path"
    24  	"strings"
    25  	"testing"
    26  
    27  	"github.com/google/go-cmp/cmp"
    28  	"github.com/google/go-cmp/cmp/cmpopts"
    29  	"sigs.k8s.io/prow/pkg/flagutil"
    30  )
    31  
    32  func TestImageAllowed(t *testing.T) {
    33  	tests := []struct {
    34  		name   string
    35  		images flagutil.Strings
    36  		image  string
    37  		want   bool
    38  	}{
    39  		{
    40  			name:   "not-specified",
    41  			images: flagutil.Strings{},
    42  			image:  "whatever",
    43  			want:   true,
    44  		},
    45  		{
    46  			name:   "included",
    47  			images: flagutil.NewStringsBeenSet("cmd/awesome"),
    48  			image:  "cmd/awesome",
    49  			want:   true,
    50  		},
    51  		{
    52  			name:   "not-included",
    53  			images: flagutil.NewStringsBeenSet("cmd/awesome"),
    54  			image:  "cmd/otherawesome",
    55  			want:   false,
    56  		},
    57  	}
    58  
    59  	for _, tc := range tests {
    60  		tc := tc
    61  		t.Run(tc.name, func(t *testing.T) {
    62  			o := options{
    63  				images: tc.images,
    64  			}
    65  			got := o.imageAllowed(tc.image)
    66  			if got != tc.want {
    67  				t.Errorf("Unexpected. Want: %v, got: %v", tc.want, got)
    68  			}
    69  		})
    70  	}
    71  }
    72  
    73  func TestRunCmdInDir(t *testing.T) {
    74  	dir := t.TempDir()
    75  	tests := []struct {
    76  		name    string
    77  		dir     string
    78  		cmd     string
    79  		args    []string
    80  		wantOut string
    81  		wantErr bool
    82  	}{
    83  		{
    84  			name:    "echo",
    85  			cmd:     "echo",
    86  			args:    []string{"abc"},
    87  			wantOut: "abc",
    88  			wantErr: false,
    89  		},
    90  		{
    91  			name:    "dir-not-exist",
    92  			dir:     "dir-not-exist",
    93  			cmd:     "echo",
    94  			args:    []string{"abc"},
    95  			wantOut: "",
    96  			wantErr: true,
    97  		},
    98  		{
    99  			name:    "dir-exist",
   100  			dir:     dir,
   101  			cmd:     "echo",
   102  			args:    []string{"abc"},
   103  			wantOut: "abc",
   104  			wantErr: false,
   105  		},
   106  		{
   107  			name:    "failed",
   108  			cmd:     "echo-abc",
   109  			args:    []string{"abc"},
   110  			wantOut: "",
   111  			wantErr: true,
   112  		},
   113  	}
   114  
   115  	for _, tc := range tests {
   116  		tc := tc
   117  		t.Run(tc.name, func(t *testing.T) {
   118  			got, gotErr := runCmdInDir(tc.dir, nil, tc.cmd, tc.args...)
   119  			if (gotErr != nil && !tc.wantErr) || (gotErr == nil && tc.wantErr) {
   120  				t.Fatalf("Error mismatch. Want: %v, got: %v", tc.wantErr, gotErr)
   121  			}
   122  			if want, got := strings.TrimSpace(tc.wantOut), strings.TrimSpace(got); want != got {
   123  				t.Fatalf("Output mismatch. Want: %q, got: %q", want, got)
   124  			}
   125  		})
   126  	}
   127  }
   128  
   129  func TestRunCmd(t *testing.T) {
   130  	gotOut, gotErr := runCmd(nil, "echo", "abc")
   131  	if gotErr != nil {
   132  		t.Fatalf("Should not error, got: %v", gotErr)
   133  	}
   134  	if want, got := "abc", strings.TrimSpace(gotOut); want != got {
   135  		t.Fatalf("Output mismatch. Want: %q, got: %q", want, got)
   136  	}
   137  }
   138  
   139  func TestLoadImageDefs(t *testing.T) {
   140  	dir := t.TempDir()
   141  	file := path.Join(dir, "temp.yaml")
   142  	body := `images:
   143  - dir: cmd/admission
   144  - dir: cmd/clonerefs
   145    arch: all`
   146  
   147  	wantDefs := []imageDef{
   148  		{Dir: "cmd/admission"},
   149  		{Dir: "cmd/clonerefs", Arch: "all"},
   150  	}
   151  
   152  	if err := os.WriteFile(file, []byte(body), 0644); err != nil {
   153  		t.Fatalf("Failed write file: %v", err)
   154  	}
   155  	defs, err := loadImageDefs(file)
   156  	if err != nil {
   157  		t.Fatalf("Failed loading image defs: %v", err)
   158  	}
   159  	if diff := cmp.Diff(defs, wantDefs, cmpopts.IgnoreUnexported(imageDef{})); diff != "" {
   160  		t.Fatalf("Output mismatch. Want(-), got(+):\n%s", diff)
   161  	}
   162  }
   163  
   164  func TestAllTags(t *testing.T) {
   165  	date, gitHash := "20220222", "a1b2c3d4"
   166  	oldRunCmdInDirFunc := runCmdInDirFunc
   167  	runCmdInDirFunc = func(dir string, additionalEnv []string, cmd string, args ...string) (string, error) {
   168  		switch cmd {
   169  		case "date":
   170  			return date, nil
   171  		case "git":
   172  			return gitHash, nil
   173  		default:
   174  			return "", errors.New("not supported command")
   175  		}
   176  	}
   177  	defer func() {
   178  		runCmdInDirFunc = oldRunCmdInDirFunc
   179  	}()
   180  
   181  	tests := []struct {
   182  		name string
   183  		arch string
   184  		want []string
   185  	}{
   186  		{
   187  			name: "base",
   188  			arch: "linux/amd64",
   189  			want: []string{
   190  				"latest",
   191  				"latest-root",
   192  				"20220222-a1b2c3d4",
   193  				"ko-20220222-a1b2c3d4",
   194  			},
   195  		},
   196  		{
   197  			name: "other",
   198  			arch: "linux/s390x",
   199  			want: []string{
   200  				"latest",
   201  				"latest-root",
   202  				"20220222-a1b2c3d4",
   203  				"ko-20220222-a1b2c3d4",
   204  				"latest-s390x",
   205  				"latest-root-s390x",
   206  				"20220222-a1b2c3d4-s390x",
   207  				"ko-20220222-a1b2c3d4-s390x",
   208  			},
   209  		},
   210  		{
   211  			name: "all",
   212  			arch: "all",
   213  			want: []string{
   214  				"latest",
   215  				"latest-root",
   216  				"20220222-a1b2c3d4",
   217  				"ko-20220222-a1b2c3d4",
   218  				"latest-arm64",
   219  				"latest-root-arm64",
   220  				"20220222-a1b2c3d4-arm64",
   221  				"ko-20220222-a1b2c3d4-arm64",
   222  				"latest-s390x",
   223  				"latest-root-s390x",
   224  				"20220222-a1b2c3d4-s390x",
   225  				"ko-20220222-a1b2c3d4-s390x",
   226  				"latest-ppc64le",
   227  				"latest-root-ppc64le",
   228  				"20220222-a1b2c3d4-ppc64le",
   229  				"ko-20220222-a1b2c3d4-ppc64le",
   230  			},
   231  		},
   232  		{
   233  			// Not supported arches are caught in the invoker of this function,
   234  			// not here.
   235  			name: "not-supported",
   236  			arch: "not/supported",
   237  			want: []string{
   238  				"latest",
   239  				"latest-root",
   240  				"20220222-a1b2c3d4",
   241  				"ko-20220222-a1b2c3d4",
   242  			},
   243  		},
   244  	}
   245  
   246  	for _, tc := range tests {
   247  		tc := tc
   248  		t.Run(tc.name, func(t *testing.T) {
   249  			got, _ := allTags(tc.arch)
   250  			if diff := cmp.Diff(tc.want, got); diff != "" {
   251  				t.Errorf("Tags mismatching. Want(-), got(+):\n%s", diff)
   252  			}
   253  		})
   254  	}
   255  }
   256  
   257  func TestGitTag(t *testing.T) {
   258  	tests := []struct {
   259  		name    string
   260  		date    string
   261  		gitHash string
   262  		cmdErr  error
   263  		want    string
   264  		wantErr bool
   265  	}{
   266  		{
   267  			name:    "base",
   268  			date:    "20220222",
   269  			gitHash: "a1b2c3d4",
   270  			want:    "20220222-a1b2c3d4",
   271  		},
   272  		{
   273  			name:    "err",
   274  			date:    "20220222",
   275  			gitHash: "a1b2c3d4",
   276  			cmdErr:  errors.New("error for test"),
   277  			want:    "",
   278  			wantErr: true,
   279  		},
   280  	}
   281  
   282  	for _, tc := range tests {
   283  		tc := tc
   284  		t.Run(tc.name, func(t *testing.T) {
   285  			oldRunCmdInDirFunc := runCmdInDirFunc
   286  			runCmdInDirFunc = func(dir string, additionalEnv []string, cmd string, args ...string) (string, error) {
   287  				switch cmd {
   288  				case "date":
   289  					return tc.date, tc.cmdErr
   290  				case "git":
   291  					return tc.gitHash, tc.cmdErr
   292  				default:
   293  					return "", errors.New("not supported command")
   294  				}
   295  			}
   296  			defer func() {
   297  				runCmdInDirFunc = oldRunCmdInDirFunc
   298  			}()
   299  
   300  			got, gotErr := gitTag()
   301  			if (gotErr != nil && !tc.wantErr) || (gotErr == nil && tc.wantErr) {
   302  				t.Fatalf("Error mismatch. Want: %v, got: %v", tc.wantErr, gotErr)
   303  			}
   304  			if want, got := strings.TrimSpace(tc.want), strings.TrimSpace(got); want != got {
   305  				t.Fatalf("Output mismatch. Want: %q, got: %q", want, got)
   306  			}
   307  		})
   308  	}
   309  }
   310  
   311  func TestBuildAndPush(t *testing.T) {
   312  	date, gitHash := "20220222", "a1b2c3d4"
   313  
   314  	tests := []struct {
   315  		name         string
   316  		id           imageDef
   317  		koDockerRepo string
   318  		push         bool
   319  		want         []string
   320  		wantErr      bool
   321  	}{
   322  		{
   323  			name: "base",
   324  			id: imageDef{
   325  				Dir:  "cmd/awesome",
   326  				Arch: "linux/amd64",
   327  			},
   328  			koDockerRepo: "local.test",
   329  			want: []string{
   330  				"publish",
   331  				"--tarball=_bin/awesome.tar",
   332  				"--push=false",
   333  				"--tags=latest",
   334  				"--tags=latest-root",
   335  				"--tags=20220222-a1b2c3d4",
   336  				"--tags=ko-20220222-a1b2c3d4",
   337  				"--base-import-paths",
   338  				"--platform=linux/amd64",
   339  				"./cmd/awesome",
   340  			},
   341  		},
   342  		{
   343  			name: "push",
   344  			id: imageDef{
   345  				Dir:  "cmd/awesome",
   346  				Arch: "linux/amd64",
   347  			},
   348  			koDockerRepo: "local.test",
   349  			push:         true,
   350  			want: []string{
   351  				"publish",
   352  				"--push=true",
   353  				"--tags=latest",
   354  				"--tags=latest-root",
   355  				"--tags=20220222-a1b2c3d4",
   356  				"--tags=ko-20220222-a1b2c3d4",
   357  				"--base-import-paths",
   358  				"--platform=linux/amd64",
   359  				"./cmd/awesome",
   360  			},
   361  		},
   362  		{
   363  			name: "all",
   364  			id: imageDef{
   365  				Dir:  "cmd/awesome",
   366  				Arch: "all",
   367  			},
   368  			koDockerRepo: "local.test",
   369  			push:         true,
   370  			want: []string{
   371  				"publish",
   372  				"--push=true",
   373  				"--tags=latest",
   374  				"--tags=latest-root",
   375  				"--tags=20220222-a1b2c3d4",
   376  				"--tags=ko-20220222-a1b2c3d4",
   377  				"--tags=latest-arm64",
   378  				"--tags=latest-root-arm64",
   379  				"--tags=20220222-a1b2c3d4-arm64",
   380  				"--tags=ko-20220222-a1b2c3d4-arm64",
   381  				"--tags=latest-s390x",
   382  				"--tags=latest-root-s390x",
   383  				"--tags=20220222-a1b2c3d4-s390x",
   384  				"--tags=ko-20220222-a1b2c3d4-s390x",
   385  				"--tags=latest-ppc64le",
   386  				"--tags=latest-root-ppc64le",
   387  				"--tags=20220222-a1b2c3d4-ppc64le",
   388  				"--tags=ko-20220222-a1b2c3d4-ppc64le",
   389  				"--base-import-paths",
   390  				"--platform=all",
   391  				"./cmd/awesome",
   392  			},
   393  		},
   394  		{
   395  			name: "unsupported-arch",
   396  			id: imageDef{
   397  				Dir:  "cmd/awesome",
   398  				Arch: "not/supported",
   399  			},
   400  			koDockerRepo: "local.test",
   401  			wantErr:      true,
   402  		},
   403  	}
   404  
   405  	for _, tc := range tests {
   406  		tc := tc
   407  		t.Run(tc.name, func(t *testing.T) {
   408  			var gotPublishArgs []string
   409  
   410  			oldRunCmdInDirFunc := runCmdInDirFunc
   411  			runCmdInDirFunc = func(dir string, additionalEnv []string, cmd string, args ...string) (string, error) {
   412  				switch cmd {
   413  				case "date":
   414  					return date, nil
   415  				case "git":
   416  					return gitHash, nil
   417  				case "_bin/ko":
   418  					gotPublishArgs = args
   419  					return fmt.Sprintf("cmd: %s, args: %v", cmd, args), nil
   420  				default:
   421  					return "", errors.New("not supported command")
   422  				}
   423  			}
   424  			defer func() {
   425  				runCmdInDirFunc = oldRunCmdInDirFunc
   426  			}()
   427  
   428  			err := buildAndPush(&tc.id, []string{tc.koDockerRepo}, tc.push)
   429  			if !tc.wantErr && err != nil {
   430  				t.Fatalf("Expect error but got nil")
   431  			}
   432  			if tc.wantErr {
   433  				if err == nil {
   434  					t.Fatalf("Failed unexpected: %v", err)
   435  				}
   436  				return
   437  			}
   438  
   439  			if diff := cmp.Diff(tc.want, gotPublishArgs); diff != "" {
   440  				t.Fatalf("Command mismatch. Want(-), got(+):\n%s", diff)
   441  			}
   442  		})
   443  	}
   444  }